</prerequisites>
<properties>
+ <aopalliance.version>1.0.0</aopalliance.version>
+ <appauth.version>0.4.2-SNAPSHOT</appauth.version>
+ <!-- Controller Modules Versions -->
<arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
+ <!-- Plugin Versions -->
+ <bouncycastle.version>1.50</bouncycastle.version>
<bundle.plugin.version>2.3.7</bundle.plugin.version>
<bundlescanner.version>0.4.2-SNAPSHOT</bundlescanner.version>
<checkstyle.version>2.10</checkstyle.version>
<clustering.services.version>0.5.1-SNAPSHOT</clustering.services.version>
<clustering.services_implementation.version>0.4.3-SNAPSHOT</clustering.services_implementation.version>
<clustering.stub.version>0.4.2-SNAPSHOT</clustering.stub.version>
+ <clustering.test.version>0.4.2-SNAPSHOT</clustering.test.version>
+ <commmons.northbound.version>0.4.2-SNAPSHOT</commmons.northbound.version>
+ <!-- Third Party Versions -->
+ <commons.codec.version>1.7</commons.codec.version>
+ <commons.fileupload.version>1.2.2</commons.fileupload.version>
<commons.httpclient.version>0.1.2-SNAPSHOT</commons.httpclient.version>
<commons.io.version>2.4</commons.io.version>
<commons.lang.version>3.1</commons.lang.version>
+ <commons.net.version>3.0.1</commons.net.version>
<compiler.version>2.3.2</compiler.version>
<concepts.version>0.5.2-SNAPSHOT</concepts.version>
<config.version>0.2.5-SNAPSHOT</config.version>
+ <configuration.implementation.version>0.4.3-SNAPSHOT</configuration.implementation.version>
<configuration.version>0.4.3-SNAPSHOT</configuration.version>
<connectionmanager.version>0.1.2-SNAPSHOT</connectionmanager.version>
<containermanager.it.version>0.5.2-SNAPSHOT</containermanager.it.version>
+ <containermanager.northbound.version>0.4.2-SNAPSHOT</containermanager.northbound.version>
<containermanager.version>0.5.2-SNAPSHOT</containermanager.version>
- <!--versions for bits of the controller -->
+ <controllermanager.northbound.version>0.0.2-SNAPSHOT</controllermanager.northbound.version>
<corsfilter.version>7.0.42</corsfilter.version>
+ <devices.web.version>0.4.2-SNAPSHOT</devices.web.version>
+ <eclipse.persistence.version>2.5.0</eclipse.persistence.version>
<!-- enforcer version -->
<enforcer.version>1.3.1</enforcer.version>
<enunciate.version>1.26.2</enunciate.version>
<exam.version>3.0.0</exam.version>
<!-- OpenEXI third party lib for netconf-->
- <exi.nagasena.version>0000.0002.0035.0-SNAPSHOT</exi.nagasena.version>
+ <exi.nagasena.version>0000.0002.0038.0-SNAPSHOT</exi.nagasena.version>
<failsafe.version>2.15</failsafe.version>
+ <felix.dependencymanager.shell.version>3.0.1</felix.dependencymanager.shell.version>
+ <felix.dependencymanager.version>3.1.0</felix.dependencymanager.version>
+ <felix.fileinstall.version>3.1.6</felix.fileinstall.version>
+ <felix.webconsole.version>4.2.0</felix.webconsole.version>
+ <flowprogrammer.northbound.version>0.4.2-SNAPSHOT</flowprogrammer.northbound.version>
+ <flows.web.version>0.4.2-SNAPSHOT</flows.web.version>
<forwarding.staticrouting>0.5.2-SNAPSHOT</forwarding.staticrouting>
+ <forwarding.staticrouting.northbound.version>0.4.2-SNAPSHOT</forwarding.staticrouting.northbound.version>
+ <forwardingrulesmanager.implementation.version>0.4.2-SNAPSHOT</forwardingrulesmanager.implementation.version>
<forwardingrulesmanager.version>0.6.0-SNAPSHOT</forwardingrulesmanager.version>
<geminiweb.version>2.2.0.RELEASE</geminiweb.version>
+ <gson.version>2.2.4</gson.version>
<guava.version>14.0.1</guava.version>
<hosttracker.api.version>0.5.2-SNAPSHOT</hosttracker.api.version>
<hosttracker.implementation.version>0.5.2-SNAPSHOT</hosttracker.implementation.version>
+ <hosttracker.northbound.version>0.4.2-SNAPSHOT</hosttracker.northbound.version>
<hosttracker_new.api.version>0.4.2-SNAPSHOT</hosttracker_new.api.version>
<ietf-inet-types.version>2010.09.24.4-SNAPSHOT</ietf-inet-types.version>
<ietf-topology.version>2013.10.21.2-SNAPSHOT</ietf-topology.version>
<!-- Third party version -->
<jersey-servlet.version>1.17</jersey-servlet.version>
<jersey.version>1.17</jersey.version>
+ <jettison.version>1.3.3</jettison.version>
<jmxGeneratorPath>src/main/yang-gen-config</jmxGeneratorPath>
<jolokia.version>1.1.4</jolokia.version>
+ <jsr305.api.version>2.0.1</jsr305.api.version>
+ <jsr311.api.version>1.1.1</jsr311.api.version>
<junit.version>4.8.1</junit.version>
<logback.version>1.0.9</logback.version>
+ <logging.bridge.version>0.4.2-SNAPSHOT</logging.bridge.version>
<maven.compile.plugin.version>2.5.1</maven.compile.plugin.version>
<!-- Java Versions -->
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<mdsal.version>1.1-SNAPSHOT</mdsal.version>
+ <mockito.version>1.9.5</mockito.version>
<netconf.version>0.2.5-SNAPSHOT</netconf.version>
<netty.version>4.0.17.Final</netty.version>
<networkconfig.bridgedomain.northbound.version>0.0.3-SNAPSHOT</networkconfig.bridgedomain.northbound.version>
+ <networkconfig.neutron.implementation.version>0.4.2-SNAPSHOT</networkconfig.neutron.implementation.version>
+ <networkconfig.neutron.northbound.version>0.4.2-SNAPSHOT</networkconfig.neutron.northbound.version>
+ <networkconfig.neutron.version>0.4.2-SNAPSHOT</networkconfig.neutron.version>
<!-- ODL repository / plugin repository -->
<nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
<opendaylight-l2-types.version>2013.08.27.4-SNAPSHOT</opendaylight-l2-types.version>
+ <osgi-brandfragment.web.version>0.0.2-SNAPSHOT</osgi-brandfragment.web.version>
+ <osgi.compendium.version>5.0.0</osgi.compendium.version>
<osgi.core.version>5.0.0</osgi.core.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<projectinfo>2.6</projectinfo>
-
<propertymavenplugin.version>1.0-alpha-2</propertymavenplugin.version>
<protocol-framework.version>0.5.0-SNAPSHOT</protocol-framework.version>
- <protocol_plugin.stub.version>0.4.2-SNAPSHOT</protocol_plugin.stub.version>
+ <protocol_plugins.openflow.version>0.4.2-SNAPSHOT</protocol_plugins.openflow.version>
+ <protocol_plugins.stub.version>0.4.2-SNAPSHOT</protocol_plugins.stub.version>
<releaseplugin.version>2.3.2</releaseplugin.version>
+ <routing.dijkstra_implementation.version>0.4.2-SNAPSHOT</routing.dijkstra_implementation.version>
<sal.connection.version>0.1.2-SNAPSHOT</sal.connection.version>
+ <sal.implementation.version>0.4.2-SNAPSHOT</sal.implementation.version>
<sal.networkconfiguration.version>0.0.3-SNAPSHOT</sal.networkconfiguration.version>
<sal.version>0.8.1-SNAPSHOT</sal.version>
<salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
<samples.loadbalancer>0.5.2-SNAPSHOT</samples.loadbalancer>
+ <samples.loadbalancer.northbound.version>0.4.2-SNAPSHOT</samples.loadbalancer.northbound.version>
+ <samples.simpleforwarding.version>0.4.2-SNAPSHOT</samples.simpleforwarding.version>
<sanitytest.version>0.4.2-SNAPSHOT</sanitytest.version>
+ <security.version>0.4.2-SNAPSHOT</security.version>
<sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
<siteplugin>3.2</siteplugin>
<slf4j.version>1.7.2</slf4j.version>
<spring-osgi.version>1.2.1</spring-osgi.version>
<spring-security.version>3.1.3.RELEASE</spring-security.version>
<spring.version>3.1.3.RELEASE</spring.version>
+ <statistics.northbound.version>0.4.2-SNAPSHOT</statistics.northbound.version>
+ <statisticsmanager.implementation.version>0.4.2-SNAPSHOT</statisticsmanager.implementation.version>
<statisticsmanager.version>0.5.1-SNAPSHOT</statisticsmanager.version>
+ <subnets.northbound.version>0.4.2-SNAPSHOT</subnets.northbound.version>
<surefire.version>2.15</surefire.version>
<switchmanager.api.version>0.7.1-SNAPSHOT</switchmanager.api.version>
+ <switchmanager.implementation.version>0.4.2-SNAPSHOT</switchmanager.implementation.version>
+ <switchmanager.northbound.version>0.4.2-SNAPSHOT</switchmanager.northbound.version>
<testvm.argLine>-Xmx1024m -XX:MaxPermSize=256m</testvm.argLine>
+ <topology.northbound.version>0.4.2-SNAPSHOT</topology.northbound.version>
+ <topology.web.version>0.4.2-SNAPSHOT</topology.web.version>
<topologymanager.version>0.4.2-SNAPSHOT</topologymanager.version>
+ <troubleshoot.web.version>0.4.2-SNAPSHOT</troubleshoot.web.version>
<url.version>1.5.0</url.version>
+ <usermanager.implementation.version>0.4.2-SNAPSHOT</usermanager.implementation.version>
+ <usermanager.northbound.version>0.0.2-SNAPSHOT</usermanager.northbound.version>
<usermanager.version>0.4.2-SNAPSHOT</usermanager.version>
<virgo.version>3.6.0.RELEASE</virgo.version>
+ <web.version>0.4.2-SNAPSHOT</web.version>
<xtend.dstdir>src/main/xtend-gen</xtend.dstdir>
<xtend.version>2.4.3</xtend.version>
<yang-ext.version>2013.09.07.4-SNAPSHOT</yang-ext.version>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson.version}</version>
</dependency>
-
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
- <version>2.0.1</version>
+ <version>${jsr305.api.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
- <version>2.2.4</version>
+ <version>${gson.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>jersey-core</artifactId>
<version>${jersey.version}</version>
</dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>jsr311-api</artifactId>
+ <version>${jsr311.api.version}</version>
+ </dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
- <version>1.7</version>
+ <version>${commons.codec.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
- <version>1.2.2</version>
+ <version>${commons.fileupload.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
- <version>3.0.1</version>
+ <version>${commons.net.version}</version>
</dependency>
<dependency>
<groupId>eclipselink</groupId>
<artifactId>netty-common</artifactId>
<version>${netty.version}</version>
</dependency>
-
- <!--Netty-->
+ <!-- Netty -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<dependency>
<groupId>org.aopalliance</groupId>
<artifactId>com.springsource.org.aopalliance</artifactId>
- <version>1.0.0</version>
+ <version>${aopalliance.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.dependencymanager</artifactId>
- <version>3.1.0</version>
+ <version>${felix.dependencymanager.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.dependencymanager.shell</artifactId>
- <version>3.0.1</version>
+ <version>${felix.dependencymanager.shell.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.fileinstall</artifactId>
- <version>3.1.6</version>
+ <version>${felix.fileinstall.version}</version>
</dependency>
<!-- felix webconsole -->
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.webconsole</artifactId>
- <version>4.2.0</version>
+ <version>${felix.webconsole.version}</version>
<!-- the all bundle includes all the necessary plugins -->
<classifier>all</classifier>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
- <version>1.50</version>
+ <version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
- <version>1.50</version>
+ <version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.enunciate</groupId>
<artifactId>enunciate-core-annotations</artifactId>
<version>${enunciate.version}</version>
</dependency>
-
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
- <version>1.3.3</version>
+ <version>${jettison.version}</version>
</dependency>
<!-- equinox http service bridge -->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.antlr</artifactId>
- <version>2.5.0</version>
+ <version>${eclipse.persistence.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
- <version>2.5.0</version>
+ <version>${eclipse.persistence.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
- <version>2.5.0</version>
+ <version>${eclipse.persistence.version}</version>
</dependency>
<!-- md-sal -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>appauth</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${appauth.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.test</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${clustering.test.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${commmons.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>configuration.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${configuration.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>containermanager.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${containermanager.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>controllermanager.northbound</artifactId>
- <version>0.0.2-SNAPSHOT</version>
+ <version>${controllermanager.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>devices.web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${devices.web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>flowprogrammer.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${flowprogrammer.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>flows.web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${flows.web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwarding.staticrouting.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${forwarding.staticrouting.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwardingrulesmanager.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${forwardingrulesmanager.implementation.version}</version>
</dependency>
<dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${hosttracker.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>logging.bridge</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${logging.bridge.version}</version>
</dependency>
<!-- Netconf -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>networkconfig.neutron</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${networkconfig.neutron.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>networkconfig.neutron.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${networkconfig.neutron.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>networkconfig.neutron.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${networkconfig.neutron.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>osgi-brandfragment.web</artifactId>
- <version>0.0.2-SNAPSHOT</version>
+ <version>${osgi-brandfragment.web.version}</version>
</dependency>
<dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>protocol_plugins.openflow</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${protocol_plugins.openflow.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>protocol_plugins.stub</artifactId>
- <version>${protocol_plugin.stub.version}</version>
+ <version>${protocol_plugins.stub.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>routing.dijkstra_implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${routing.dijkstra_implementation.version}</version>
</dependency>
<!-- SAL bundles -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${sal.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>samples.loadbalancer.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${samples.loadbalancer.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>samples.simpleforwarding</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${samples.simpleforwarding.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>security</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${security.version}</version>
</dependency>
<dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>statistics.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${statistics.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>statisticsmanager.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${statisticsmanager.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>subnets.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${subnets.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager.implementation</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${switchmanager.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${switchmanager.northbound.version}</version>
</dependency>
<!-- threadpool -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>topology.northbound</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${topology.northbound.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>topology.web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${topology.web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>troubleshoot.web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${troubleshoot.web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>usermanager.implementation</artifactId>
- <version>${usermanager.version}</version>
+ <version>${usermanager.implementation.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>usermanager.northbound</artifactId>
- <version>0.0.2-SNAPSHOT</version>
+ <version>${usermanager.northbound.version}</version>
</dependency>
<!-- Web bundles -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>web</artifactId>
- <version>0.4.2-SNAPSHOT</version>
+ <version>${web.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
- <version>${osgi.core.version}</version>
+ <version>${osgi.compendium.version}</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>${mockito.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.logback_settings</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-it</artifactId>
+ <version>${mdsal.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>mockito-configuration</artifactId>
<artifactId>yang-maven-plugin</artifactId>
<version>${yangtools.version}</version>
<dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <type>jar</type>
+ </dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
*/
package org.opendaylight.controller.config.yang.protocol.framework;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
public class NeverReconnectStrategyModuleTest extends AbstractConfigTest {
private static final String INSTANCE_NAME = "never-reconect-strategy-factory-impl";
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new NeverReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory()));
}
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new ReconnectImmediatelyStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory()));
}
*/
package org.opendaylight.controller.config.yang.protocol.framework;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.math.BigDecimal;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+import java.math.BigDecimal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
public class TimedReconnectStrategyModuleTest extends AbstractConfigTest {
private static final String INSTANCE_NAME = "timed-reconect-stategy-facotry-impl";
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TimedReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory()));
}
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+/**
+ * Interface exposing some internal state on top of ServiceReferenceReadableRegistry. This will
+ * not be exposed via JMX.
+ */
public interface CloseableServiceReferenceReadableRegistry extends AutoCloseable, ServiceReferenceReadableRegistry {
-
void close();
}
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
-import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.dependencyresolver.DestroyedModule;
}
};
- Map<String, Map.Entry<ModuleFactory, BundleContext>> allCurrentFactories = Collections.unmodifiableMap(
+ Map<String, Map.Entry<ModuleFactory, BundleContext>> allCurrentFactories = new HashMap<>(
resolver.getAllFactories());
+ // add all factories that disappeared from SR but are still committed
+ for (ModuleInternalInfo moduleInternalInfo : currentConfig.getEntries()) {
+ String name = moduleInternalInfo.getModuleFactory().getImplementationName();
+ if (allCurrentFactories.containsKey(name) == false) {
+ logger.trace("Factory {} not found in SR, using reference from previous commit", name);
+ allCurrentFactories.put(name,
+ Maps.immutableEntry(moduleInternalInfo.getModuleFactory(), moduleInternalInfo.getBundleContext()));
+ }
+ }
+ allCurrentFactories = Collections.unmodifiableMap(allCurrentFactories);
+
// closed by transaction controller
ConfigTransactionLookupRegistry txLookupRegistry = new ConfigTransactionLookupRegistry(new TransactionIdentifier(
transactionName), factory, allCurrentFactories);
- ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
+ SearchableServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
readableSRRegistry, txLookupRegistry, allCurrentFactories);
ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
// non recoverable from here:
try {
return secondPhaseCommit(configTransactionController, commitInfo, configTransactionControllerEntry.getValue());
- } catch (Throwable t) { // some libs throw Errors: e.g.
+ } catch (Error | RuntimeException t) { // some libs throw Errors: e.g.
// javax.xml.ws.spi.FactoryFinder$ConfigurationError
isHealthy = false;
logger.error("Configuration Transaction failed on 2PC, server is unhealthy", t);
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
- } else if (t instanceof Error) {
- throw (Error) t;
} else {
- throw new RuntimeException(t);
+ throw (Error) t;
}
}
}
// register to JMX
try {
- newModuleJMXRegistrator.registerMBean(newReadableConfigBean,
- primaryReadOnlyON);
+ newModuleJMXRegistrator.registerMBean(newReadableConfigBean, primaryReadOnlyON);
} catch (InstanceAlreadyExistsException e) {
- throw new IllegalStateException(e);
+ throw new IllegalStateException("Possible code error, already registered:" + primaryReadOnlyON,e);
}
- // register to OSGi
+ // register services to OSGi
+ Map<String, ServiceInterfaceAnnotation> annotationMapping = configTransactionController.getWritableRegistry().findServiceInterfaces(moduleIdentifier);
+ BundleContext bc = configTransactionController.getModuleFactoryBundleContext(
+ entry.getModuleFactory().getImplementationName());
if (osgiRegistration == null) {
- ModuleFactory moduleFactory = entry.getModuleFactory();
- if (moduleFactory != null) {
- BundleContext bc = configTransactionController.
- getModuleFactoryBundleContext(moduleFactory.getImplementationName());
- osgiRegistration = beanToOsgiServiceManager.registerToOsgi(realModule.getClass(),
- newReadableConfigBean.getInstance(), entry.getIdentifier(), bc);
- } else {
- throw new NullPointerException(entry.getIdentifier().getFactoryName() + " ModuleFactory not found.");
- }
-
+ osgiRegistration = beanToOsgiServiceManager.registerToOsgi(
+ newReadableConfigBean.getInstance(), moduleIdentifier, bc, annotationMapping);
+ } else {
+ osgiRegistration.updateRegistrations(annotationMapping, bc, instance);
}
RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator = runtimeRegistrators
ModuleInternalInfo newInfo = new ModuleInternalInfo(
entry.getIdentifier(), newReadableConfigBean, osgiRegistration,
runtimeBeanRegistrator, newModuleJMXRegistrator,
- orderingIdx, entry.isDefaultBean());
+ orderingIdx, entry.isDefaultBean(), entry.getModuleFactory(), entry.getBundleContext());
newConfigEntries.put(realModule, newInfo);
orderingIdx++;
*/
package org.opendaylight.controller.config.manager.impl;
+import static java.lang.String.format;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.DynamicMBean;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.DynamicMBean;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-
import static com.google.common.base.Preconditions.checkNotNull;
-import static java.lang.String.format;
-
/**
* This is a JMX bean representing current transaction. It contains
* transaction identifier, unique version and parent version for
private final boolean blankTransaction;
@GuardedBy("this")
- private final ServiceReferenceWritableRegistry writableSRRegistry;
+ private final SearchableServiceReferenceWritableRegistry writableSRRegistry;
public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
long parentVersion, CodecRegistry codecRegistry, long currentVersion,
Map<String, Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
- boolean blankTransaction, ServiceReferenceWritableRegistry writableSRRegistry) {
+ boolean blankTransaction, SearchableServiceReferenceWritableRegistry writableSRRegistry) {
this.txLookupRegistry = txLookupRegistry;
String transactionName = txLookupRegistry.getTransactionIdentifier().getName();
this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName);
}
// add default modules
for (ModuleFactory moduleFactory : toBeAdded) {
+ BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager,
- getModuleFactoryBundleContext(moduleFactory.getImplementationName()));
+ bundleContext);
for (Module module : defaultModules) {
// ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
try {
boolean defaultBean = true;
- putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver, defaultBean);
+ putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null,
+ dependencyResolver, defaultBean, bundleContext);
} catch (InstanceAlreadyExistsException e) {
throw new IllegalStateException(e);
}
}
- private synchronized void copyExistingModule(
- ModuleInternalInfo oldConfigBeanInfo)
- throws InstanceAlreadyExistsException {
+ private synchronized void copyExistingModule(ModuleInternalInfo oldConfigBeanInfo) throws InstanceAlreadyExistsException {
+
transactionStatus.checkNotCommitStarted();
transactionStatus.checkNotAborted();
ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getIdentifier();
dependencyResolverManager.assertNotExists(moduleIdentifier);
- ModuleFactory moduleFactory = factoriesHolder
- .findByModuleName(moduleIdentifier.getFactoryName());
+ ModuleFactory moduleFactory;
+ BundleContext bc;
+ try {
+ moduleFactory = factoriesHolder.findByModuleName(moduleIdentifier.getFactoryName());
+ bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
+ } catch (InstanceNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
Module module;
DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
try {
- BundleContext bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
+
module = moduleFactory.createModule(
moduleIdentifier.getInstanceName(), dependencyResolver,
oldConfigBeanInfo.getReadableModule(), bc);
oldConfigBeanInfo, moduleFactory), e);
}
putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver,
- oldConfigBeanInfo.isDefaultBean());
+ oldConfigBeanInfo.isDefaultBean(), bc);
}
@Override
dependencyResolverManager.assertNotExists(moduleIdentifier);
// find factory
- ModuleFactory moduleFactory = factoriesHolder.findByModuleName(factoryName);
+ ModuleFactory moduleFactory;
+ try {
+ moduleFactory = factoriesHolder.findByModuleName(factoryName);
+ } catch (InstanceNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ }
DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
+ BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
Module module = moduleFactory.createModule(instanceName, dependencyResolver,
- getModuleFactoryBundleContext(moduleFactory.getImplementationName()));
+ bundleContext);
boolean defaultBean = false;
return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
- moduleFactory, null, dependencyResolver, defaultBean);
+ moduleFactory, null, dependencyResolver, defaultBean, bundleContext);
}
private synchronized ObjectName putConfigBeanToJMXAndInternalMaps(
ModuleIdentifier moduleIdentifier, Module module,
ModuleFactory moduleFactory,
- @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver, boolean isDefaultBean)
+ @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver,
+ boolean isDefaultBean, BundleContext bundleContext)
throws InstanceAlreadyExistsException {
logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
dependencyResolverManager.put(
moduleIdentifier, module, moduleFactory,
- maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean);
+ maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean, bundleContext);
return writableON;
}
logger.debug("Destroying module {} in transaction {}", moduleIdentifier, this);
transactionStatus.checkNotAborted();
+ ModuleInternalTransactionalInfo found = dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier);
if (blankTransaction == false) {
- ModuleInternalTransactionalInfo found =
- dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier);
+
if (found.isDefaultBean()) {
logger.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem");
}
}
// first remove refNames, it checks for objectname existence
+
try {
writableSRRegistry.removeServiceReferences(
ObjectNameUtil.createTransactionModuleON(getTransactionName(), moduleIdentifier));
}
@Override
- public ServiceReferenceWritableRegistry getWritableRegistry() {
+ public SearchableServiceReferenceWritableRegistry getWritableRegistry() {
return writableSRRegistry;
}
*/
package org.opendaylight.controller.config.manager.impl;
-import java.util.Collection;
-import java.util.List;
-
-import javax.management.ObjectName;
-
import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.osgi.framework.BundleContext;
+import javax.management.ObjectName;
+import java.util.Collection;
+import java.util.List;
+
/**
* Defines contract between {@link ConfigTransactionControllerImpl} (producer)
* and {@link ConfigRegistryImpl} (consumer).
BundleContext getModuleFactoryBundleContext(String factoryName);
- ServiceReferenceWritableRegistry getWritableRegistry();
+ SearchableServiceReferenceWritableRegistry getWritableRegistry();
TransactionIdentifier getTransactionIdentifier();
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
+import java.util.Deque;
+import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
public class DeadlockMonitor implements AutoCloseable {
private final TransactionIdentifier transactionIdentifier;
private final DeadlockMonitorRunnable thread;
@GuardedBy("this")
- private ModuleIdentifierWithNanos moduleIdentifierWithNanos = new ModuleIdentifierWithNanos();
+ private final Deque<ModuleIdentifierWithNanos> moduleIdentifierWithNanosStack = new LinkedList<>();
+ @GuardedBy("this")
+ private ModuleIdentifierWithNanos top = ModuleIdentifierWithNanos.EMPTY;
public DeadlockMonitor(TransactionIdentifier transactionIdentifier) {
this.transactionIdentifier = transactionIdentifier;
}
public synchronized void setCurrentlyInstantiatedModule(ModuleIdentifier currentlyInstantiatedModule) {
- this.moduleIdentifierWithNanos = new ModuleIdentifierWithNanos(currentlyInstantiatedModule);
+
+ boolean popping = currentlyInstantiatedModule == null;
+ if (popping) {
+ moduleIdentifierWithNanosStack.pop();
+ if (moduleIdentifierWithNanosStack.isEmpty()) {
+ top = ModuleIdentifierWithNanos.EMPTY;
+ } else {
+ top = moduleIdentifierWithNanosStack.peekLast();
+ }
+ } else {
+ ModuleIdentifierWithNanos current = new ModuleIdentifierWithNanos(currentlyInstantiatedModule);
+ moduleIdentifierWithNanosStack.push(current);
+ top = current;
+ }
+ logger.trace("setCurrentlyInstantiatedModule {}, top {}", currentlyInstantiatedModule, top);
}
public boolean isAlive() {
public void run() {
ModuleIdentifierWithNanos old = new ModuleIdentifierWithNanos(); // null moduleId
while (this.isInterrupted() == false) {
- ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.moduleIdentifierWithNanos);
- if (old.moduleIdentifier == null) {
+ ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.top);
+ if (old.moduleIdentifier == null || old.equals(copy) == false) {
// started
old = copy;
- } else if (old.moduleIdentifier != null && old.equals(copy)) {
+ } else {
// is the getInstance() running longer than WARN_AFTER_MILLIS ?
long runningTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - copy.nanoTime);
if (runningTime > WARN_AFTER_MILLIS) {
}
}
- private class ModuleIdentifierWithNanos {
+
+
+
+ private static class ModuleIdentifierWithNanos {
+ private static ModuleIdentifierWithNanos EMPTY = new ModuleIdentifierWithNanos();
@Nullable
private final ModuleIdentifier moduleIdentifier;
+
private final long nanoTime;
private ModuleIdentifierWithNanos() {
- moduleIdentifier = null;
- nanoTime = System.nanoTime();
+ this((ModuleIdentifier)null);
}
private ModuleIdentifierWithNanos(ModuleIdentifier moduleIdentifier) {
result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
return result;
}
+
+ @Override
+ public String toString() {
+ return "ModuleIdentifierWithNanos{" +
+ moduleIdentifier +
+ '}';
+ }
}
}
import org.opendaylight.controller.config.manager.impl.jmx.ModuleJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.RootRuntimeBeanRegistratorImpl;
import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceManager.OsgiRegistration;
+import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.concepts.Identifiable;
+import org.osgi.framework.BundleContext;
/**
* Provides metadata about Module from controller to registry.
private final ModuleJMXRegistrator moduleJMXRegistrator;
private final int orderingIdx;
private final boolean isDefaultBean;
+ private final ModuleFactory moduleFactory;
+ private final BundleContext bundleContext;
public ModuleInternalInfo(ModuleIdentifier name,
@Nullable DynamicReadableWrapper readableModule,
OsgiRegistration osgiRegistration,
RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator,
ModuleJMXRegistrator moduleJMXRegistrator, int orderingIdx,
- boolean isDefaultBean) {
+ boolean isDefaultBean, ModuleFactory moduleFactory, BundleContext bundleContext) {
if (osgiRegistration == null) {
throw new IllegalArgumentException(
this.moduleJMXRegistrator = moduleJMXRegistrator;
this.orderingIdx = orderingIdx;
this.isDefaultBean = isDefaultBean;
+ this.moduleFactory = moduleFactory;
+ this.bundleContext = bundleContext;
}
public DynamicReadableWrapper getReadableModule() {
public boolean isDefaultBean() {
return isDefaultBean;
}
+
+ public ModuleFactory getModuleFactory() {
+ return moduleFactory;
+ }
+
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
}
--- /dev/null
+/*
+ * 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.config.manager.impl;
+
+import java.util.Map;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
+
+public interface SearchableServiceReferenceWritableRegistry extends ServiceReferenceWritableRegistry {
+ /**
+ * Return mapping between service ref names and service interface annotation for given
+ * module.
+ *
+ * @throws java.lang.IllegalArgumentException if any of service qNames is not found
+ * @throws java.lang.NullPointerException if parameter is null
+ */
+ Map<String /* service ref */, ServiceInterfaceAnnotation> findServiceInterfaces(ModuleIdentifier moduleIdentifier);
+
+}
*/
package org.opendaylight.controller.config.manager.impl;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.api.LookupRegistry;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
+public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, SearchableServiceReferenceWritableRegistry {
private static final Logger logger = LoggerFactory.getLogger(ServiceReferenceRegistryImpl.class);
private final Map<String, ModuleFactory> factories;
private final ServiceReferenceRegistrator serviceReferenceRegistrator;
// helper method for getting QName of SI from namespace + local name
private final Map<String /* namespace */, Map<String /* local name */, ServiceInterfaceAnnotation>> namespacesToAnnotations;
+ private final Map<String /* service qName */, ServiceInterfaceAnnotation> serviceQNamesToAnnotations;
// all Service Interface qNames for sanity checking
private final Set<String /* qName */> allQNames;
+ Map<ModuleIdentifier, Map<String /* service ref name */, ServiceInterfaceAnnotation >> modulesToServiceRef = new HashMap<>();
+
// actual reference database
private final Map<ServiceReference, ModuleIdentifier> refNames = new HashMap<>();
/**
* Static constructor for transaction controller. Take current state as seen by config registry, allow writing new data.
*/
- public static ServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
+ public static SearchableServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
ConfigTransactionLookupRegistry txLookupRegistry,
Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
Map<String, Set<String /* QName */>> modifiableFactoryNamesToQNames = new HashMap<>();
Set<ServiceInterfaceAnnotation> allAnnotations = new HashSet<>();
Set<String /* qName */> allQNames = new HashSet<>();
+
+
for (Entry<String, ModuleFactory> entry : factories.entrySet()) {
if (entry.getKey().equals(entry.getValue().getImplementationName()) == false) {
logger.error("Possible error in code: Mismatch between supplied and actual name of {}", entry);
throw new IllegalArgumentException("Possible error in code: Mismatch between supplied and actual name of " + entry);
}
Set<ServiceInterfaceAnnotation> siAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(entry.getValue());
- Set<String> qNames = new HashSet<>();
- for (ServiceInterfaceAnnotation sia: siAnnotations) {
- qNames.add(sia.value());
- }
+ Set<String> qNames = InterfacesHelper.getQNames(siAnnotations);
allAnnotations.addAll(siAnnotations);
allQNames.addAll(qNames);
modifiableFactoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames));
// fill namespacesToAnnotations
Map<String /* namespace */, Map<String /* localName */, ServiceInterfaceAnnotation>> modifiableNamespacesToAnnotations =
new HashMap<>();
+ Map<String /* service qName*/, ServiceInterfaceAnnotation> modifiableServiceQNamesToAnnotations = new HashMap<>();
for (ServiceInterfaceAnnotation sia : allAnnotations) {
Map<String, ServiceInterfaceAnnotation> ofNamespace = modifiableNamespacesToAnnotations.get(sia.namespace());
if (ofNamespace == null) {
throw new IllegalArgumentException("Conflict between local names in " + sia.namespace() + " : " + sia.localName());
}
ofNamespace.put(sia.localName(), sia);
+ modifiableServiceQNamesToAnnotations.put(sia.value(), sia);
}
this.namespacesToAnnotations = Collections.unmodifiableMap(modifiableNamespacesToAnnotations);
- // copy refNames
+ this.serviceQNamesToAnnotations = Collections.unmodifiableMap(modifiableServiceQNamesToAnnotations);
logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames);
}
+ @Override
+ public Map<String /* service ref */, ServiceInterfaceAnnotation> findServiceInterfaces(ModuleIdentifier moduleIdentifier) {
+ Map<String, ServiceInterfaceAnnotation> result = modulesToServiceRef.get(moduleIdentifier);
+ if (result == null) {
+ return Collections.emptyMap();
+ }
+ return Collections.unmodifiableMap(result);
+ }
@Override
public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
public synchronized Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping() {
Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> result = new HashMap<>();
for (Entry<ServiceReference, ModuleIdentifier> entry: refNames.entrySet()) {
- String qName = entry.getKey().getServiceInterfaceName();
+ String qName = entry.getKey().getServiceInterfaceQName();
Map<String /* refName */, ObjectName> innerMap = result.get(qName);
if (innerMap == null) {
innerMap = new HashMap<>();
throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + moduleIdentifier.getFactoryName());
}
// supplied serviceInterfaceName must exist in this collection
- if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
- logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames);
- throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName() + " within factory " + moduleIdentifier.getFactoryName());
+ if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceQName()) == false) {
+ logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceQName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames);
+ throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceQName() + " within factory " + moduleIdentifier.getFactoryName());
}
}
// save to refNames
refNames.put(serviceReference, moduleIdentifier);
+ Map<String, ServiceInterfaceAnnotation> refNamesToAnnotations = modulesToServiceRef.get(moduleIdentifier);
+ if (refNamesToAnnotations == null){
+ refNamesToAnnotations = new HashMap<>();
+ modulesToServiceRef.put(moduleIdentifier, refNamesToAnnotations);
+ }
+
+ ServiceInterfaceAnnotation annotation = serviceQNamesToAnnotations.get(serviceReference.getServiceInterfaceQName());
+ checkNotNull(annotation, "Possible error in code, cannot find annotation for " + serviceReference);
+ refNamesToAnnotations.put(serviceReference.getRefName(), annotation);
return result;
}
private ObjectName getServiceON(ServiceReference serviceReference) {
if (writable) {
return ObjectNameUtil.createTransactionServiceON(serviceReferenceRegistrator.getNullableTransactionName(),
- serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
+ serviceReference.getServiceInterfaceQName(), serviceReference.getRefName());
} else {
- return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
+ return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceQName(), serviceReference.getRefName());
}
}
logger.debug("Removing service reference {} from {}", serviceReference, this);
assertWritable();
// is the qName known?
- if (allQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
- logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceName(), allQNames);
- throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName());
+ if (allQNames.contains(serviceReference.getServiceInterfaceQName()) == false) {
+ logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceQName(), allQNames);
+ throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceQName());
}
ModuleIdentifier removed = refNames.remove(serviceReference);
if (removed == null){
- throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceName());
+ throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceQName());
}
Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> entry = mBeans.remove(serviceReference);
if (entry == null) {
@Override
public synchronized boolean removeServiceReferences(ObjectName moduleObjectName) throws InstanceNotFoundException {
+ lookupRegistry.checkConfigBeanExists(moduleObjectName);
+ String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName);
+ // check that service interface name exist
+ Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
+ return removeServiceReferences(moduleObjectName, serviceInterfaceQNames);
+ }
+
+
+ private boolean removeServiceReferences(ObjectName moduleObjectName, Set<String> qNames) throws InstanceNotFoundException {
+ ObjectNameUtil.checkType(moduleObjectName, ObjectNameUtil.TYPE_MODULE);
assertWritable();
- Set<ServiceReference> serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName);
+ Set<ServiceReference> serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName, qNames);
for (ServiceReference sr : serviceReferencesLinkingTo) {
removeServiceReference(sr);
}
return serviceReferencesLinkingTo.isEmpty() == false;
}
- private synchronized Set<ServiceReference> findServiceReferencesLinkingTo(ObjectName moduleObjectName) throws InstanceNotFoundException {
- lookupRegistry.checkConfigBeanExists(moduleObjectName);
+ private Set<ServiceReference> findServiceReferencesLinkingTo(ObjectName moduleObjectName, Set<String> serviceInterfaceQNames) {
String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName);
- // check that service interface name exist
- Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
if (serviceInterfaceQNames == null) {
- logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName);
+ logger.warn("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName);
throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
}
String instanceName = ObjectNameUtil.getInstanceName(moduleObjectName);
return result;
}
-
@Override
public String toString() {
return "ServiceReferenceRegistryImpl{" +
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.reflect.AbstractInvocationHandler;
import com.google.common.reflect.Reflection;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.DependencyResolverFactory;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static com.google.common.base.Preconditions.checkState;
+import org.osgi.framework.BundleContext;
/**
* Holds information about modules being created and destroyed within this
ModuleFactory moduleFactory,
ModuleInternalInfo maybeOldInternalInfo,
TransactionModuleJMXRegistration transactionModuleJMXRegistration,
- boolean isDefaultBean) {
+ boolean isDefaultBean, BundleContext bundleContext) {
transactionStatus.checkNotCommitted();
Class<? extends Module> moduleClass = Module.class;
ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo(
moduleIdentifier, proxiedModule, moduleFactory,
- maybeOldInternalInfo, transactionModuleJMXRegistration, isDefaultBean, module);
+ maybeOldInternalInfo, transactionModuleJMXRegistration, isDefaultBean, module, bundleContext);
modulesHolder.put(moduleInternalTransactionalInfo);
}
import org.opendaylight.yangtools.concepts.Identifiable;
import javax.annotation.Nullable;
+import org.osgi.framework.BundleContext;
public class ModuleInternalTransactionalInfo implements Identifiable<ModuleIdentifier> {
private final ModuleIdentifier name;
private final ModuleInternalInfo maybeOldInternalInfo;
private final TransactionModuleJMXRegistration transactionModuleJMXRegistration;
private final boolean isDefaultBean;
+ private final BundleContext bundleContext;
public ModuleInternalTransactionalInfo(ModuleIdentifier name, Module proxiedModule,
ModuleFactory moduleFactory,
ModuleInternalInfo maybeOldInternalInfo,
TransactionModuleJMXRegistration transactionModuleJMXRegistration,
- boolean isDefaultBean, Module realModule) {
+ boolean isDefaultBean, Module realModule, BundleContext bundleContext) {
this.name = name;
this.proxiedModule = proxiedModule;
this.moduleFactory = moduleFactory;
this.transactionModuleJMXRegistration = transactionModuleJMXRegistration;
this.isDefaultBean = isDefaultBean;
this.realModule = realModule;
+ this.bundleContext = bundleContext;
}
public Module getRealModule() {
return realModule;
}
+
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
}
package org.opendaylight.controller.config.manager.impl.factoriesresolver;
-import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.osgi.framework.BundleContext;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
+import javax.management.InstanceNotFoundException;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.BundleContext;
/**
* Hold sorted ConfigMBeanFactories by their module names. Check that module
* @throws IllegalArgumentException
* if factory is not found
*/
- public ModuleFactory findByModuleName(String moduleName) {
+ public ModuleFactory findByModuleName(String moduleName) throws InstanceNotFoundException {
Map.Entry<ModuleFactory, BundleContext> result = moduleNamesToConfigBeanFactories.get(moduleName);
if (result == null) {
- throw new IllegalArgumentException(
+ throw new InstanceNotFoundException(
"ModuleFactory not found with module name: " + moduleName);
}
return result.getKey();
return moduleFactories;
}
- public Map<String, Entry<ModuleFactory, BundleContext>> getModuleNamesToConfigBeanFactories() {
- return moduleNamesToConfigBeanFactories;
- }
}
this.refName = refName;
}
- public String getServiceInterfaceName() {
+ public String getServiceInterfaceQName() {
return serviceInterfaceName;
}
result = 31 * result + refName.hashCode();
return result;
}
+
+ @Override
+ public String toString() {
+ return "ServiceReference{" +
+ "serviceInterfaceName='" + serviceInterfaceName + '\'' +
+ ", refName='" + refName + '\'' +
+ '}';
+ }
}
*/
package org.opendaylight.controller.config.manager.impl.osgi;
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
-import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
-import org.opendaylight.controller.config.spi.Module;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
+import static com.google.common.base.Preconditions.checkState;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Registers instantiated beans as OSGi services and unregisters these services
* if beans are destroyed.
*/
public class BeanToOsgiServiceManager {
- // name of properties submitted to osgi
- static final String INSTANCE_NAME_OSGI_PROP = "instanceName";
- static final String IMPLEMENTATION_NAME_OSGI_PROP = "implementationName";
+ private static final String SERVICE_NAME_OSGI_PROP = "name";
/**
* To be called for every created, reconfigured and recreated config bean.
* It is expected that before using this method OSGi service registry will
* be cleaned from previous registrations.
*/
- public OsgiRegistration registerToOsgi(
- Class<? extends Module> configBeanClass, AutoCloseable instance,
- ModuleIdentifier moduleIdentifier, BundleContext bundleContext) {
- try {
- final Set<Class<?>> configuresInterfaces = InterfacesHelper
- .getOsgiRegistrationTypes(configBeanClass);
- checkInstanceImplementing(instance, configuresInterfaces);
-
- // bundleContext.registerService blows up with empty 'clazzes'
- if (configuresInterfaces.isEmpty() == false) {
- final Dictionary<String, ?> propertiesForOsgi = getPropertiesForOsgi(moduleIdentifier);
- final ServiceRegistration<?> serviceRegistration = bundleContext
- .registerService(classesToNames(configuresInterfaces), instance, propertiesForOsgi);
- return new OsgiRegistration(serviceRegistration);
- } else {
- return new OsgiRegistration();
- }
- } catch (IllegalStateException e) {
- throw new IllegalStateException(
- "Error while registering instance into OSGi Service Registry: "
- + moduleIdentifier, e);
- }
+ public OsgiRegistration registerToOsgi(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
+ BundleContext bundleContext,
+ Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+ return new OsgiRegistration(instance, moduleIdentifier, bundleContext, serviceNamesToAnnotations);
}
- private static String[] classesToNames(Set<Class<?>> cfgs) {
- String[] result = new String[cfgs.size()];
- int i = 0;
- for (Class<?> cfg : cfgs) {
- result[i] = cfg.getName();
- i++;
- }
+ private static Dictionary<String, String> createProps(String serviceName) {
+ Hashtable<String, String> result = new Hashtable<>();
+ result.put(SERVICE_NAME_OSGI_PROP, serviceName);
return result;
}
- private void checkInstanceImplementing(AutoCloseable instance,
- Set<Class<?>> configures) {
- Set<Class<?>> missing = new HashSet<>();
- for (Class<?> requiredIfc : configures) {
- if (requiredIfc.isInstance(instance) == false) {
- missing.add(requiredIfc);
- }
- }
- if (missing.isEmpty() == false) {
- throw new IllegalStateException(
- instance.getClass()
- + " does not implement following interfaces as announced by "
- + ServiceInterfaceAnnotation.class.getName()
- + " annotation :" + missing);
- }
- }
-
- private static Dictionary<String, ?> getPropertiesForOsgi(
- ModuleIdentifier moduleIdentifier) {
- Hashtable<String, String> table = new Hashtable<>();
- table.put(IMPLEMENTATION_NAME_OSGI_PROP,
- moduleIdentifier.getFactoryName());
- table.put(INSTANCE_NAME_OSGI_PROP, moduleIdentifier.getInstanceName());
- return table;
- }
public static class OsgiRegistration implements AutoCloseable {
- private final ServiceRegistration<?> serviceRegistration;
+ private static final Logger logger = LoggerFactory.getLogger(OsgiRegistration.class);
- public OsgiRegistration(ServiceRegistration<?> serviceRegistration) {
- this.serviceRegistration = serviceRegistration;
+ @GuardedBy("this")
+ private AutoCloseable instance;
+ private final ModuleIdentifier moduleIdentifier;
+ @GuardedBy("this")
+ private final Set<ServiceRegistration<?>> serviceRegistrations;
+ @GuardedBy("this")
+ private final Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations;
+
+ public OsgiRegistration(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
+ BundleContext bundleContext,
+ Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+ this.instance = instance;
+ this.moduleIdentifier = moduleIdentifier;
+ this.serviceNamesToAnnotations = serviceNamesToAnnotations;
+ this.serviceRegistrations = registerToSR(instance, bundleContext, serviceNamesToAnnotations);
}
- public OsgiRegistration() {
- this.serviceRegistration = null;
+ private static Set<ServiceRegistration<?>> registerToSR(AutoCloseable instance, BundleContext bundleContext,
+ Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+ Set<ServiceRegistration<?>> serviceRegistrations = new HashSet<>();
+ for (Entry<String, ServiceInterfaceAnnotation> entry : serviceNamesToAnnotations.entrySet()) {
+ Class<?> requiredInterface = entry.getValue().osgiRegistrationType();
+ checkState(requiredInterface.isInstance(instance), instance.getClass().getName() +
+ " instance should implement " + requiredInterface.getName());
+ Dictionary<String, String> propertiesForOsgi = createProps(entry.getKey());
+ ServiceRegistration<?> serviceRegistration = bundleContext
+ .registerService(requiredInterface.getName(), instance, propertiesForOsgi);
+ serviceRegistrations.add(serviceRegistration);
+ }
+ return serviceRegistrations;
}
@Override
- public void close() {
- if (serviceRegistration != null) {
- serviceRegistration.unregister();
+ public synchronized void close() {
+ for (ServiceRegistration<?> serviceRegistration : serviceRegistrations) {
+ try {
+ serviceRegistration.unregister();
+ } catch(IllegalStateException e) {
+ logger.trace("Cannot unregister {}", serviceRegistration, e);
+ }
}
+ serviceRegistrations.clear();
}
- }
+ public synchronized void updateRegistrations(Map<String, ServiceInterfaceAnnotation> newAnnotationMapping,
+ BundleContext bundleContext, AutoCloseable newInstance) {
+ boolean notEquals = this.instance != newInstance;
+ notEquals |= newAnnotationMapping.equals(serviceNamesToAnnotations) == false;
+ if (notEquals) {
+ // FIXME: changing from old state to new state can be improved by computing the diff
+ logger.debug("Detected change in service registrations for {}: old: {}, new: {}", moduleIdentifier,
+ serviceNamesToAnnotations, newAnnotationMapping);
+ close();
+ this.instance = newInstance;
+ Set<ServiceRegistration<?>> newRegs = registerToSR(instance, bundleContext, newAnnotationMapping);
+ serviceRegistrations.clear();
+ serviceRegistrations.addAll(newRegs);
+ }
+ }
+ }
}
return result;
}
+ public static Set<String> getQNames(Set<ServiceInterfaceAnnotation> siAnnotations) {
+ Set<String> qNames = new HashSet<>();
+ for (ServiceInterfaceAnnotation sia: siAnnotations) {
+ qNames.add(sia.value());
+ }
+ return Collections.unmodifiableSet(qNames);
+ }
public static Set<ServiceInterfaceAnnotation> getServiceInterfaceAnnotations(ModuleFactory factory) {
Set<Class<? extends AbstractServiceInterface>> implementedServiceIntefaces = Collections.unmodifiableSet(factory.getImplementedServiceIntefaces());
result.add(annotation);
}
}
- return result;
+ return Collections.unmodifiableSet(result);
}
static Set<Class<? extends AbstractServiceInterface>> getAllAbstractServiceInterfaceClasses(
*/
package org.opendaylight.controller.config.manager;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-import java.lang.management.ManagementFactory;
-
import org.junit.Test;
import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
import org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.lang.management.ManagementFactory;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
public class ConfigRegistryImplTest extends
AbstractLockedPlatformMBeanServerTest {
private static final Logger logger = LoggerFactory
BundleContext context = mock(BundleContext.class);
ConfigRegistryImpl configRegistry = null;
try {
- ModuleFactoriesResolver resolver = new HardcodedModuleFactoriesResolver(
+ ModuleFactoriesResolver resolver = new HardcodedModuleFactoriesResolver(mock(BundleContext.class),
factory, factory);
configRegistry = new ConfigRegistryImpl(resolver,
package org.opendaylight.controller.config.manager.impl;
import com.google.common.base.Preconditions;
-import junit.framework.Assert;
import org.junit.After;
+import org.junit.Before;
import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.RuntimeMBeanException;
-import java.io.Closeable;
-import java.io.InputStream;
import java.lang.management.ManagementFactory;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Dictionary;
+import java.util.LinkedList;
import java.util.List;
import java.util.Set;
protected ConfigRegistryJMXClient configRegistryClient;
protected BaseJMXRegistrator baseJmxRegistrator;
protected InternalJMXRegistrator internalJmxRegistrator;
- protected BundleContext mockedContext = mock(BundleContext.class);
+ @Mock
+ protected BundleContext mockedContext;
+ @Mock
protected ServiceRegistration<?> mockedServiceRegistration;
- private static final Logger logger = LoggerFactory.getLogger(AbstractConfigTest.class);
+ @Before
+ public void setUpMocks() {
+ MockitoAnnotations.initMocks(this);
+ }
+
// Default handler for OSGi service registration
- private static final BundleContextServiceRegistrationHandler noopServiceRegHandler = new BundleContextServiceRegistrationHandler() {
+ protected static class RecordingBundleContextServiceRegistrationHandler implements BundleContextServiceRegistrationHandler {
+ private final List<RegistrationHolder> registrations = new LinkedList<>();
@Override
- public void handleServiceRegistration(Object serviceInstance) {}
- };
+ public void handleServiceRegistration(Class<?> clazz, Object serviceInstance, Dictionary<String, ?> props) {
+
+ registrations.add(new RegistrationHolder(clazz, serviceInstance, props));
+ }
+
+ public List<RegistrationHolder> getRegistrations() {
+ return registrations;
+ }
+
+ protected static class RegistrationHolder {
+ protected final Class<?> clazz;
+ protected final Object instance;
+ protected final Dictionary<String, ?> props;
+
+ public RegistrationHolder(Class<?> clazz, Object instance, Dictionary<String, ?> props) {
+ this.clazz = clazz;
+ this.instance = instance;
+ this.props = props;
+ }
+ }
+
+ }
+
+ protected BundleContextServiceRegistrationHandler currentBundleContextServiceRegistrationHandler;
protected BundleContextServiceRegistrationHandler getBundleContextServiceRegistrationHandler(Class<?> serviceType) {
- return noopServiceRegHandler;
+ return currentBundleContextServiceRegistrationHandler;
}
// this method should be called in @Before
protected void initConfigTransactionManagerImpl(
ModuleFactoriesResolver resolver) {
+
final MBeanServer platformMBeanServer = ManagementFactory
.getPlatformMBeanServer();
- configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(
- platformMBeanServer);
+ configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(platformMBeanServer);
initBundleContext();
internalJmxRegistrator = new InternalJMXRegistrator(platformMBeanServer);
throw new RuntimeException(e);
}
configRegistryClient = new ConfigRegistryJMXClient(platformMBeanServer);
+ currentBundleContextServiceRegistrationHandler = new RecordingBundleContextServiceRegistrationHandler();
}
private void initBundleContext() {
- this.mockedServiceRegistration = mock(ServiceRegistration.class);
doNothing().when(mockedServiceRegistration).unregister();
-
RegisterServiceAnswer answer = new RegisterServiceAnswer();
-
- doAnswer(answer).when(mockedContext).registerService(Matchers.any(String[].class),
- any(Closeable.class), Matchers.<Dictionary<String, ?>>any());
- doAnswer(answer).when(mockedContext).registerService(Matchers.<Class<Closeable>>any(), any(Closeable.class),
- Matchers.<Dictionary<String, ?>>any());
- }
-
-
- public Collection<InputStream> getFilesAsInputStreams(List<String> paths) {
- final Collection<InputStream> resources = new ArrayList<>();
- List<String> failedToFind = new ArrayList<>();
- for (String path : paths) {
- InputStream resourceAsStream = getClass().getResourceAsStream(path);
- if (resourceAsStream == null) {
- failedToFind.add(path);
- } else {
- resources.add(resourceAsStream);
- }
- }
- Assert.assertEquals("Some files were not found", Collections.<String>emptyList(), failedToFind);
-
- return resources;
+ doAnswer(answer).when(mockedContext).registerService(Matchers.<String>any(), any(), Matchers.<Dictionary<String, ?>>any());
+ doAnswer(answer).when(mockedContext).registerService(Matchers.<Class>any(), any(), Matchers.<Dictionary<String, ?>>any());
}
@After
transaction.commit();
}
- protected void assertSame(ObjectName oN1, ObjectName oN2) {
- assertEquals(oN1.getKeyProperty("instanceName"),
- oN2.getKeyProperty("instanceName"));
- assertEquals(oN1.getKeyProperty("interfaceName"),
- oN2.getKeyProperty("interfaceName"));
- }
-
protected void assertStatus(CommitStatus status, int expectedNewInstances,
int expectedRecreatedInstances, int expectedReusedInstances) {
assertEquals("New instances mismatch in " + status, expectedNewInstances, status.getNewInstances().size());
.size());
}
- protected ObjectName createTestConfigBean(
- ConfigTransactionJMXClient transaction, String implementationName,
- String name) throws InstanceAlreadyExistsException {
- return transaction.createModule(implementationName,
- name);
- }
protected void assertBeanCount(int i, String configMXBeanName) {
assertEquals(i, configRegistry.lookupConfigBeans(configMXBeanName)
.size());
}
- protected void assertBeanExists(int count, String moduleName,
- String instanceName) {
- assertEquals(1,
- configRegistry.lookupConfigBeans(moduleName, instanceName)
- .size());
- }
-
/**
*
* @param configBeanClass
public static interface BundleContextServiceRegistrationHandler {
- void handleServiceRegistration(Object serviceInstance);
+ void handleServiceRegistration(Class<?> clazz, Object serviceInstance, Dictionary<String, ?> props);
}
Object serviceTypeRaw = args[0];
Object serviceInstance = args[1];
+ Dictionary<String, ?> props = (Dictionary) args[2];
if (serviceTypeRaw instanceof Class) {
Class<?> serviceType = (Class<?>) serviceTypeRaw;
- invokeServiceHandler(serviceInstance, serviceType);
+ invokeServiceHandler(serviceInstance, serviceType, props);
} else if(serviceTypeRaw instanceof String[]) {
for (String className : (String[]) serviceTypeRaw) {
- try {
- Class<?> serviceType = Class.forName(className);
- invokeServiceHandler(serviceInstance, serviceType);
- } catch (ClassNotFoundException e) {
- logger.warn("Not handling service registration of type {} ", className, e);
- }
+ invokeServiceHandler(serviceInstance, className, props);
}
+ } else if (serviceTypeRaw instanceof String) {
+ invokeServiceHandler(serviceInstance, (String) serviceTypeRaw, props);
+ } else {
+ throw new IllegalStateException("Not handling service registration of type, Unknown type" + serviceTypeRaw);
+ }
- } else
- logger.debug("Not handling service registration of type {}, Unknown type", serviceTypeRaw);
return mockedServiceRegistration;
}
- private void invokeServiceHandler(Object serviceInstance, Class<?> serviceType) {
+ public void invokeServiceHandler(Object serviceInstance, String className, Dictionary<String, ?> props) {
+ try {
+ Class<?> serviceType = Class.forName(className);
+ invokeServiceHandler(serviceInstance, serviceType, props);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Not handling service registration of type " + className, e);
+ }
+ }
+
+ private void invokeServiceHandler(Object serviceInstance, Class<?> serviceType, Dictionary<String, ?> props) {
BundleContextServiceRegistrationHandler serviceRegistrationHandler = getBundleContextServiceRegistrationHandler(serviceType);
if (serviceRegistrationHandler != null) {
- serviceRegistrationHandler.handleServiceRegistration(serviceType.cast(serviceInstance));
+ serviceRegistrationHandler.handleServiceRegistration(serviceType, serviceInstance, props);
}
}
}
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator;
}
}, currentlyRegisteredFactories);
- ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
+ SearchableServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
ServiceReferenceRegistryImpl.createInitialSRLookupRegistry(), txLookupRegistry, currentlyRegisteredFactories);
@Before
public void setUp() {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver());
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext));
}
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest.RecordingBundleContextServiceRegistrationHandler.RegistrationHolder;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBean;
import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory;
import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolIfc;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import javax.management.Attribute;
import javax.management.MBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
-
+import java.util.List;
import java.util.Map;
import java.util.Set;
@Before
public void setUp() {
super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ mockedContext,
new TestingFixedThreadPoolModuleFactory(),
new TestingParallelAPSPModuleFactory(),
new TestingScheduledThreadPoolModuleFactory()));
// create apsp-parallel
createParallelAPSP(transaction1, serviceReference);
transaction1.commit();
+
// check fixed1 is used
ServiceReferenceMXBean serviceReferenceMXBean = JMX.newMXBeanProxy(platformMBeanServer,
withoutTransactionName(serviceReference), ServiceReferenceMXBean.class);
assertEquals(withoutTransactionName(fixedTPTransactionON), serviceReferenceMXBean.getCurrentImplementation());
checkApspThreadCount(fixedNrOfThreads);
+ // check OSGi SR
+ List<RegistrationHolder> registrations =
+ ((RecordingBundleContextServiceRegistrationHandler) currentBundleContextServiceRegistrationHandler).getRegistrations();
+ assertEquals(1, registrations.size());
+ RegistrationHolder record = registrations.get(0);
+ assertEquals(TestingThreadPoolIfc.class, record.clazz);
+ assertEquals(ImmutableMap.of("name","ref"), (Map<String, String>) record.props);
// switch reference to scheduled
ConfigTransactionJMXClient transaction2 = configRegistryClient.createTransaction();
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+
+import java.util.Arrays;
+import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
+import org.osgi.framework.BundleContext;
public class DependencyResolverManagerTest {
moduleFactory,
maybeOldInternalInfo,
transactionModuleJMXRegistration,
- isDefaultBean);
+ isDefaultBean, mock(BundleContext.class));
}
private static Module mockedModule() {
}
}
- public HardcodedModuleFactoriesResolver(ModuleFactory... list) {
- this(mockBundleContext(),list);
- }
-
private static BundleContext mockBundleContext() {
BundleContext bundleContext = Mockito.mock(BundleContext.class);
ServiceRegistration<ModuleFactory> serviceRegistration = mock(ServiceRegistration.class);
@Before
public void setUp() {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TestingFixedThreadPoolModuleFactory(),
new TestingParallelAPSPModuleFactory()));
}
*/
package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test;
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.concurrent.Executor;
-
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import javax.management.ObjectName;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.Executor;
+
public class MockedDependenciesTest extends AbstractParallelAPSPTest {
private final String threadPoolImplementationName = "mockedthreadpool";
ClassBasedModuleFactory mockedThreadPoolConfigFactory = new ClassBasedModuleFactory(
threadPoolImplementationName, MockedThreadPoolModule.class);
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TestingParallelAPSPModuleFactory(),
mockedThreadPoolConfigFactory));
}
*/
package org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.test;
-import static org.junit.Assert.assertEquals;
-
import org.junit.After;
import org.junit.Before;
import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolImpl;
-import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool
- .TestingScheduledThreadPoolModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory;
import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
+import static org.junit.Assert.assertEquals;
+
public abstract class AbstractScheduledTest extends AbstractConfigTest {
protected static final String scheduled1 = "scheduled1";
public final void setUp() {
assertEquals(0,
TestingScheduledThreadPoolImpl.getNumberOfCloseMethodCalls());
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TestingScheduledThreadPoolModuleFactory(),
new TestingFixedThreadPoolModuleFactory(),
new TestingParallelAPSPModuleFactory()));
@Override
public void close() throws IOException {
executorService.shutdown();
+ allExecutors.remove(executorService);
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.config.manager.testingservices.threadpool.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleFactoriesResolver;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.osgi.framework.BundleContext;
+
+public class ShutdownTest extends AbstractConfigTest {
+ private final TestingFixedThreadPoolModuleFactory testingFixedThreadPoolModuleFactory = new TestingFixedThreadPoolModuleFactory();
+
+ @Mock
+ ModuleFactoriesResolver mockedResolver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Map<String, Entry<ModuleFactory, BundleContext>> allFactories = ImmutableMap.of(
+ testingFixedThreadPoolModuleFactory.getImplementationName(),
+ Maps.<ModuleFactory, BundleContext>immutableEntry(testingFixedThreadPoolModuleFactory, mockedContext));
+ doReturn(allFactories).when(mockedResolver).getAllFactories();
+ super.initConfigTransactionManagerImpl(mockedResolver);
+ }
+
+
+ @Test
+ public void testCreateAndDestroyBeanInSameTransaction() throws Exception {
+ {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ SimpleConfigurationTest.createFixedThreadPool(transaction);
+ transaction.commit();
+ }
+ assertEquals(1, TestingFixedThreadPool.allExecutors.size());
+ doReturn(Collections.emptyMap()).when(mockedResolver).getAllFactories();
+ {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ transaction.commit();
+ }
+ assertEquals(1, TestingFixedThreadPool.allExecutors.size());
+ }
+}
* dependencies.
*/
public class SimpleConfigurationTest extends AbstractConfigTest {
- private final int numberOfThreads = 5;
+ private static final int numberOfThreads = 5;
private final int numberOfThreads2 = 10;
private static final String fixed1 = "fixed1";
private static final List<ObjectName> emptyONs = Collections
@Before
public void setUp() {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
new TestingFixedThreadPoolModuleFactory()));
}
return fixed1names;
}
- private ObjectName createFixedThreadPool(
+ static ObjectName createFixedThreadPool(
ConfigTransactionJMXClient transaction)
throws InstanceAlreadyExistsException, InstanceNotFoundException {
transaction.assertVersion(0, 1);
// 4, check
assertEquals(2, configRegistryClient.getVersion());
- assertEquals(1, TestingFixedThreadPool.allExecutors.size());
- assertTrue(TestingFixedThreadPool.allExecutors.get(0).isShutdown());
+ assertEquals(0, TestingFixedThreadPool.allExecutors.size());
// dynamic config should be removed from platform
try {
// commit
transaction.commit();
// check that first threadpool is closed
- checkThreadPools(2, numberOfThreads2);
+ checkThreadPools(1, numberOfThreads2);
}
private void checkThreadPools(int expectedTotalNumberOfExecutors,
// commit
CommitStatus commitStatus = transaction.commit();
// check that new threadpool is created and old one is closed
- checkThreadPools(2, numberOfThreads);
+ checkThreadPools(1, numberOfThreads);
CommitStatus expected = new CommitStatus(emptyONs, emptyONs, fixed1List);
assertEquals(expected, commitStatus);
}
platformMBeanServer.getMBeanInfo(transaction.getObjectName());
fail();
}catch(InstanceNotFoundException e){
+ assertEquals("org.opendaylight.controller:TransactionName=ConfigTransaction-0-1,type=ConfigTransaction", e.getMessage());
}
}
* @return prefix + key as used in getProperty method.
*/
String getFullKeyForReporting(String key);
+
+ String getPrefix();
+ String getPropertyWithoutPrefix(String fullKey);
}
public String getFullKeyForReporting(String key) {
return null;
}
+
+ @Override
+ public String getPrefix() {
+ return null;
+ }
+
+ @Override
+ public String getPropertyWithoutPrefix(String fullKey) {
+ return null;
+ }
}
public void setUp() throws Exception {
factory = new LogbackModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
@Test
public void setUp() throws IOException, ClassNotFoundException {
factory = new LogbackModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
/**
public void setUp() throws JoranException, IOException {
factory = new LogbackModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
lc = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator configurator = new JoranConfigurator();
@Before
public void setUp() {
factory = new GlobalEventExecutorModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
@Test
@Before
public void setUp() {
factory = new NettyThreadgroupModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
@Test
class StopSystemBundleThread extends Thread {
private static final Logger logger = LoggerFactory.getLogger(StopSystemBundleThread.class);
- public static final String CONFIG_MANAGER_SYMBOLIC_NAME = "org.opendaylight.controller.config-manager";
private final Bundle systemBundle;
StopSystemBundleThread(Bundle systemBundle) {
try {
// wait so that JMX response is received
Thread.sleep(1000);
- // first try to stop config-manager
- Bundle configManager = findConfigManager();
- if (configManager != null){
- logger.debug("Stopping config-manager");
- configManager.stop();
- Thread.sleep(1000);
- }
logger.debug("Stopping system bundle");
systemBundle.stop();
} catch (BundleException e) {
logger.warn("Shutdown process interrupted", e);
}
}
-
- private Bundle findConfigManager() {
- for(Bundle bundle: systemBundle.getBundleContext().getBundles()){
- if (CONFIG_MANAGER_SYMBOLIC_NAME.equals(bundle.getSymbolicName())) {
- return bundle;
- }
- }
- return null;
- }
-
}
class CallSystemExitThread extends Thread {
*/
package org.opendaylight.controller.config.yang.shutdown.impl;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.opendaylight.controller.config.yang.shutdown.impl.ShutdownModuleFactory.NAME;
+
+import java.util.Collections;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMX;
+import javax.management.ObjectName;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.osgi.framework.Bundle;
-import javax.management.InstanceNotFoundException;
-import javax.management.JMX;
-import javax.management.ObjectName;
-import java.util.Collections;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
-import static org.opendaylight.controller.config.yang.shutdown.impl.ShutdownModuleFactory.NAME;
-
public class ShutdownTest extends AbstractConfigTest {
private final ShutdownModuleFactory factory = new ShutdownModuleFactory();
@Mock
- private Bundle mockedSysBundle, mockedConfigManager;
+ private Bundle mockedSysBundle;
@Before
doReturn(mockedSysBundle).when(mockedContext).getBundle(0);
mockedContext.getBundle(0);
doNothing().when(mockedSysBundle).stop();
- doNothing().when(mockedConfigManager).stop();
doReturn(mockedContext).when(mockedSysBundle).getBundleContext();
- doReturn(new Bundle[]{mockedSysBundle, mockedConfigManager}).when(mockedContext).getBundles();
+ doReturn(new Bundle[]{mockedSysBundle}).when(mockedContext).getBundles();
doReturn("system bundle").when(mockedSysBundle).getSymbolicName();
- doReturn(StopSystemBundleThread.CONFIG_MANAGER_SYMBOLIC_NAME).when(mockedConfigManager).getSymbolicName();
+
ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
private void assertStopped() throws Exception {
Thread.sleep(3000); // happens on another thread
- verify(mockedConfigManager).stop();
verify(mockedSysBundle).stop();
}
}
TestingScheduledThreadPoolModule.class, poolImplName);
factory = new AsyncEventBusModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
scheduledThreadPoolConfigFactory));
}
*/
package org.opendaylight.controller.config.threadpool.eventbus;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.junit.matchers.JUnitMatchers.containsString;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.opendaylight.controller.config.yang.threadpool.impl.EventBusModuleFactory;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
public class SyncEventBusConfigBeanTest extends AbstractConfigTest {
private EventBusModuleFactory factory;
public void setUp() {
factory = new EventBusModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
}
@Test
@Before
public void setUp() {
factory = new FixedThreadPoolModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
new NamingThreadFactoryModuleFactory()));
}
public void setUp() {
flexibleFactory = new FlexibleThreadPoolModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(flexibleFactory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,flexibleFactory,
new NamingThreadFactoryModuleFactory()));
}
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.api.ConflictingVersionException;
public void setUp() {
factory = new NamingThreadFactoryModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory));
}
@Test
public void setUp() {
factory = new ScheduledThreadPoolModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory,
new NamingThreadFactoryModuleFactory()));
}
*/
package org.opendaylight.controller.config.yangjmxgenerator.it;
-import static org.junit.Assert.fail;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
import org.opendaylight.controller.config.yang.test.impl.TestImplModuleMXBean;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import static org.junit.Assert.fail;
+
@Ignore
// ietf beans are not JMX compliant beans:
// Do not know how to make a
public void setUp() {
factory = new TestImplModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,
factory));
}
--- /dev/null
+/*
+* 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
+*/
+/*
+* Generated file
+*
+* Generated from: yang module name: config-test-impl yang module local name: impl-dep
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Apr 25 11:50:32 CEST 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.test.impl;
+public class DepTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory {
+
+}
--- /dev/null
+/*
+* 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
+*/
+/*
+* Generated file
+*
+* Generated from: yang module name: config-test-impl yang module local name: impl-identity-test
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Apr 25 11:50:32 CEST 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.test.impl;
+public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory {
+
+}
--- /dev/null
+/*
+* 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
+*/
+/*
+* Generated file
+*
+* Generated from: yang module name: config-test-impl yang module local name: impl-netconf
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Apr 25 11:50:32 CEST 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.test.impl;
+public class NetconfTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory {
+
+}
--- /dev/null
+/*
+* 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
+*/
+/*
+* Generated file
+*
+* Generated from: yang module name: config-test-impl yang module local name: impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Apr 25 11:50:32 CEST 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.test.impl;
+public class TestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory {
+
+}
public void setUp() {
factory = new NetconfTestImplModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
new DepTestImplModuleFactory(), new IdentityTestModuleFactory()));
}
reference\:file\:../lib/slf4j-api-1.7.2.jar@1:start,\
reference\:file\:../lib/logback-classic-1.0.9.jar@1:start,\
reference\:file\:../lib/logback-core-1.0.9.jar@1:start,\
- reference\:file\:../lib/logging.bridge-${controller.version}@1:start,\
+ reference\:file\:../lib/logging.bridge-${logging.bridge.version}@1:start,\
reference\:file\:../lib/jersey-core-1.17.jar@2:start,\
reference\:file\:../lib/jersey-server-1.17.jar@2:start
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
<snapshot>
<required-capabilities>
<capability>urn:opendaylight:params:xml:ns:yang:controller:netty?module=netty&revision=2013-11-19</capability>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
<snapshot>
<configuration>
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
<snapshot>
<configuration>
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<snapshot>
+ <configuration>
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">prefix:sal-netconf-connector</type>
+ <name>controller-config</name>
+ <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">1830</port>
+ <username xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">admin</username>
+ <worker-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+ <name>global-worker-group</name>
+ </worker-thread-group>
+ <address xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">127.0.0.1</address>
+ <tcp-only xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">false</tcp-only>
+ <event-executor xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-event-executor</type>
+ <name>global-event-executor</name>
+ </event-executor>
+ <password xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">admin</password>
+ <boss-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
+ <name>global-boss-group</name>
+ </boss-thread-group>
+ <dom-registry xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf">
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
+ <name>dom-broker</name>
+ </dom-registry>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf?module=odl-sal-netconf-connector-cfg&revision=2013-10-28</capability>
+ </required-capabilities>
+</snapshot>
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie
public class MDFlowMapping {
hardTimeout = sourceFlow.hardTimeout as int
idleTimeout = sourceFlow.idleTimeout as int
- cookie = BigInteger.valueOf(sourceFlow.id)
+ cookie = new FlowCookie(BigInteger.valueOf(sourceFlow.id))
priority = sourceFlow.priority as int
val sourceActions = sourceFlow.actions;
val it = new FlowBuilder();
hardTimeout = sourceFlow.hardTimeout as int
idleTimeout = sourceFlow.idleTimeout as int
- cookie = BigInteger.valueOf(sourceFlow.id)
+ cookie = new FlowCookie(BigInteger.valueOf(sourceFlow.id))
priority = sourceFlow.priority as int
id = new FlowId(flowId)
hardTimeout = sourceFlow.hardTimeout as int
idleTimeout = sourceFlow.idleTimeout as int
- cookie = BigInteger.valueOf(sourceFlow.id)
+ cookie = new FlowCookie(BigInteger.valueOf(sourceFlow.id))
priority = sourceFlow.priority as int
val sourceActions = sourceFlow.actions;
target.setActions(actionFrom(actions, node));
}
- target.setId(source.getCookie().longValue());
+ target.setId(source.getCookie().getValue().longValue());
return target;
}
}
private void checkOdFlow(NodeFlow odNodeFlow) {
- assertEquals("Cookie is incorrect.", 9223372036854775807L, odNodeFlow.getCookie().longValue());
+ assertEquals("Cookie is incorrect.", 9223372036854775807L, odNodeFlow.getCookie().getValue().longValue());
assertEquals("Hard timeout is incorrect.", 32765, odNodeFlow.getHardTimeout().shortValue());
assertEquals("Iddle timeout is incorrect.", 32766, odNodeFlow.getIdleTimeout().shortValue());
assertEquals("Priority is incorrect.", 32767, odNodeFlow.getPriority().shortValue());
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
private FlowAddedBuilder prepareOdFlowCommon() {
FlowAddedBuilder odNodeFlowBuilder = new FlowAddedBuilder();
- odNodeFlowBuilder.setCookie(new BigInteger("9223372036854775807"));
+ odNodeFlowBuilder.setCookie(new FlowCookie(new BigInteger("9223372036854775807")));
odNodeFlowBuilder.setHardTimeout(32767);
odNodeFlowBuilder.setIdleTimeout(32767);
odNodeFlowBuilder.setPriority(32767);
type instance-identifier;
}
+ typedef flow-cookie {
+ description "openflow specific type - flow cookie / flow cookie mask";
+ type uint64;
+ }
+
typedef output-port-values {
type enumeration {
enum MAX {
}
leaf cookie {
- type uint64;
+ type flow-cookie;
}
leaf table_id {
}
leaf cookie_mask {
- type uint64;
+ type flow-cookie;
}
leaf buffer_id {
--- /dev/null
+module node-error {
+ namespace "urn:opendaylight:node:error:service";
+ prefix node-error;
+
+ import sal-flow {prefix flow; revision-date "2013-08-19";}
+ import flow-errors {prefix error;}
+ import flow-capable-transaction {prefix tr;}
+ import yang-ext {prefix ext; revision-date "2013-07-09";}
+ import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+ import opendaylight-flow-types {prefix types;revision-date "2013-10-26";}
+ import opendaylight-group-types {prefix group-type;revision-date 2013-10-18;}
+ import opendaylight-meter-types {prefix meter-type;revision-date "2013-09-18";}
+
+ revision "2014-04-10" {
+ description "Initial revision of errors received from a node";
+ }
+
+ notification hello-failed-error-notification {
+ description "Model for ofp_error-Type=0, Hello protocol failed";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification bad-request-error-notification {
+ description "Model for ofp_error-Type=1, Request was not understood.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification bad-action-error-notification {
+ description "Model for ofp_error-Type=2, Error in action description.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification bad-instruction-error-notification {
+ description "Model for ofp_error-Type=3, Error in instruction list.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification bad-match-error-notification {
+ description "Model for ofp_error-Type=4, Error in match.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification flow-mod-error-notification {
+ description "Model for ofp_error-Type=5 - Problem modifying flow entry.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ uses flow:node-error-reference;
+ }
+
+ notification group-mod-error-notification {
+ description "Model for ofp_error-Type=6 - Problem modifying group entry.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification port-mod-error-notification {
+ description "Model for ofp_error-Type=7 - Port mod request failed.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification table-mod-error-notification {
+ description "Model for ofp_error-Type=8 - Table mod request failed.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification queue-op-error-notification {
+ description "Model for ofp_error-Type=9 - Queue operation failed.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification switch-config-error-notification {
+ description "Model for ofp_error-Type=10 - Switch Config request failed.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification role-request-error-notification {
+ description "Model for ofp_error-Type=11 - Controller Role request failed.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification meter-mod-error-notification {
+ description "Model for ofp_error-Type=12 - Error in meter.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification table-features-error-notification {
+ description "Model for ofp_error-Type=13 - Setting table features failed.";
+
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+
+ notification experimenter-error-notification {
+ description "Model for ofp_error-Type=65535 - Experimenter Error Messages";
+ uses error:error-message;
+ uses tr:transaction-aware;
+ uses tr:transaction-metadata;
+ uses flow:base-node-error-notification;
+ uses flow:node-error-reference;
+ }
+}
+
import opendaylight-match-types {prefix match-type;revision-date "2013-10-26";}
import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";}
import opendaylight-action-types {prefix action-type;revision-date "2013-11-12";}
+ import opendaylight-flow-types {prefix flow-type;revision-date "2013-10-26";}
revision "2013-07-09" {
description "";
}
- typedef cookie {
+ typedef connection-cookie {
type uint32;
}
}
notification packet-received {
- leaf cookie {
- type cookie;
+ leaf connection-cookie {
+ type connection-cookie;
+ }
+
+ leaf flow-cookie {
+ type flow-type:flow-cookie;
}
leaf table-id {
input {
uses inv:node-context-ref;
- leaf cookie {
- type cookie;
+ leaf connection-cookie {
+ type connection-cookie;
}
leaf egress {
type inv:node-connector-ref;
}
- leaf buffer-id {
+ leaf buffer-id {
type uint32;
}
uses types:flow;
}
+ grouping base-node-error-notification {
+ leaf node {
+ ext:context-reference "inv:node-context";
+ type inv:node-ref;
+ }
+ }
+
+ grouping node-error-reference {
+ choice object-reference {
+ case flow-ref{
+ leaf flow-ref {
+ type types:flow-ref;
+ }
+ }
+ case group-ref{
+ leaf group-ref {
+ type group-type:group-ref;
+ }
+ }
+ case meter-ref{
+ leaf meter-ref {
+ type meter-type:meter-ref;
+ }
+ }
+ }
+ }
+
/** Base configuration structure **/
grouping flow-update {
uses "inv:node-context-ref";
uses error:error-message;
uses tr:transaction-aware;
uses tr:transaction-metadata;
- choice object-reference {
- case flow-ref{
- leaf flow-ref {
- type types:flow-ref;
- }
- }
- case group-ref{
- leaf group-ref {
- type group-type:group-ref;
- }
- }
- case meter-ref{
- leaf meter-ref {
- type meter-type:meter-ref;
- }
- }
- }
- leaf node {
- ext:context-reference "inv:node-context";
- type inv:node-ref;
- }
-
+ uses node-error-reference;
+ uses base-node-error-notification;
}
notification node-experimenter-error-notification {
</modules>
- <properties>
-
- <!-- Plugin Versions -->
- <bundle.plugin.version>2.4.0</bundle.plugin.version>
- <exam.version>3.0.0</exam.version>
- <maven.clean.plugin.version>2.5</maven.clean.plugin.version>
-
- <!-- Dependency Versions -->
- <mockito.version>1.9.5</mockito.version>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <sal.version>0.8.1-SNAPSHOT</sal.version>
- <sonar.branch>${user.name}-private-view</sonar.branch>
- <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
- <sonar.host.url>https://sonar.opendaylight.org/</sonar.host.url>
- <sonar.jacoco.Reportpath>target/jacoco.exec</sonar.jacoco.Reportpath>
- <sonar.jacoco.itReportPath>target/jacoco-it.exec</sonar.jacoco.itReportPath>
-
- <!-- Sonar properties using jacoco to retrieve integration test results -->
- <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
- <sonar.language>java</sonar.language>
- </properties>
-
- <dependencyManagement>
- <dependencies>
-
- <!-- SAL Dependencies -->
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>sal-connector-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- <version>${sal.version}</version>
- <exclusions>
- <exclusion>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-util</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-remote</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>binding-generator-impl</artifactId>
- <version>${yangtools.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-parser-impl</artifactId>
- <version>${yangtools.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <version>${osgi.core.version}</version>
- </dependency>
-
- <!-- Supporting Libraries -->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>${slf4j.version}</version>
- </dependency>
- <dependency>
- <groupId>xml-apis</groupId>
- <artifactId>xml-apis</artifactId>
- <version>1.4.01</version>
- </dependency>
- <!-- Testing Dependencies -->
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <version>${mockito.version}</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
- <version>2.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-jmx-generator-plugin</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ </dependencies>
</plugin>
</plugins>
</build>
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${config.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
<executions>
<execution>
<goals>
}
if (!d.isPresent() && iterator.hasNext()) {
- writeTransaction.put(store, currentPath, currentOp.createDefault(currentArg));
+ writeTransaction.merge(store, currentPath, currentOp.createDefault(currentArg));
}
}
//LOG .info("Tx: {} : Putting data {}",getDelegate().getIdentifier(),normalized.getKey());
*/
package org.opendaylight.controller.sal.binding.codegen.impl;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import javassist.ClassPool;
+import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator;
+import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
+
+import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import javassist.ClassPool;
-
-import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator;
-import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
-
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-
public class SingletonHolder {
public static final ClassPool CLASS_POOL = ClassPool.getDefault();
*/
@Deprecated
public static synchronized final ListeningExecutorService getDefaultNotificationExecutor() {
+
if (NOTIFICATION_EXECUTOR == null) {
+ // Overriding the queue since we need an unbounded queue
+ // and threadpoolexecutor would not create new threads if the queue is not full
+ BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>() {
+ @Override
+ public boolean offer(Runnable r) {
+ if (size() <= 1) {
+ // if the queue is empty (or has just 1), no need to rampup the threads
+ return super.offer(r);
+ } else {
+ // if the queue is not empty, force the queue to return false.
+ // threadpoolexecutor will spawn a new thread if the queue.offer returns false.
+ return false;
+ }
+ }
+ };
+
ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("md-sal-binding-notification-%d").build();
- ExecutorService executor = new ThreadPoolExecutor(CORE_NOTIFICATION_THREADS, MAX_NOTIFICATION_THREADS,
- NOTIFICATION_THREAD_LIFE, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), factory);
+
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_NOTIFICATION_THREADS, MAX_NOTIFICATION_THREADS,
+ NOTIFICATION_THREAD_LIFE, TimeUnit.SECONDS, queue , factory,
+ new RejectedExecutionHandler() {
+ // if the max threads are met, then it will raise a rejectedExecution. We then push to the queue.
+ @Override
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
+ try {
+ executor.getQueue().put(r);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
NOTIFICATION_EXECUTOR = MoreExecutors.listeningDecorator(executor);
}
+
return NOTIFICATION_EXECUTOR;
}
return schemaContext;
}
+ public DOMDataBroker getDomAsyncDataBroker() {
+ return newDOMDataBroker;
+ }
+
protected BindingTestContext(final ListeningExecutorService executor, final ClassPool classPool, final boolean startWithSchema) {
this.executor = executor;
this.classPool = classPool;
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${config.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
<executions>
<execution>
<goals>
<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-flow-management</artifactId>
</dependencies>
<build>
<plugins>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
--- /dev/null
+module opendaylight-sal-test-store {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:store";
+ prefix "binding-impl";
+
+ description
+ "Regression Test model for data store";
+
+ revision "2014-04-22" {
+ description
+ "Initial revision";
+ }
+
+ grouping name-value {
+ leaf name {
+ type string;
+ }
+ leaf value {
+ type string;
+ }
+ }
+
+ container lists {
+ config false;
+ container unordered-container {
+ list unordered-list {
+ key "name";
+ uses name-value;
+ }
+ }
+ container ordered-container {
+ list ordered-list {
+ ordered-by user;
+ key "name";
+ uses name-value;
+ }
+ }
+ container unkeyed-container {
+ /*
+ Following list nodes not specify key, which
+ makes impossible to uniquely identify list items
+ over time.
+ */
+ list unkeyed-list {
+ uses name-value;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 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.md.sal.binding.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public class ConcurrentImplicitCreateTest extends AbstractDataServiceTest {
+
+ private static final NodeKey NODE_FOO_KEY = new NodeKey(new NodeId("foo"));
+ private static final NodeKey NODE_BAR_KEY = new NodeKey(new NodeId("foo"));
+ private static InstanceIdentifier<Nodes> NODES_PATH = InstanceIdentifier.builder(Nodes.class).build();
+ private static InstanceIdentifier<Node> NODE_FOO_PATH = InstanceIdentifier.builder(NODES_PATH)
+ .child(Node.class, NODE_FOO_KEY).build();
+ private static InstanceIdentifier<Node> NODE_BAR_PATH = InstanceIdentifier.builder(NODES_PATH)
+ .child(Node.class, NODE_FOO_KEY).build();
+
+ @Test
+ public void testConcurrentCreate() throws InterruptedException, ExecutionException {
+
+ DataModificationTransaction fooTx = baDataService.beginTransaction();
+ DataModificationTransaction barTx = baDataService.beginTransaction();
+
+ fooTx.putOperationalData(NODE_FOO_PATH, new NodeBuilder().setKey(NODE_FOO_KEY).build());
+ barTx.putOperationalData(NODE_BAR_PATH, new NodeBuilder().setKey(NODE_BAR_KEY).build());
+
+ Future<RpcResult<TransactionStatus>> fooFuture = fooTx.commit();
+ Future<RpcResult<TransactionStatus>> barFuture = barTx.commit();
+
+ RpcResult<TransactionStatus> fooResult = fooFuture.get();
+ RpcResult<TransactionStatus> barResult = barFuture.get();
+
+ assertTrue(fooResult.isSuccessful());
+ assertTrue(barResult.isSuccessful());
+
+ assertEquals(TransactionStatus.COMMITED, fooResult.getResult());
+ assertEquals(TransactionStatus.COMMITED, barResult.getResult());
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.md.sal.binding.data;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.Lists;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.OrderedContainer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.UnkeyedContainer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.UnkeyedContainerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.UnorderedContainer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.ordered.container.OrderedList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.ordered.container.OrderedListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.ordered.container.OrderedListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unkeyed.container.UnkeyedList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unkeyed.container.UnkeyedListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unordered.container.UnorderedList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unordered.container.UnorderedListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unordered.container.UnorderedListKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/*
+ * Copyright (c) 2014 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
+ */
+public class ListProcessingAndOrderingTest extends AbstractDataServiceTest {
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier DOM_UNORDERED_LIST_PATH = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+ .builder(Lists.QNAME).node(UnorderedContainer.QNAME).node(UnorderedList.QNAME).build();
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier DOM_ORDERED_LIST_PATH = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+ .builder(Lists.QNAME).node(OrderedContainer.QNAME).node(OrderedList.QNAME).build();
+
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier DOM_UNKEYED_LIST_PATH = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+ .builder(Lists.QNAME).node(UnkeyedContainer.QNAME).node(UnkeyedList.QNAME).build();
+
+ private static final InstanceIdentifier<UnorderedContainer> UNORDERED_CONTAINER_PATH = InstanceIdentifier.builder(Lists.class).child(UnorderedContainer.class).build();
+ private static final InstanceIdentifier<OrderedContainer> ORDERED_CONTAINER_PATH = InstanceIdentifier.builder(Lists.class).child(OrderedContainer.class).build();
+ private static final InstanceIdentifier<UnkeyedContainer> UNKEYED_CONTAINER_PATH = InstanceIdentifier.builder(Lists.class).child(UnkeyedContainer.class).build();
+
+ private static final UnorderedListKey UNORDERED_FOO_KEY = new UnorderedListKey("foo");
+ private static final UnorderedListKey UNORDERED_BAR_KEY = new UnorderedListKey("bar");
+
+ private static final InstanceIdentifier<UnorderedList> UNORDERED_FOO_PATH = InstanceIdentifier.builder(UNORDERED_CONTAINER_PATH).child(UnorderedList.class,UNORDERED_FOO_KEY).build();
+ private static final InstanceIdentifier<UnorderedList> UNORDERED_BAR_PATH = InstanceIdentifier.builder(UNORDERED_CONTAINER_PATH).child(UnorderedList.class,UNORDERED_BAR_KEY).build();
+
+ private static final OrderedListKey ORDERED_FOO_KEY = new OrderedListKey("foo");
+ private static final OrderedListKey ORDERED_BAR_KEY = new OrderedListKey("bar");
+ private static final InstanceIdentifier<OrderedList> ORDERED_FOO_PATH = InstanceIdentifier.builder(ORDERED_CONTAINER_PATH).child(OrderedList.class,ORDERED_FOO_KEY).build();
+ private static final InstanceIdentifier<OrderedList> ORDERED_BAR_PATH = InstanceIdentifier.builder(ORDERED_CONTAINER_PATH).child(OrderedList.class,ORDERED_BAR_KEY).build();
+
+
+ @Test
+ public void unorderedListReadWriteTest() throws InterruptedException, ExecutionException {
+ DataModificationTransaction tx = baDataService.beginTransaction();
+
+ tx.putOperationalData(UNORDERED_FOO_PATH, createUnordered("foo"));
+ tx.putOperationalData(UNORDERED_BAR_PATH, createUnordered("bar"));
+ assertedCommit(tx);
+
+ NormalizedNode<?, ?> data = resolveDataAsserted(DOM_UNORDERED_LIST_PATH);
+ assertTrue(data instanceof MapNode);
+ assertFalse(data instanceof OrderedMapNode);
+
+ assertXmlRepresentation(UNORDERED_CONTAINER_PATH, "foo","bar");
+ }
+
+
+
+ @Test
+ public void orderedListReadWriteTest() throws InterruptedException, ExecutionException {
+ DataModificationTransaction tx = baDataService.beginTransaction();
+
+ tx.putOperationalData(ORDERED_FOO_PATH, createOrdered("foo"));
+ tx.putOperationalData(ORDERED_BAR_PATH, createOrdered("bar"));
+ assertedCommit(tx);
+ NormalizedNode<?, ?> data = resolveDataAsserted(DOM_ORDERED_LIST_PATH);
+ assertTrue(data instanceof MapNode);
+ assertTrue(data instanceof OrderedMapNode);
+
+ assertXmlRepresentation(ORDERED_CONTAINER_PATH, "foo","bar");
+
+ }
+
+
+
+ @Test
+ public void unkeyedListReadWriteTest() throws InterruptedException, ExecutionException {
+ DataModificationTransaction tx = baDataService.beginTransaction();
+
+ ImmutableList<UnkeyedList> unkeyedItems= ImmutableList.<UnkeyedList>builder()
+ .add(createUnkeyed("foo"))
+ .add(createUnkeyed("bar"))
+ .build();
+
+ tx.putOperationalData(UNKEYED_CONTAINER_PATH, new UnkeyedContainerBuilder().setUnkeyedList(unkeyedItems).build());
+ assertedCommit(tx);
+ NormalizedNode<?, ?> data = resolveDataAsserted(DOM_UNKEYED_LIST_PATH);
+ assertFalse(data instanceof MapNode);
+ assertTrue(data instanceof UnkeyedListNode);
+
+ assertXmlRepresentation(UNKEYED_CONTAINER_PATH, "foo","bar");
+ }
+
+ private NormalizedNode<?, ?> resolveDataAsserted(
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath) {
+
+ try (DOMDataReadTransaction readTx = testContext.getDomAsyncDataBroker().newReadOnlyTransaction()){
+ ListenableFuture<Optional<NormalizedNode<?, ?>>> data = readTx.read(LogicalDatastoreType.OPERATIONAL, domPath);
+ Optional<NormalizedNode<?, ?>> potential = data.get();
+ assertTrue(potential.isPresent());
+ return potential.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static UnorderedList createUnordered(final String name) {
+ return new UnorderedListBuilder().setName(name).setValue(createValue(name)).build();
+ }
+
+ private static OrderedList createOrdered(final String name) {
+ return new OrderedListBuilder().setName(name).setValue(createValue(name)).build();
+ }
+
+ private static UnkeyedList createUnkeyed(final String name) {
+ return new UnkeyedListBuilder().setName(name).setValue(createValue(name)).build();
+ }
+
+ private static String createValue(final String name) {
+ return name + "-" + name.hashCode();
+ }
+
+ private static void assertedCommit(final DataModificationTransaction tx) throws InterruptedException, ExecutionException {
+ RpcResult<TransactionStatus> result = tx.commit().get();
+ assertTrue(result.isSuccessful());
+ assertEquals(TransactionStatus.COMMITED,result.getResult());
+ }
+
+ @SuppressWarnings("deprecation")
+ private void assertXmlRepresentation(final InstanceIdentifier<?> containerPath, final String... childNameValues) {
+
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = testContext.getBindingToDomMappingService().toDataDom(containerPath);
+ CompositeNode compositeNode = testContext.getDomDataBroker().readOperationalData(domPath);
+ assertNotNull(compositeNode);
+
+ Set<String> childValues = new HashSet<>();
+ Collections.addAll(childValues, childNameValues);
+
+ for(Node<?> child : compositeNode.getChildren()) {
+ assertTrue(child instanceof CompositeNode);
+ CompositeNode compChild = (CompositeNode) child;
+ String nameLeafValue = (String) compChild.getSimpleNodesByName("name").get(0).getValue();
+ String valueLeafValue = (String) compChild.getSimpleNodesByName("value").get(0).getValue();
+
+ assertEquals(createValue(nameLeafValue), valueLeafValue);
+ childValues.remove(nameLeafValue);
+ }
+ assertTrue(childValues.isEmpty());
+ }
+
+}
import java.util.List;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.NotificationListener;
import org.opendaylight.yangtools.yang.binding.RpcService;
-public class NoficationTest extends AbstractTest {
+@Ignore
+public class NotificationTest extends AbstractTest {
private final FlowListener listener1 = new FlowListener();
private final FlowListener listener2 = new FlowListener();
*
*/
assertEquals(1, listener1.addedFlows.size());
- assertEquals(0, listener1.addedFlows.get(0).getCookie().intValue());
+ assertEquals(0, listener1.addedFlows.get(0).getCookie().getValue().intValue());
/**
* The registration of the Consumer 2. SalFlowListener is registered
*/
public static FlowAdded flowAdded(int i) {
FlowAddedBuilder ret = new FlowAddedBuilder();
- ret.setCookie(BigInteger.valueOf(i));
+ ret.setCookie(new FlowCookie(BigInteger.valueOf(i)));
return ret.build();
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
static AddFlowInput createSampleAddFlow(NodeRef node, int cookie) {
AddFlowInputBuilder ret = new AddFlowInputBuilder();
ret.setNode(node);
- ret.setCookie(BigInteger.valueOf(cookie));
+ ret.setCookie(new FlowCookie(BigInteger.valueOf(cookie)));
return ret.build();
}
}
</provider>
</instance>
</service>
+
<service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
binding:binding-broker-osgi-registry
</provider>
</instance>
</service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <instance>
+ <name>binding-rpc-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+ </instance>
+ </service>
<service>
<type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
binding-impl:binding-dom-mapping-service
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
- // TODO Auto-generated method stub
return null;
}
}
}
- private static abstract class CompositeNodeNormalizationOpertation<T extends PathArgument> extends
+ private static abstract class CompositeNodeNormalizationOperation<T extends PathArgument> extends
DataNormalizationOperation<T> {
- protected CompositeNodeNormalizationOpertation(final T identifier) {
+ protected CompositeNodeNormalizationOperation(final T identifier) {
super(identifier);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
- public final NormalizedNodeContainer<?, ?, ?> normalize(final Node<?> legacyData) {
+ public final NormalizedNode<?, ?> normalize(final Node<?> legacyData) {
checkArgument(legacyData != null);
if (!isMixin() && getIdentifier().getNodeType() != null) {
checkArgument(getIdentifier().getNodeType().equals(legacyData.getNodeType()),
builder.addChild(childOp.normalize(childLegacy));
}
}
- return (NormalizedNodeContainer<?, ?, ?>) builder.build();
+ return builder.build();
}
@SuppressWarnings("rawtypes")
}
private static abstract class DataContainerNormalizationOperation<T extends PathArgument> extends
- CompositeNodeNormalizationOpertation<T> {
+ CompositeNodeNormalizationOperation<T> {
private final DataNodeContainer schema;
private final Map<QName, DataNormalizationOperation<?>> byQName;
}
}
+ private static final class UnkeyedListItemNormalization extends DataContainerNormalizationOperation<NodeIdentifier> {
+
+ protected UnkeyedListItemNormalization(final ListSchemaNode schema) {
+ super(new NodeIdentifier(schema.getQName()), schema);
+ }
+
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
+ }
+
+ @Override
+ public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
+ return Builders.unkeyedListEntryBuilder().withNodeIdentifier((NodeIdentifier) currentArg).build();
+ }
+
+ }
+
private static final class ContainerNormalization extends DataContainerNormalizationOperation<NodeIdentifier> {
protected ContainerNormalization(final ContainerSchemaNode schema) {
}
private static abstract class MixinNormalizationOp<T extends PathArgument> extends
- CompositeNodeNormalizationOpertation<T> {
+ CompositeNodeNormalizationOperation<T> {
protected MixinNormalizationOp(final T identifier) {
super(identifier);
}
- private static final class LeafListMixinNormalization extends MixinNormalizationOp<NodeIdentifier> {
+
+ private static final class OrderedLeafListMixinNormalization extends UnorderedLeafListMixinNormalization {
+
+
+ public OrderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
+ super(potential);
+ }
+
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
+ }
+
+ @Override
+ public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
+ return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier()).build();
+ }
+ }
+
+ private static class UnorderedLeafListMixinNormalization extends MixinNormalizationOp<NodeIdentifier> {
private final DataNormalizationOperation<?> innerOp;
- public LeafListMixinNormalization(final LeafListSchemaNode potential) {
+ public UnorderedLeafListMixinNormalization(final LeafListSchemaNode potential) {
super(new NodeIdentifier(potential.getQName()));
innerOp = new LeafListEntryNormalization(potential);
}
}
- private static final class ListMixinNormalization extends MixinNormalizationOp<NodeIdentifier> {
+ private static class UnorderedMapMixinNormalization extends MixinNormalizationOp<NodeIdentifier> {
private final ListItemNormalization innerNode;
- public ListMixinNormalization(final ListSchemaNode list) {
+ public UnorderedMapMixinNormalization(final ListSchemaNode list) {
super(new NodeIdentifier(list.getQName()));
this.innerNode = new ListItemNormalization(new NodeIdentifierWithPredicates(list.getQName(),
Collections.<QName, Object> emptyMap()), list);
}
+
+ private static class UnkeyedListMixinNormalization extends MixinNormalizationOp<NodeIdentifier> {
+
+ private final UnkeyedListItemNormalization innerNode;
+
+ public UnkeyedListMixinNormalization(final ListSchemaNode list) {
+ super(new NodeIdentifier(list.getQName()));
+ this.innerNode = new UnkeyedListItemNormalization(list);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ return Builders.unkeyedListBuilder().withNodeIdentifier(getIdentifier());
+ }
+
+ @Override
+ public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
+ return Builders.unkeyedListBuilder().withNodeIdentifier(getIdentifier()).build();
+ }
+
+ @Override
+ public DataNormalizationOperation<?> getChild(final PathArgument child) {
+ if (child.getNodeType().equals(getIdentifier().getNodeType())) {
+ return innerNode;
+ }
+ return null;
+ }
+
+ @Override
+ public DataNormalizationOperation<?> getChild(final QName child) {
+ if (getIdentifier().getNodeType().equals(child)) {
+ return innerNode;
+ }
+ return null;
+ }
+
+ }
+
+ private static final class OrderedMapMixinNormalization extends UnorderedMapMixinNormalization {
+
+ public OrderedMapMixinNormalization(final ListSchemaNode list) {
+ super(list);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier());
+ }
+
+ @Override
+ public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
+ return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier()).build();
+ }
+
+ }
+
private static class ChoiceNodeNormalization extends MixinNormalizationOp<NodeIdentifier> {
private final ImmutableMap<QName, DataNormalizationOperation<?>> byQName;
}
if (potential == null) {
- throw new DataNormalizationException(String.format("Supplied QName %s is not valid according to schema %s", child, schema));
+ throw new DataNormalizationException(String.format("Supplied QName %s is not valid according to schema %s, potential children nodes: %s", child, schema,schema.getChildNodes()));
}
if ((schema instanceof DataSchemaNode) && !((DataSchemaNode) schema).isAugmenting() && potential.isAugmenting()) {
if (potential instanceof ContainerSchemaNode) {
return new ContainerNormalization((ContainerSchemaNode) potential);
} else if (potential instanceof ListSchemaNode) {
- return new ListMixinNormalization((ListSchemaNode) potential);
+
+ return fromListSchemaNode((ListSchemaNode) potential);
} else if (potential instanceof LeafSchemaNode) {
return new LeafNormalization(new NodeIdentifier(potential.getQName()));
} else if (potential instanceof org.opendaylight.yangtools.yang.model.api.ChoiceNode) {
return new ChoiceNodeNormalization((org.opendaylight.yangtools.yang.model.api.ChoiceNode) potential);
} else if (potential instanceof LeafListSchemaNode) {
- return new LeafListMixinNormalization((LeafListSchemaNode) potential);
+ return fromLeafListSchemaNode((LeafListSchemaNode) potential);
}
return null;
}
+ private static DataNormalizationOperation<?> fromListSchemaNode(final ListSchemaNode potential) {
+ List<QName> keyDefinition = potential.getKeyDefinition();
+ if(keyDefinition == null || keyDefinition.isEmpty()) {
+ return new UnkeyedListMixinNormalization(potential);
+ }
+ if(potential.isUserOrdered()) {
+ return new OrderedMapMixinNormalization(potential);
+ }
+ return new UnorderedMapMixinNormalization(potential);
+ }
+
+ private static DataNormalizationOperation<?> fromLeafListSchemaNode(final LeafListSchemaNode potential) {
+ if(potential.isUserOrdered()) {
+ return new OrderedLeafListMixinNormalization(potential);
+ }
+ return new UnorderedLeafListMixinNormalization(potential);
+ }
+
+
public static DataNormalizationOperation<?> from(final SchemaContext ctx) {
return new ContainerNormalization(ctx);
}
import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
for (NormalizedNode<?, ?> child : node.getValue()) {
if (child instanceof MixinNode && child instanceof NormalizedNodeContainer<?, ?, ?>) {
builder.addAll(toLegacyNodesFromMixin((NormalizedNodeContainer) child));
+ } else if( child instanceof UnkeyedListNode) {
+ builder.addAll(toLegacyNodesFromUnkeyedList((UnkeyedListNode) child));
} else {
addToBuilder(builder, toLegacy(child));
}
return builder.toInstance();
}
+ private static Iterable<? extends Node<?>> toLegacyNodesFromUnkeyedList(final UnkeyedListNode mixin) {
+ ArrayList<Node<?>> ret = new ArrayList<>();
+ for (NormalizedNode<?, ?> child : mixin.getValue()) {
+ ret.add(toLegacy(child));
+ }
+ return FluentIterable.from(ret).filter(Predicates.notNull());
+ }
+
private static void addToBuilder(final CompositeNodeBuilder<ImmutableCompositeNode> builder, final Node<?> legacy) {
if (legacy != null) {
builder.add(legacy);
ret.add(toLegacy(child));
}
}
- return FluentIterable.from(ret).filter(new Predicate<Node<?>>() {
-
- @Override
- public boolean apply(final Node<?> input) {
- return input != null;
- }
- });
+ return FluentIterable.from(ret).filter(Predicates.notNull());
}
public DataNormalizationOperation<?> getRootOperation() {
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${config.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
<executions>
<execution>
<goals>
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${config.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
<executions>
<execution>
<goals>
@Override
public void merge(final LogicalDatastoreType store, final InstanceIdentifier path,
final NormalizedNode<?, ?> data) {
- // TODO Auto-generated method stub
- throw new UnsupportedOperationException("Not implemented yet.");
+ getSubtransaction(store).merge(path,data);
}
@Override
final InstanceIdentifier path) {
return getSubtransaction(store).read(path);
}
-
- @Override
- public void merge(final LogicalDatastoreType store, final InstanceIdentifier path,
- final NormalizedNode<?, ?> data) {
-
- }
}
private final class CommitCoordination implements Callable<RpcResult<TransactionStatus>> {
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
public abstract class BackwardsCompatibleTransaction<T extends DOMDataReadTransaction> implements
InstanceIdentifier currentPath = new InstanceIdentifier(currentArguments);
boolean isPresent = getDelegate().read(store, currentPath).get().isPresent();
if(isPresent == false && iterator.hasNext()) {
- getDelegate().put(store, currentPath, currentOp.createDefault(currentArg));
+ getDelegate().merge(store, currentPath, currentOp.createDefault(currentArg));
}
}
} catch (InterruptedException | ExecutionException e) {
getDelegate().put(store, normalizedPath, normalizedData);
}
- private boolean isAugmentationChild(final InstanceIdentifier normalizedPath) {
- List<PathArgument> parentArgs = parentPath(normalizedPath).getPath();
- if(parentArgs.isEmpty()) {
- return false;
- }
- return Iterables.getLast(parentArgs) instanceof AugmentationIdentifier;
- }
-
- private void ensureParentNode(final LogicalDatastoreType store, final InstanceIdentifier normalizedPath,
- final NormalizedNode<?, ?> normalizedData) {
- InstanceIdentifier parentPath = parentPath(normalizedPath);
- PathArgument parentType = Iterables.getLast(parentPath.getPath());
- if(parentType instanceof AugmentationIdentifier) {
- AugmentationNode node = Builders.augmentationBuilder()
- .withNodeIdentifier((AugmentationIdentifier) parentType)
- .build();
- getDelegate().put(store, parentPath, node);
- }
- if(normalizedData instanceof MapEntryNode) {
- MapNode mapNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(normalizedData.getNodeType())).build();
- getDelegate().put(store, parentPath, mapNode);
- } else if (normalizedData instanceof LeafSetNode<?>){
- LeafSetNode<Object> leafNode = Builders.leafSetBuilder().withNodeIdentifier(new NodeIdentifier(normalizedData.getNodeType())).build();
- getDelegate().put(store, parentPath, leafNode);
- }
-
-
- }
-
- private InstanceIdentifier parentPath(final InstanceIdentifier normalizedPath) {
- List<PathArgument> childArgs = normalizedPath.getPath();
- return new InstanceIdentifier(childArgs.subList(0, childArgs.size() -1));
- }
-
- private boolean parentNodeDoesNotExists(final LogicalDatastoreType store, final InstanceIdentifier normalizedPath) {
- try {
- return !getDelegate().read(store, parentPath(normalizedPath)).get().isPresent();
- } catch (InterruptedException | ExecutionException e) {
- throw new IllegalStateException(e);
- }
- }
-
@Override
public void removeConfigurationData(final InstanceIdentifier legacyPath) {
checkNotNull(legacyPath, "Path MUST NOT be null.");
}
+ @Override
+ public String toString() {
+ return "ChangeListenerNotifyTask [listeners=" + listeners + ", event=" + event + "]";
+ }
+
}
checkState(success, "Store snapshot and transaction snapshot differ. This should never happen.");
for (ChangeListenerNotifyTask task : listenerResolver.call()) {
+ LOG.trace("Scheduling invocation of listeners: {}",task);
executor.submit(task);
}
}
@Override
public void write(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
checkNotReady();
- mutableTree.write(path, data);
+ try {
+ LOG.trace("Tx: {} Write: {}:{}",getIdentifier(),path,data);
+ mutableTree.write(path, data);
+ // FIXME: Add checked exception
+ } catch (Exception e) {
+ LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e);
+ }
+ }
+
+ @Override
+ public void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ checkNotReady();
+ try {
+ LOG.trace("Tx: {} Merge: {}:{}",getIdentifier(),path,data);
+ mutableTree.merge(path, data);
+ // FIXME: Add checked exception
+ } catch (Exception e) {
+ LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e);
+ }
}
@Override
public void delete(final InstanceIdentifier path) {
checkNotReady();
- mutableTree.delete(path);
+ try {
+ LOG.trace("Tx: {} Delete: {}",getIdentifier(),path);
+ mutableTree.delete(path);
+ // FIXME: Add checked exception
+ } catch (Exception e) {
+ LOG.error("Tx: {}, failed to delete {} in {}",getIdentifier(),path,mutableTree,e);
+ }
}
protected final boolean isReady() {
@Override
public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final InstanceIdentifier path) {
- return Futures.immediateFuture(getMutatedView().read(path));
+ LOG.trace("Tx: {} Read: {}",getIdentifier(),path);
+ try {
+ return Futures.immediateFuture(getMutatedView().read(path));
+ } catch (Exception e) {
+ LOG.error("Tx: {} Failed Read of {}",getIdentifier(),path,e);
+ throw e;
+ }
}
}
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
resolveModificationFor(path).write(value);
}
+ public void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ checkSealed();
+ mergeImpl(resolveModificationFor(path),data);
+ }
+
+ private void mergeImpl(final OperationWithModification op,final NormalizedNode<?,?> data) {
+
+ if(data instanceof NormalizedNodeContainer<?,?,?>) {
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ NormalizedNodeContainer<?,?,NormalizedNode<PathArgument, ?>> dataContainer = (NormalizedNodeContainer) data;
+ for(NormalizedNode<PathArgument, ?> child : dataContainer.getValue()) {
+ PathArgument childId = child.getIdentifier();
+ mergeImpl(op.forChild(childId), child);
+ }
+ }
+ op.merge(data);
+ }
+
public void delete(final InstanceIdentifier path) {
checkSealed();
resolveModificationFor(path).delete();
return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
StoreUtils.increase(snapshot.getMetadataTree().getSubtreeVersion()));
} catch (Exception e) {
- LOG.error("Could not create snapshot for {}", path,e);
+ LOG.error("Could not create snapshot for {}:{}", path,modification,e);
throw e;
}
}
import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import com.google.common.base.Optional;
public class OperationWithModification {
private final NodeModification modification;
+
private final ModificationApplyOperation applyOperation;
private OperationWithModification(final ModificationApplyOperation op, final NodeModification mod) {
return this;
}
+ public NodeModification getModification() {
+ return modification;
+ }
+
+ public ModificationApplyOperation getApplyOperation() {
+ return applyOperation;
+ }
+
public boolean isApplicable(final Optional<StoreMetadataNode> data) {
return applyOperation.isApplicable(modification, data);
}
return new OperationWithModification(operation, modification);
}
+
+ public void merge(final NormalizedNode<?, ?> data) {
+ modification.merge(data);
+ applyOperation.verifyStructure(modification);
+
+ }
+
+ public OperationWithModification forChild(final PathArgument childId) {
+ NodeModification childMod = modification.modifyChild(childId);
+ Optional<ModificationApplyOperation> childOp = applyOperation.getChild(childId);
+ return from(childOp.get(),childMod);
+ }
}
\ No newline at end of file
switch (modification.getModificationType()) {
case SUBTREE_MODIFIED:
return resolveSubtreeChangeEvent(path, listeners, modification, before.get(), after.get());
+ case MERGE:
case WRITE:
if (before.isPresent()) {
return resolveReplacedEvent(path, listeners, before.get().getData(), after.get().getData());
switch (childMod.getModificationType()) {
case WRITE:
+ case MERGE:
case DELETE:
one.merge(resolveAnyChangeEvent(childPath, childListeners, childMod, childBefore, childAfter));
break;
import static com.google.common.base.Preconditions.checkArgument;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import com.google.common.base.Function;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
if (schemaNode instanceof ContainerSchemaNode) {
return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
} else if (schemaNode instanceof ListSchemaNode) {
- return new ListMapModificationStrategy((ListSchemaNode) schemaNode);
+ return fromListSchemaNode((ListSchemaNode) schemaNode);
} else if (schemaNode instanceof ChoiceNode) {
return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
} else if (schemaNode instanceof LeafListSchemaNode) {
throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
}
+ private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
+ List<QName> keyDefinition = schemaNode.getKeyDefinition();
+ if (keyDefinition == null || keyDefinition.isEmpty()) {
+ return new UnkeyedListModificationStrategy(schemaNode);
+ }
+ if (schemaNode.isUserOrdered()) {
+ return new OrderedMapModificationStrategy(schemaNode);
+ }
+
+ return new UnorderedMapModificationStrategy(schemaNode);
+ }
+
public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
AugmentationSchema augSchema = null;
- allAugments : for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
+ allAugments: for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
boolean containsAll = true;
- for(DataSchemaNode child : potential.getChildNodes()) {
- if(identifier.getPossibleChildNames().contains(child.getQName())) {
+ for (DataSchemaNode child : potential.getChildNodes()) {
+ if (identifier.getPossibleChildNames().contains(child.getQName())) {
augSchema = potential;
break allAugments;
}
}
}
- if(augSchema != null) {
- return new AugmentationModificationStrategy(augSchema,resolvedTree);
+ if (augSchema != null) {
+ return new AugmentationModificationStrategy(augSchema, resolvedTree);
}
return null;
}
-
-
protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
Optional<ModificationApplyOperation> potential = getChild(child);
checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
return isSubtreeModificationApplicable(modification, current);
case WRITE:
return isWriteApplicable(modification, current);
+ case MERGE:
+ return isMergeApplicable(modification,current);
case UNMODIFIED:
return true;
default:
}
}
+ private boolean isMergeApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
+ Optional<StoreMetadataNode> original = modification.getOriginal();
+ if (original.isPresent() && current.isPresent()) {
+ return isNotConflicting(original.get(), current.get());
+ } else if (current.isPresent()) {
+ return true;
+ }
+ return true;
+ }
+
protected boolean isWriteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
Optional<StoreMetadataNode> original = modification.getOriginal();
if (original.isPresent() && current.isPresent()) {
switch (modification.getModificationType()) {
case DELETE:
- return modification.storeSnapshot(Optional.<StoreMetadataNode>absent());
+ return modification.storeSnapshot(Optional.<StoreMetadataNode> absent());
case SUBTREE_MODIFIED:
- return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(), subtreeVersion)));
+ Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
+ modification);
+ return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
+ subtreeVersion)));
+ case MERGE:
+ if(currentMeta.isPresent()) {
+ return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
+ } // Fallback to write is intentional - if node is not preexisting merge is same as write
case WRITE:
return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
case UNMODIFIED:
}
}
+ protected abstract StoreMetadataNode applyMerge(NodeModification modification,
+ StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
+
protected abstract StoreMetadataNode applyWrite(NodeModification modification,
Optional<StoreMetadataNode> currentMeta, UnsignedLong subtreeVersion);
+ "is leaf type node. Subtree change is not allowed.");
}
+ @Override
+ protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
+ final UnsignedLong subtreeVersion) {
+ return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
+ }
+
@Override
protected StoreMetadataNode applyWrite(final NodeModification modification,
final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
UnsignedLong nodeVersion = subtreeVersion;
- if (currentMeta.isPresent()) {
- nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
- }
-
return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
.setData(modification.getWritenValue()).build();
}
}
+ @Override
+ protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
+ final UnsignedLong subtreeVersion) {
+ // For Node Containers - merge is same as subtree change - we only replace children.
+ return applySubtreeChange(modification, currentMeta, subtreeVersion);
+ }
+
@Override
public StoreMetadataNode applySubtreeChange(final NodeModification modification,
final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
NormalizedNodeContainerModificationStrategy {
private final T schema;
- private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder().build(
- CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
+ private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
+ .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
@Override
public ModificationApplyOperation apply(final PathArgument identifier) {
}
+ public static class UnkeyedListItemModificationStrategy extends
+ DataNodeContainerModificationStrategy<ListSchemaNode> {
+
+ public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
+ super(schemaNode, UnkeyedListEntryNode.class);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
+ checkArgument(identifier instanceof NodeIdentifier);
+ return ImmutableUnkeyedListEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ }
+
+ }
+
public static class AugmentationModificationStrategy extends
DataNodeContainerModificationStrategy<AugmentationSchema> {
}
-
@Override
protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
return Builders.augmentationBuilder().withNodeIdentifier((AugmentationIdentifier) identifier);
public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
private final ChoiceNode schema;
- private final Map<PathArgument,ModificationApplyOperation> childNodes;
+ private final Map<PathArgument, ModificationApplyOperation> childNodes;
public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
this.schema = schemaNode;
ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
- for(ChoiceCaseNode caze : schemaNode.getCases()) {
- for(DataSchemaNode cazeChild : caze.getChildNodes()) {
+ for (ChoiceCaseNode caze : schemaNode.getCases()) {
+ for (DataSchemaNode cazeChild : caze.getChildNodes()) {
SchemaAwareApplyOperation childNode = from(cazeChild);
- child.put(new NodeIdentifier(cazeChild.getQName()),childNode);
+ child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
}
}
childNodes = child.build();
}
- public static class ListMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+ public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
private final Optional<ModificationApplyOperation> entryStrategy;
- protected ListMapModificationStrategy(final ListSchemaNode schema) {
+ protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
+ entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
+ }
+
+ @Override
+ protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
+ final UnsignedLong subtreeVersion) {
+ return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
+ }
+
+ @Override
+ protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
+ final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
+ throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
+ }
+
+ @Override
+ protected StoreMetadataNode applyWrite(final NodeModification modification,
+ final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
+ return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+ if (child instanceof NodeIdentifier) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
+
+ }
+
+ @Override
+ protected boolean isSubtreeModificationApplicable(final NodeModification modification,
+ final Optional<StoreMetadataNode> current) {
+ return false;
+ }
+
+ }
+
+ public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
super(MapNode.class);
entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
}
@Override
public String toString() {
- return "ListMapModificationStrategy [entry=" + entryStrategy + "]";
+ return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
+ }
+ }
+
+ public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
+ super(OrderedMapNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
+ return ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+ if (identifier instanceof NodeIdentifierWithPredicates) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ public String toString() {
+ return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
}
}
* Tree node is to be deleted.
*
*/
- DELETE
+ DELETE,
+
+ /**
+ *
+ * Tree node is to be merged with existing one.
+ *
+ */
+ MERGE
}
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
-import com.google.common.primitives.UnsignedLong;
/**
* Node Modification Node and Tree
public static final Predicate<NodeModification> IS_TERMINAL_PREDICATE = new Predicate<NodeModification>() {
@Override
public boolean apply(final NodeModification input) {
- return input.getModificationType() == ModificationType.WRITE || input.getModificationType() == ModificationType.DELETE;
+ return input.getModificationType() == ModificationType.WRITE //
+ || input.getModificationType() == ModificationType.DELETE //
+ || input.getModificationType() == ModificationType.MERGE;
}
};
private final PathArgument identifier;
private NormalizedNode<?, ?> value;
- private UnsignedLong subtreeVersion;
private Optional<StoreMetadataNode> snapshotCache;
private final Map<PathArgument, NodeModification> childModification;
this.value = value;
}
+ public synchronized void merge(final NormalizedNode<?, ?> data) {
+ checkSealed();
+ clearSnapshot();
+ updateModificationType(ModificationType.MERGE);
+ // FIXME: Probably merge with previous value.
+ this.value = data;
+ }
+
@GuardedBy("this")
private void checkSealed() {
checkState(!sealed, "Node Modification is sealed. No further changes allowed.");
*/
void write(InstanceIdentifier path, NormalizedNode<?, ?> data);
+ /**
+ * Store a provided data at specified path. This acts as a add / replace
+ * operation, which is to say that whole subtree will be replaced by
+ * specified path.
+ *
+ * If you need add or merge of current object with specified use
+ * {@link #merge(LogicalDatastoreType, Path, Object)}
+ *
+ *
+ * @param path
+ * @param data
+ * Data object to be written
+ *
+ * @throws IllegalStateException
+ * if the client code already sealed transaction and invoked
+ * {@link #ready()}
+ */
+ void merge(InstanceIdentifier path, NormalizedNode<?, ?> data);
+
/**
*
* Deletes data and whole subtree located at provided path.
<groupId>${project.groupId}</groupId>
<artifactId>sal-connector-api</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>ietf-netconf-monitoring</artifactId>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
-
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${config.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
<executions>
<execution>
<goals>
--- /dev/null
+/*
+ * Copyright (c) 2014 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.sal.connect.netconf;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.INVENTORY_CONNECTED;
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.INVENTORY_ID;
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.INVENTORY_NODE;
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.INVENTORY_PATH;
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.NETCONF_INVENTORY_INITIAL_CAPABILITY;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.CONFIG_SOURCE_RUNNING;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_DATA_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_GET_CONFIG_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_GET_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.toFilterStructure;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.toRpcMessage;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.wrap;
+
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider;
+import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.opendaylight.yangtools.yang.parser.impl.util.YangSourceContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.ListenableFuture;
+import io.netty.util.concurrent.EventExecutor;
+
+public class NetconfDevice implements Provider, //
+ DataReader<InstanceIdentifier, CompositeNode>, //
+ DataCommitHandler<InstanceIdentifier, CompositeNode>, //
+ RpcImplementation, //
+ AutoCloseable {
+
+ InetSocketAddress socketAddress;
+
+ MountProvisionInstance mountInstance;
+
+ EventExecutor eventExecutor;
+
+ ExecutorService processingExecutor;
+
+ InstanceIdentifier path;
+
+ ReconnectStrategy reconnectStrategy;
+
+ AbstractCachingSchemaSourceProvider<String, InputStream> schemaSourceProvider;
+
+ private NetconfDeviceSchemaContextProvider deviceContextProvider;
+
+ protected Logger logger;
+
+ Registration<DataReader<InstanceIdentifier, CompositeNode>> operReaderReg;
+ Registration<DataReader<InstanceIdentifier, CompositeNode>> confReaderReg;
+ Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> commitHandlerReg;
+ List<RpcRegistration> rpcReg;
+
+ String name;
+
+ MountProvisionService mountService;
+
+ NetconfClientDispatcher dispatcher;
+
+ static InstanceIdentifier ROOT_PATH = InstanceIdentifier.builder().toInstance();
+
+ SchemaSourceProvider<InputStream> remoteSourceProvider;
+
+ DataBrokerService dataBroker;
+
+ NetconfDeviceListener listener;
+
+ private boolean rollbackSupported;
+
+
+ public NetconfDevice(String name) {
+ this.name = name;
+ this.logger = LoggerFactory.getLogger(NetconfDevice.class + "#" + name);
+ this.path = InstanceIdentifier.builder(INVENTORY_PATH)
+ .nodeWithKey(INVENTORY_NODE, Collections.<QName, Object>singletonMap(INVENTORY_ID, name)).toInstance();
+ }
+
+ public void start() {
+ checkState(dispatcher != null, "Dispatcher must be set.");
+ checkState(schemaSourceProvider != null, "Schema Source Provider must be set.");
+ checkState(eventExecutor != null, "Event executor must be set.");
+
+ listener = new NetconfDeviceListener(this);
+
+ logger.info("Starting NETCONF Client {} for address {}", name, socketAddress);
+
+ dispatcher.createClient(socketAddress, listener, reconnectStrategy);
+ }
+
+ Optional<SchemaContext> getSchemaContext() {
+ if (deviceContextProvider == null) {
+ return Optional.absent();
+ }
+ return deviceContextProvider.currentContext;
+ }
+
+ void bringDown() {
+ if (rpcReg != null) {
+ for (RpcRegistration reg : rpcReg) {
+ reg.close();
+ }
+ rpcReg = null;
+ }
+ closeGracefully(confReaderReg);
+ confReaderReg = null;
+ closeGracefully(operReaderReg);
+ operReaderReg = null;
+ closeGracefully(commitHandlerReg);
+ commitHandlerReg = null;
+
+ updateDeviceState(false, Collections.<QName> emptySet());
+ }
+
+ private void closeGracefully(final AutoCloseable resource) {
+ if (resource != null) {
+ try {
+ resource.close();
+ } catch (Exception e) {
+ logger.warn("Ignoring exception while closing {}", resource, e);
+ }
+ }
+ }
+
+ void bringUp(final SchemaSourceProvider<String> delegate, final Set<QName> capabilities, final boolean rollbackSupported) {
+ // This has to be called from separate thread, not from netty thread calling onSessionUp in DeviceListener.
+ // Reason: delegate.getSchema blocks thread when waiting for response
+ // however, if the netty thread is blocked, no incoming message can be processed
+ // ... netty should pick another thread from pool to process incoming message, but it does not http://netty.io/wiki/thread-model.html
+ // TODO redesign +refactor
+ processingExecutor.submit(new Runnable() {
+ @Override
+ public void run() {
+ NetconfDevice.this.rollbackSupported = rollbackSupported;
+ remoteSourceProvider = schemaSourceProvider.createInstanceFor(delegate);
+ deviceContextProvider = new NetconfDeviceSchemaContextProvider(NetconfDevice.this, remoteSourceProvider);
+ deviceContextProvider.createContextFromCapabilities(capabilities);
+ if (mountInstance != null && getSchemaContext().isPresent()) {
+ mountInstance.setSchemaContext(getSchemaContext().get());
+ }
+
+ updateDeviceState(true, capabilities);
+
+ if (mountInstance != null) {
+ confReaderReg = mountInstance.registerConfigurationReader(ROOT_PATH, NetconfDevice.this);
+ operReaderReg = mountInstance.registerOperationalReader(ROOT_PATH, NetconfDevice.this);
+ commitHandlerReg = mountInstance.registerCommitHandler(ROOT_PATH, NetconfDevice.this);
+
+ List<RpcRegistration> rpcs = new ArrayList<>();
+ // TODO same condition twice
+ if (mountInstance != null && getSchemaContext().isPresent()) {
+ for (RpcDefinition rpc : mountInstance.getSchemaContext().getOperations()) {
+ rpcs.add(mountInstance.addRpcImplementation(rpc.getQName(), NetconfDevice.this));
+ }
+ }
+ rpcReg = rpcs;
+ }
+ }
+ });
+ }
+
+ private void updateDeviceState(boolean up, Set<QName> capabilities) {
+ DataModificationTransaction transaction = dataBroker.beginTransaction();
+
+ CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder();
+ it.setQName(INVENTORY_NODE);
+ it.addLeaf(INVENTORY_ID, name);
+ it.addLeaf(INVENTORY_CONNECTED, up);
+
+ logger.debug("Client capabilities {}", capabilities);
+ for (QName capability : capabilities) {
+ it.addLeaf(NETCONF_INVENTORY_INITIAL_CAPABILITY, capability);
+ }
+
+ logger.debug("Update device state transaction " + transaction.getIdentifier()
+ + " putting operational data started.");
+ transaction.removeOperationalData(path);
+ transaction.putOperationalData(path, it.toInstance());
+ logger.debug("Update device state transaction " + transaction.getIdentifier()
+ + " putting operational data ended.");
+
+ // FIXME: this has to be asynchronous
+ RpcResult<TransactionStatus> transactionStatus = null;
+ try {
+ transactionStatus = transaction.commit().get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while waiting for response", e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException("Read configuration data " + path + " failed", e);
+ }
+ // TODO better ex handling
+
+ if (transactionStatus.isSuccessful()) {
+ logger.debug("Update device state transaction " + transaction.getIdentifier() + " SUCCESSFUL.");
+ } else {
+ logger.debug("Update device state transaction " + transaction.getIdentifier() + " FAILED!");
+ logger.debug("Update device state transaction status " + transaction.getStatus());
+ }
+ }
+
+ @Override
+ public CompositeNode readConfigurationData(InstanceIdentifier path) {
+ RpcResult<CompositeNode> result = null;
+ try {
+ result = this.invokeRpc(NETCONF_GET_CONFIG_QNAME,
+ wrap(NETCONF_GET_CONFIG_QNAME, CONFIG_SOURCE_RUNNING, toFilterStructure(path))).get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while waiting for response", e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException("Read configuration data " + path + " failed", e);
+ }
+
+ CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
+ return data == null ? null : (CompositeNode) findNode(data, path);
+ }
+
+ @Override
+ public CompositeNode readOperationalData(InstanceIdentifier path) {
+ RpcResult<CompositeNode> result = null;
+ try {
+ result = invokeRpc(NETCONF_GET_QNAME, wrap(NETCONF_GET_QNAME, toFilterStructure(path))).get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while waiting for response", e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException("Read configuration data " + path + " failed", e);
+ }
+
+ CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
+ return (CompositeNode) findNode(data, path);
+ }
+
+ @Override
+ public Set<QName> getSupportedRpcs() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
+ return listener.sendRequest(toRpcMessage(rpc, input, getSchemaContext()), rpc);
+ }
+
+ @Override
+ public Collection<ProviderFunctionality> getProviderFunctionality() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderSession session) {
+ dataBroker = session.getService(DataBrokerService.class);
+
+ DataModificationTransaction transaction = dataBroker.beginTransaction();
+ if (operationalNodeNotExisting(transaction)) {
+ transaction.putOperationalData(path, getNodeWithId());
+ }
+ if (configurationNodeNotExisting(transaction)) {
+ transaction.putConfigurationData(path, getNodeWithId());
+ }
+
+ try {
+ transaction.commit().get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while waiting for response", e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException("Read configuration data " + path + " failed", e);
+ }
+
+ mountService = session.getService(MountProvisionService.class);
+ if (mountService != null) {
+ mountInstance = mountService.createOrGetMountPoint(path);
+ }
+ }
+
+ CompositeNode getNodeWithId() {
+ SimpleNodeTOImpl id = new SimpleNodeTOImpl(INVENTORY_ID, null, name);
+ return new CompositeNodeTOImpl(INVENTORY_NODE, null, Collections.<Node<?>> singletonList(id));
+ }
+
+ boolean configurationNodeNotExisting(DataModificationTransaction transaction) {
+ return null == transaction.readConfigurationData(path);
+ }
+
+ boolean operationalNodeNotExisting(DataModificationTransaction transaction) {
+ return null == transaction.readOperationalData(path);
+ }
+
+ static Node<?> findNode(CompositeNode node, InstanceIdentifier identifier) {
+
+ Node<?> current = node;
+ for (InstanceIdentifier.PathArgument arg : identifier.getPath()) {
+ if (current instanceof SimpleNode<?>) {
+ return null;
+ } else if (current instanceof CompositeNode) {
+ CompositeNode currentComposite = (CompositeNode) current;
+
+ current = currentComposite.getFirstCompositeByName(arg.getNodeType());
+ if (current == null) {
+ current = currentComposite.getFirstCompositeByName(arg.getNodeType().withoutRevision());
+ }
+ if (current == null) {
+ current = currentComposite.getFirstSimpleByName(arg.getNodeType());
+ }
+ if (current == null) {
+ current = currentComposite.getFirstSimpleByName(arg.getNodeType().withoutRevision());
+ }
+ if (current == null) {
+ return null;
+ }
+ }
+ }
+ return current;
+ }
+
+ @Override
+ public DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
+ DataModification<InstanceIdentifier, CompositeNode> modification) {
+ NetconfDeviceTwoPhaseCommitTransaction twoPhaseCommit = new NetconfDeviceTwoPhaseCommitTransaction(this,
+ modification, true, rollbackSupported);
+ try {
+ twoPhaseCommit.prepare();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while waiting for response", e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException("Read configuration data " + path + " failed", e);
+ }
+ return twoPhaseCommit;
+ }
+
+ Set<QName> getCapabilities(Collection<String> capabilities) {
+ return FluentIterable.from(capabilities).filter(new Predicate<String>() {
+ @Override
+ public boolean apply(final String capability) {
+ return capability.contains("?") && capability.contains("module=") && capability.contains("revision=");
+ }
+ }).transform(new Function<String, QName>() {
+ @Override
+ public QName apply(final String capability) {
+ String[] parts = capability.split("\\?");
+ String namespace = parts[0];
+ FluentIterable<String> queryParams = FluentIterable.from(Arrays.asList(parts[1].split("&")));
+
+ String revision = getStringAndTransform(queryParams, "revision=", "revision=");
+
+ String moduleName = getStringAndTransform(queryParams, "module=", "module=");
+
+ if (revision == null) {
+ logger.warn("Netconf device was not reporting revision correctly, trying to get amp;revision=");
+ revision = getStringAndTransform(queryParams, "amp;revision==", "revision=");
+
+ if (revision != null) {
+ logger.warn("Netconf device returned revision incorectly escaped for {}", capability);
+ }
+ }
+ if (revision == null) {
+ return QName.create(URI.create(namespace), null, moduleName);
+ }
+ return QName.create(namespace, revision, moduleName);
+ }
+
+ private String getStringAndTransform(final Iterable<String> queryParams, final String match,
+ final String substringToRemove) {
+ Optional<String> found = Iterables.tryFind(queryParams, new Predicate<String>() {
+ @Override
+ public boolean apply(final String input) {
+ return input.startsWith(match);
+ }
+ });
+
+ return found.isPresent() ? found.get().replaceAll(substringToRemove, "") : null;
+ }
+
+ }).toSet();
+ }
+
+ @Override
+ public void close() {
+ bringDown();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public InetSocketAddress getSocketAddress() {
+ return socketAddress;
+ }
+
+ public MountProvisionInstance getMountInstance() {
+ return mountInstance;
+ }
+
+ public void setReconnectStrategy(final ReconnectStrategy reconnectStrategy) {
+ this.reconnectStrategy = reconnectStrategy;
+ }
+
+ public void setProcessingExecutor(final ExecutorService processingExecutor) {
+ this.processingExecutor = processingExecutor;
+ }
+
+ public void setSocketAddress(final InetSocketAddress socketAddress) {
+ this.socketAddress = socketAddress;
+ }
+
+ public void setEventExecutor(final EventExecutor eventExecutor) {
+ this.eventExecutor = eventExecutor;
+ }
+
+ public void setSchemaSourceProvider(final AbstractCachingSchemaSourceProvider<String, InputStream> schemaSourceProvider) {
+ this.schemaSourceProvider = schemaSourceProvider;
+ }
+
+ public void setDispatcher(final NetconfClientDispatcher dispatcher) {
+ this.dispatcher = dispatcher;
+ }
+}
+
+class NetconfDeviceSchemaContextProvider {
+
+ NetconfDevice device;
+
+ SchemaSourceProvider<InputStream> sourceProvider;
+
+ Optional<SchemaContext> currentContext;
+
+ NetconfDeviceSchemaContextProvider(NetconfDevice device, SchemaSourceProvider<InputStream> sourceProvider) {
+ this.device = device;
+ this.sourceProvider = sourceProvider;
+ this.currentContext = Optional.absent();
+ }
+
+ void createContextFromCapabilities(Iterable<QName> capabilities) {
+ YangSourceContext sourceContext = YangSourceContext.createFrom(capabilities, sourceProvider);
+ if (!sourceContext.getMissingSources().isEmpty()) {
+ device.logger.warn("Sources for following models are missing {}", sourceContext.getMissingSources());
+ }
+ device.logger.debug("Trying to create schema context from {}", sourceContext.getValidSources());
+ List<InputStream> modelsToParse = YangSourceContext.getValidInputStreams(sourceContext);
+ if (!sourceContext.getValidSources().isEmpty()) {
+ SchemaContext schemaContext = tryToCreateContext(modelsToParse);
+ currentContext = Optional.fromNullable(schemaContext);
+ } else {
+ currentContext = Optional.absent();
+ }
+ if (currentContext.isPresent()) {
+ device.logger.debug("Schema context successfully created.");
+ }
+ }
+
+ SchemaContext tryToCreateContext(List<InputStream> modelsToParse) {
+ YangParserImpl parser = new YangParserImpl();
+ try {
+
+ Set<Module> models = parser.parseYangModelsFromStreams(modelsToParse);
+ return parser.resolveSchemaContext(models);
+ } catch (Exception e) {
+ device.logger.debug("Error occured during parsing YANG schemas", e);
+ return null;
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.sal.connect.netconf
-
-import com.google.common.base.Optional
-import com.google.common.collect.FluentIterable
-import io.netty.util.concurrent.EventExecutor
-import java.io.InputStream
-import java.net.InetSocketAddress
-import java.net.URI
-import java.util.ArrayList
-import java.util.Collection
-import java.util.Collections
-import java.util.List
-import java.util.Set
-import java.util.concurrent.ExecutorService
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration
-import org.opendaylight.controller.sal.core.api.Provider
-import org.opendaylight.controller.sal.core.api.RpcImplementation
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
-import org.opendaylight.protocol.framework.ReconnectStrategy
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.data.api.SimpleNode
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider
-import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl
-import org.opendaylight.yangtools.yang.parser.impl.util.YangSourceContext
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-
-import static com.google.common.base.Preconditions.*
-import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.*
-
-import static extension org.opendaylight.controller.sal.connect.netconf.NetconfMapping.*
-
-class NetconfDevice implements Provider, //
-DataReader<InstanceIdentifier, CompositeNode>, //
-DataCommitHandler<InstanceIdentifier, CompositeNode>, //
-RpcImplementation, //
-AutoCloseable {
-
- @Property
- var InetSocketAddress socketAddress;
-
- @Property
- var MountProvisionInstance mountInstance;
-
- @Property
- var EventExecutor eventExecutor;
-
- @Property
- var ExecutorService processingExecutor;
-
- @Property
- var InstanceIdentifier path;
-
- @Property
- var ReconnectStrategy reconnectStrategy;
-
- @Property
- var AbstractCachingSchemaSourceProvider<String, InputStream> schemaSourceProvider;
-
- @Property
- private NetconfDeviceSchemaContextProvider deviceContextProvider
-
- protected val Logger logger
-
- Registration<DataReader<InstanceIdentifier, CompositeNode>> operReaderReg
- Registration<DataReader<InstanceIdentifier, CompositeNode>> confReaderReg
- Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> commitHandlerReg
- List<RpcRegistration> rpcReg
-
- @Property
- val String name
-
- MountProvisionService mountService
-
- @Property
- var NetconfClientDispatcher dispatcher
-
- static val InstanceIdentifier ROOT_PATH = InstanceIdentifier.builder().toInstance();
-
- @Property
- var SchemaSourceProvider<InputStream> remoteSourceProvider
-
- DataBrokerService dataBroker
-
- var NetconfDeviceListener listener;
-
- public new(String name) {
- this._name = name;
- this.logger = LoggerFactory.getLogger(NetconfDevice.name + "#" + name);
- this.path = InstanceIdentifier.builder(INVENTORY_PATH).nodeWithKey(INVENTORY_NODE,
- Collections.singletonMap(INVENTORY_ID, name)).toInstance;
- }
-
- def start() {
- checkState(dispatcher != null, "Dispatcher must be set.");
- checkState(schemaSourceProvider != null, "Schema Source Provider must be set.")
- checkState(eventExecutor != null, "Event executor must be set.");
-
- listener = new NetconfDeviceListener(this);
-
- logger.info("Starting NETCONF Client {} for address {}", name, socketAddress);
-
- dispatcher.createClient(socketAddress, listener, reconnectStrategy);
- }
-
- def Optional<SchemaContext> getSchemaContext() {
- if (deviceContextProvider == null) {
- return Optional.absent();
- }
- return deviceContextProvider.currentContext;
- }
-
- def bringDown() {
- if (rpcReg != null) {
- for (reg : rpcReg) {
- reg.close()
- }
- rpcReg = null
- }
- confReaderReg?.close()
- confReaderReg = null
- operReaderReg?.close()
- operReaderReg = null
- commitHandlerReg?.close()
- commitHandlerReg = null
-
- updateDeviceState(false, Collections.emptySet())
- }
-
- def bringUp(SchemaSourceProvider<String> delegate, Set<QName> capabilities) {
- remoteSourceProvider = schemaSourceProvider.createInstanceFor(delegate);
- deviceContextProvider = new NetconfDeviceSchemaContextProvider(this, remoteSourceProvider);
- deviceContextProvider.createContextFromCapabilities(capabilities);
- if (mountInstance != null && schemaContext.isPresent) {
- mountInstance.schemaContext = schemaContext.get();
- }
-
- updateDeviceState(true, capabilities)
-
- if (mountInstance != null) {
- confReaderReg = mountInstance.registerConfigurationReader(ROOT_PATH, this);
- operReaderReg = mountInstance.registerOperationalReader(ROOT_PATH, this);
- commitHandlerReg = mountInstance.registerCommitHandler(ROOT_PATH, this);
-
- val rpcs = new ArrayList<RpcRegistration>();
- for (rpc : mountInstance.schemaContext.operations) {
- rpcs.add(mountInstance.addRpcImplementation(rpc.QName, this));
- }
- rpcReg = rpcs
- }
- }
-
- private def updateDeviceState(boolean up, Set<QName> capabilities) {
- val transaction = dataBroker.beginTransaction
-
- val it = ImmutableCompositeNode.builder
- setQName(INVENTORY_NODE)
- addLeaf(INVENTORY_ID, name)
- addLeaf(INVENTORY_CONNECTED, up)
-
- logger.debug("Client capabilities {}", capabilities)
- for (capability : capabilities) {
- addLeaf(NETCONF_INVENTORY_INITIAL_CAPABILITY, capability)
- }
-
- logger.debug("Update device state transaction " + transaction.identifier + " putting operational data started.")
- transaction.removeOperationalData(path)
- transaction.putOperationalData(path, it.toInstance)
- logger.debug("Update device state transaction " + transaction.identifier + " putting operational data ended.")
-
- // FIXME: this has to be asynchronous
- val transactionStatus = transaction.commit.get;
-
- if (transactionStatus.successful) {
- logger.debug("Update device state transaction " + transaction.identifier + " SUCCESSFUL.")
- } else {
- logger.debug("Update device state transaction " + transaction.identifier + " FAILED!")
- logger.debug("Update device state transaction status " + transaction.status)
- }
- }
-
- override readConfigurationData(InstanceIdentifier path) {
- val result = invokeRpc(NETCONF_GET_CONFIG_QNAME,
- wrap(NETCONF_GET_CONFIG_QNAME, CONFIG_SOURCE_RUNNING, path.toFilterStructure())).get();
- val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
- return data?.findNode(path) as CompositeNode;
- }
-
- override readOperationalData(InstanceIdentifier path) {
- val result = invokeRpc(NETCONF_GET_QNAME, wrap(NETCONF_GET_QNAME, path.toFilterStructure())).get();
- val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
- return data?.findNode(path) as CompositeNode;
- }
-
- override getSupportedRpcs() {
- Collections.emptySet;
- }
-
- override invokeRpc(QName rpc, CompositeNode input) {
- return listener.sendRequest(rpc.toRpcMessage(input,schemaContext));
- }
-
- override getProviderFunctionality() {
- Collections.emptySet
- }
-
- override onSessionInitiated(ProviderSession session) {
- dataBroker = session.getService(DataBrokerService);
-
- val transaction = dataBroker.beginTransaction
- if (transaction.operationalNodeNotExisting) {
- transaction.putOperationalData(path, nodeWithId)
- }
- if (transaction.configurationNodeNotExisting) {
- transaction.putConfigurationData(path, nodeWithId)
- }
- transaction.commit().get();
- mountService = session.getService(MountProvisionService);
- mountInstance = mountService?.createOrGetMountPoint(path);
- }
-
- def getNodeWithId() {
- val id = new SimpleNodeTOImpl(INVENTORY_ID, null, name);
- return new CompositeNodeTOImpl(INVENTORY_NODE, null, Collections.singletonList(id));
- }
-
- def boolean configurationNodeNotExisting(DataModificationTransaction transaction) {
- return null === transaction.readConfigurationData(path);
- }
-
- def boolean operationalNodeNotExisting(DataModificationTransaction transaction) {
- return null === transaction.readOperationalData(path);
- }
-
- static def Node<?> findNode(CompositeNode node, InstanceIdentifier identifier) {
-
- var Node<?> current = node;
- for (arg : identifier.path) {
- if (current instanceof SimpleNode<?>) {
- return null;
- } else if (current instanceof CompositeNode) {
- val currentComposite = (current as CompositeNode);
-
- current = currentComposite.getFirstCompositeByName(arg.nodeType);
- if(current == null) {
- current = currentComposite.getFirstCompositeByName(arg.nodeType.withoutRevision());
- }
- if(current == null) {
- current = currentComposite.getFirstSimpleByName(arg.nodeType);
- }
- if (current == null) {
- current = currentComposite.getFirstSimpleByName(arg.nodeType.withoutRevision());
- } if (current == null) {
- return null;
- }
- }
- }
- return current;
- }
-
- override requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
- val twoPhaseCommit = new NetconfDeviceTwoPhaseCommitTransaction(this, modification, true);
- twoPhaseCommit.prepare()
- return twoPhaseCommit;
- }
-
- def getCapabilities(Collection<String> capabilities) {
- return FluentIterable.from(capabilities).filter[
- contains("?") && contains("module=") && contains("revision=")].transform [
- val parts = split("\\?");
- val namespace = parts.get(0);
- val queryParams = FluentIterable.from(parts.get(1).split("&"));
- var revision = queryParams.findFirst[startsWith("revision=")]?.replaceAll("revision=", "");
- val moduleName = queryParams.findFirst[startsWith("module=")]?.replaceAll("module=", "");
- if (revision === null) {
- logger.warn("Netconf device was not reporting revision correctly, trying to get amp;revision=");
- revision = queryParams.findFirst[startsWith("&revision=")]?.replaceAll("revision=", "");
- if (revision != null) {
- logger.warn("Netconf device returned revision incorectly escaped for {}", it)
- }
- }
- if (revision == null) {
- return QName.create(URI.create(namespace), null, moduleName);
- }
- return QName.create(namespace, revision, moduleName);
- ].toSet();
- }
-
- override close() {
- bringDown()
- }
-}
-
-package class NetconfDeviceSchemaContextProvider {
-
- @Property
- val NetconfDevice device;
-
- @Property
- val SchemaSourceProvider<InputStream> sourceProvider;
-
- @Property
- var Optional<SchemaContext> currentContext;
-
- new(NetconfDevice device, SchemaSourceProvider<InputStream> sourceProvider) {
- _device = device
- _sourceProvider = sourceProvider
- _currentContext = Optional.absent();
- }
-
- def createContextFromCapabilities(Iterable<QName> capabilities) {
- val sourceContext = YangSourceContext.createFrom(capabilities, sourceProvider)
- if (!sourceContext.missingSources.empty) {
- device.logger.warn("Sources for following models are missing {}", sourceContext.missingSources);
- }
- device.logger.debug("Trying to create schema context from {}", sourceContext.validSources)
- val modelsToParse = YangSourceContext.getValidInputStreams(sourceContext);
- if (!sourceContext.validSources.empty) {
- val schemaContext = tryToCreateContext(modelsToParse);
- currentContext = Optional.fromNullable(schemaContext);
- } else {
- currentContext = Optional.absent();
- }
- if (currentContext.present) {
- device.logger.debug("Schema context successfully created.");
- }
-
- }
-
- def SchemaContext tryToCreateContext(List<InputStream> modelsToParse) {
- val parser = new YangParserImpl();
- try {
-
- val models = parser.parseYangModelsFromStreams(modelsToParse);
- val result = parser.resolveSchemaContext(models);
- return result;
- } catch (Exception e) {
- device.logger.debug("Error occured during parsing YANG schemas", e);
- return null;
- }
- }
-}
*/
package org.opendaylight.controller.sal.connect.netconf;
+import com.google.common.collect.Sets;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import java.util.Queue;
import java.util.Set;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
import org.opendaylight.controller.netconf.client.NetconfClientSession;
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
import org.opendaylight.yangtools.yang.common.QName;
import com.google.common.util.concurrent.ListenableFuture;
class NetconfDeviceListener implements NetconfClientSessionListener {
+
private static final class Request {
final UncancellableFuture<RpcResult<CompositeNode>> future;
final NetconfMessage request;
+ final QName rpc;
- private Request(UncancellableFuture<RpcResult<CompositeNode>> future, NetconfMessage request) {
+ private Request(UncancellableFuture<RpcResult<CompositeNode>> future, NetconfMessage request, final QName rpc) {
this.future = future;
this.request = request;
+ this.rpc = rpc;
}
}
LOG.debug("Session with {} established as address {} session-id {}",
device.getName(), device.getSocketAddress(), session.getSessionId());
+ this.session = session;
+
final Set<QName> caps = device.getCapabilities(session.getServerCapabilities());
LOG.trace("Server {} advertized capabilities {}", device.getName(), caps);
final SchemaSourceProvider<String> delegate;
if (NetconfRemoteSchemaSourceProvider.isSupportedFor(caps)) {
delegate = new NetconfRemoteSchemaSourceProvider(device);
- } else if(caps.contains(NetconfRemoteSchemaSourceProvider.IETF_NETCONF_MONITORING.getNamespace().toString())) {
+ // FIXME caps do not contain urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring, since it is filtered out in getCapabilitites
+ } else if(session.getServerCapabilities().contains(NetconfRemoteSchemaSourceProvider.IETF_NETCONF_MONITORING.getNamespace().toString())) {
delegate = new NetconfRemoteSchemaSourceProvider(device);
} else {
LOG.info("Netconf server {} does not support IETF Netconf Monitoring", device.getName());
- delegate = SchemaSourceProviders.<String>noopProvider();
+ delegate = SchemaSourceProviders.noopProvider();
}
- device.bringUp(delegate, caps);
+ device.bringUp(delegate, caps, isRollbackSupported(session.getServerCapabilities()));
- this.session = session;
+ }
+
+ private static boolean isRollbackSupported(final Collection<String> serverCapabilities) {
+ // TODO rollback capability cannot be searched for in Set<QName> caps
+ // since this set does not contain module-less capabilities
+ return Sets.newHashSet(serverCapabilities).contains(NetconfMapping.NETCONF_ROLLBACK_ON_ERROR_URI.toString());
}
private synchronized void tearDown(final Exception e) {
requests.poll();
LOG.debug("Matched {} to {}", r.request, message);
- // FIXME: this can throw exceptions, which should result
- // in the future failing
- NetconfMapping.checkValidReply(r.request, message);
- r.future.set(Rpcs.getRpcResult(true, NetconfMapping.toNotificationNode(message, device.getSchemaContext()),
- Collections.<RpcError>emptyList()));
+ try {
+ NetconfMapping.checkValidReply(r.request, message);
+ } catch (IllegalStateException e) {
+ LOG.warn("Invalid request-reply match, reply message contains different message-id", e);
+ r.future.setException(e);
+ return;
+ }
+
+ try {
+ NetconfMapping.checkSuccessReply(message);
+ } catch (NetconfDocumentedException | IllegalStateException e) {
+ LOG.warn("Error reply from remote device", e);
+ r.future.setException(e);
+ return;
+ }
+
+ r.future.set(NetconfMapping.toRpcResult(message, r.rpc, device.getSchemaContext()));
} else {
LOG.warn("Ignoring unsolicited message", message);
}
}
- synchronized ListenableFuture<RpcResult<CompositeNode>> sendRequest(final NetconfMessage message) {
+ synchronized ListenableFuture<RpcResult<CompositeNode>> sendRequest(final NetconfMessage message, final QName rpc) {
if (session == null) {
LOG.debug("Session to {} is disconnected, failing RPC request {}", device.getName(), message);
return Futures.<RpcResult<CompositeNode>>immediateFuture(new RpcResult<CompositeNode>() {
});
}
- final Request req = new Request(new UncancellableFuture<RpcResult<CompositeNode>>(true), message);
+ final Request req = new Request(new UncancellableFuture<RpcResult<CompositeNode>>(true), message, rpc);
requests.add(req);
session.sendMessage(req.request).addListener(new FutureListener<Void>() {
public void operationComplete(final Future<Void> future) throws Exception {
if (!future.isSuccess()) {
// We expect that a session down will occur at this point
- LOG.debug("Failed to send request {}", req.request, future.cause());
+ LOG.debug("Failed to send request {}", XmlUtil.toString(req.request.getDocument()), future.cause());
req.future.setException(future.cause());
} else {
LOG.trace("Finished sending request {}", req.request);
import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_COMMIT_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_CONFIG_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_EDIT_CONFIG_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_ERROR_OPTION_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_OPERATION_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_RUNNING_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_TARGET_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.ROLLBACK_ON_ERROR_OPTION;
import java.util.Collection;
import java.util.Collections;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final DataModification<InstanceIdentifier, CompositeNode> modification;
private final NetconfDevice device;
private final boolean candidateSupported;
+ private final boolean rollbackSupported;
public NetconfDeviceTwoPhaseCommitTransaction(NetconfDevice device,
DataModification<InstanceIdentifier, CompositeNode> modification,
- boolean candidateSupported) {
+ boolean candidateSupported, boolean rollbackOnErrorSupported) {
this.device = Preconditions.checkNotNull(device);
this.modification = Preconditions.checkNotNull(modification);
this.candidateSupported = candidateSupported;
+ this.rollbackSupported = rollbackOnErrorSupported;
}
void prepare() throws InterruptedException, ExecutionException {
} else {
targetNode = ImmutableCompositeNode.create(NETCONF_RUNNING_QNAME, ImmutableList.<Node<?>>of());
}
+
Node<?> targetWrapperNode = ImmutableCompositeNode.create(NETCONF_TARGET_QNAME, ImmutableList.<Node<?>>of(targetNode));
+
+ if(rollbackSupported) {
+ LOG.debug("Rollback-on-error supported, setting {} to {}", NETCONF_ERROR_OPTION_QNAME, ROLLBACK_ON_ERROR_OPTION);
+ ret.addLeaf(NETCONF_ERROR_OPTION_QNAME, ROLLBACK_ON_ERROR_OPTION);
+ }
+
ret.add(targetWrapperNode);
return ret;
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.sal.connect.netconf;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.activation.UnsupportedDataTypeException;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class NetconfMapping {
+
+ public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
+ public static String NETCONF_MONITORING_URI = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring";
+ public static URI NETCONF_NOTIFICATION_URI = URI.create("urn:ietf:params:xml:ns:netconf:notification:1.0");
+ public static URI NETCONF_ROLLBACK_ON_ERROR_URI = URI.create("urn:ietf:params:netconf:capability:rollback-on-error:1.0");
+
+ public static QName NETCONF_QNAME = QName.create(NETCONF_URI, null, "netconf");
+ public static QName NETCONF_RPC_QNAME = QName.create(NETCONF_QNAME, "rpc");
+ public static QName NETCONF_GET_QNAME = QName.create(NETCONF_QNAME, "get");
+ public static QName NETCONF_FILTER_QNAME = QName.create(NETCONF_QNAME, "filter");
+ public static QName NETCONF_TYPE_QNAME = QName.create(NETCONF_QNAME, "type");
+ public static QName NETCONF_GET_CONFIG_QNAME = QName.create(NETCONF_QNAME, "get-config");
+ public static QName NETCONF_EDIT_CONFIG_QNAME = QName.create(NETCONF_QNAME, "edit-config");
+ public static QName NETCONF_DELETE_CONFIG_QNAME = QName.create(NETCONF_QNAME, "delete-config");
+ public static QName NETCONF_OPERATION_QNAME = QName.create(NETCONF_QNAME, "operation");
+ public static QName NETCONF_COMMIT_QNAME = QName.create(NETCONF_QNAME, "commit");
+
+ public static QName NETCONF_CONFIG_QNAME = QName.create(NETCONF_QNAME, "config");
+ public static QName NETCONF_SOURCE_QNAME = QName.create(NETCONF_QNAME, "source");
+ public static QName NETCONF_TARGET_QNAME = QName.create(NETCONF_QNAME, "target");
+
+ public static QName NETCONF_CANDIDATE_QNAME = QName.create(NETCONF_QNAME, "candidate");
+ public static QName NETCONF_RUNNING_QNAME = QName.create(NETCONF_QNAME, "running");
+
+ public static QName NETCONF_ERROR_OPTION_QNAME = QName.create(NETCONF_QNAME, "error-option");
+ public static String ROLLBACK_ON_ERROR_OPTION = "rollback-on-error";
+
+ public static QName NETCONF_RPC_REPLY_QNAME = QName.create(NETCONF_QNAME, "rpc-reply");
+ public static QName NETCONF_OK_QNAME = QName.create(NETCONF_QNAME, "ok");
+ public static QName NETCONF_DATA_QNAME = QName.create(NETCONF_QNAME, "data");
+ public static QName NETCONF_CREATE_SUBSCRIPTION_QNAME = QName.create(NETCONF_NOTIFICATION_URI, null,
+ "create-subscription");
+ public static QName NETCONF_CANCEL_SUBSCRIPTION_QNAME = QName.create(NETCONF_NOTIFICATION_URI, null,
+ "cancel-subscription");
+ public static QName IETF_NETCONF_MONITORING_MODULE = QName.create(NETCONF_MONITORING_URI, "2010-10-04",
+ "ietf-netconf-monitoring");
+
+ static List<Node<?>> RUNNING = Collections.<Node<?>> singletonList(new SimpleNodeTOImpl(NETCONF_RUNNING_QNAME,
+ null, null));
+
+ public static CompositeNode CONFIG_SOURCE_RUNNING = new CompositeNodeTOImpl(NETCONF_SOURCE_QNAME, null, RUNNING);
+
+ static AtomicInteger messageId = new AtomicInteger(0);
+
+ static Node<?> toFilterStructure(InstanceIdentifier identifier) {
+ Node<?> previous = null;
+ if (identifier.getPath().isEmpty()) {
+ return null;
+ }
+
+ for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument component : Lists
+ .reverse(identifier.getPath())) {
+ previous = toNode(component, previous);
+ }
+ return filter("subtree", previous);
+ }
+
+ static Node<?> toNode(NodeIdentifierWithPredicates argument, Node<?> node) {
+ List<Node<?>> list = new ArrayList<>();
+ for (Map.Entry<QName, Object> arg : argument.getKeyValues().entrySet()) {
+ list.add(new SimpleNodeTOImpl(arg.getKey(), null, arg.getValue()));
+ }
+ if (node != null) {
+ list.add(node);
+ }
+ return new CompositeNodeTOImpl(argument.getNodeType(), null, list);
+ }
+
+ static Node<?> toNode(PathArgument argument, Node<?> node) {
+ if (node != null) {
+ return new CompositeNodeTOImpl(argument.getNodeType(), null, Collections.<Node<?>> singletonList(node));
+ } else {
+ return new SimpleNodeTOImpl(argument.getNodeType(), null, null);
+ }
+ }
+
+ static CompositeNode toCompositeNode(NetconfMessage message, Optional<SchemaContext> ctx) {
+ // TODO: implement general normalization to normalize incoming Netconf
+ // Message
+ // for Schema Context counterpart
+ return null;
+ }
+
+ static CompositeNode toNotificationNode(NetconfMessage message, Optional<SchemaContext> ctx) {
+ if (ctx.isPresent()) {
+ SchemaContext schemaContext = ctx.get();
+ Set<NotificationDefinition> notifications = schemaContext.getNotifications();
+ Document document = message.getDocument();
+ return XmlDocumentUtils.notificationToDomNodes(document, Optional.fromNullable(notifications));
+ }
+ return null;
+ }
+
+ static NetconfMessage toRpcMessage(QName rpc, CompositeNode node, Optional<SchemaContext> ctx) {
+ CompositeNodeTOImpl rpcPayload = wrap(NETCONF_RPC_QNAME, flattenInput(node));
+ Document w3cPayload = null;
+ try {
+ w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, XmlDocumentUtils.defaultValueCodecProvider());
+ } catch (UnsupportedDataTypeException e) {
+ throw new IllegalArgumentException("Unable to create message", e);
+ }
+ w3cPayload.getDocumentElement().setAttribute("message-id", "m-" + messageId.getAndIncrement());
+ return new NetconfMessage(w3cPayload);
+ }
+
+ static CompositeNode flattenInput(final CompositeNode node) {
+ final QName inputQName = QName.create(node.getNodeType(), "input");
+ CompositeNode input = node.getFirstCompositeByName(inputQName);
+ if (input == null)
+ return node;
+ if (input instanceof CompositeNode) {
+
+ List<Node<?>> nodes = ImmutableList.<Node<?>> builder() //
+ .addAll(input.getChildren()) //
+ .addAll(Collections2.filter(node.getChildren(), new Predicate<Node<?>>() {
+ @Override
+ public boolean apply(@Nullable final Node<?> input) {
+ return input.getNodeType() != inputQName;
+ }
+ })) //
+ .build();
+
+ return ImmutableCompositeNode.create(node.getNodeType(), nodes);
+ }
+
+ return input;
+ }
+
+ static RpcResult<CompositeNode> toRpcResult(NetconfMessage message, final QName rpc, Optional<SchemaContext> context) {
+ CompositeNode rawRpc;
+ if (context.isPresent())
+ if (isDataRetrieQNameReply(rpc)) {
+
+ Element xmlData = getDataSubtree(message.getDocument());
+
+ List<org.opendaylight.yangtools.yang.data.api.Node<?>> dataNodes = XmlDocumentUtils.toDomNodes(xmlData,
+ Optional.of(context.get().getDataDefinitions()));
+
+ CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder();
+ it.setQName(NETCONF_RPC_REPLY_QNAME);
+ it.add(ImmutableCompositeNode.create(NETCONF_DATA_QNAME, dataNodes));
+
+ rawRpc = it.toInstance();
+ // sys(xmlData)
+ } else {
+ rawRpc = (CompositeNode) toCompositeNode(message.getDocument());
+ }
+ else {
+ rawRpc = (CompositeNode) toCompositeNode(message.getDocument());
+ }
+ // rawRpc.
+ return Rpcs.getRpcResult(true, rawRpc, Collections.<RpcError> emptySet());
+ }
+
+ static Element getDataSubtree(Document doc) {
+ return (Element) doc.getElementsByTagNameNS(NETCONF_URI.toString(), "data").item(0);
+ }
+
+ static boolean isDataRetrieQNameReply(QName it) {
+ return NETCONF_URI == it.getNamespace()
+ && (it.getLocalName() == NETCONF_GET_CONFIG_QNAME.getLocalName() || it.getLocalName() == NETCONF_GET_QNAME
+ .getLocalName());
+ }
+
+ static CompositeNodeTOImpl wrap(QName name, Node<?> node) {
+ if (node != null) {
+ return new CompositeNodeTOImpl(name, null, Collections.<Node<?>> singletonList(node));
+ } else {
+ return new CompositeNodeTOImpl(name, null, Collections.<Node<?>> emptyList());
+ }
+ }
+
+ static CompositeNodeTOImpl wrap(QName name, Node<?> additional, Node<?> node) {
+ if (node != null) {
+ return new CompositeNodeTOImpl(name, null, ImmutableList.of(additional, node));
+ } else {
+ return new CompositeNodeTOImpl(name, null, ImmutableList.<Node<?>> of(additional));
+ }
+ }
+
+ static ImmutableCompositeNode filter(String type, Node<?> node) {
+ CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder(); //
+ it.setQName(NETCONF_FILTER_QNAME);
+ it.setAttribute(NETCONF_TYPE_QNAME, type);
+ if (node != null) {
+ return it.add(node).toInstance();
+ } else {
+ return it.toInstance();
+ }
+ }
+
+ public static Node<?> toCompositeNode(Document document) {
+ return XmlDocumentUtils.toDomNode(document);
+ }
+
+ public static void checkValidReply(NetconfMessage input, NetconfMessage output) {
+ String inputMsgId = input.getDocument().getDocumentElement().getAttribute("message-id");
+ String outputMsgId = output.getDocument().getDocumentElement().getAttribute("message-id");
+
+ if(inputMsgId.equals(outputMsgId) == false) {
+ String requestXml = XmlUtil.toString(input.getDocument());
+ String responseXml = XmlUtil.toString(output.getDocument());
+ throw new IllegalStateException(String.format("Rpc request and reply message IDs must be same. Request: %s, response: %s", requestXml, responseXml));
+ }
+ }
+
+ public static void checkSuccessReply(NetconfMessage output) throws NetconfDocumentedException {
+ if(NetconfMessageUtil.isErrorMessage(output)) {
+ throw new IllegalStateException(String.format("Response contains error: %s", XmlUtil.toString(output.getDocument())));
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.sal.connect.netconf
-
-import com.google.common.base.Optional
-import com.google.common.base.Preconditions
-import com.google.common.collect.ImmutableList
-import java.net.URI
-import java.util.ArrayList
-import java.util.Collections
-import java.util.List
-import java.util.Set
-import java.util.concurrent.atomic.AtomicInteger
-import org.opendaylight.controller.netconf.api.NetconfMessage
-import org.opendaylight.controller.sal.common.util.Rpcs
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.w3c.dom.Document
-import org.w3c.dom.Element
-
-class NetconfMapping {
-
- public static val NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0")
- public static val NETCONF_MONITORING_URI = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"
- public static val NETCONF_NOTIFICATION_URI = URI.create("urn:ietf:params:xml:ns:netconf:notification:1.0")
-
-
- public static val NETCONF_QNAME = QName.create(NETCONF_URI, null, "netconf");
- public static val NETCONF_RPC_QNAME = QName.create(NETCONF_QNAME, "rpc");
- public static val NETCONF_GET_QNAME = QName.create(NETCONF_QNAME, "get");
- public static val NETCONF_FILTER_QNAME = QName.create(NETCONF_QNAME, "filter");
- public static val NETCONF_TYPE_QNAME = QName.create(NETCONF_QNAME, "type");
- public static val NETCONF_GET_CONFIG_QNAME = QName.create(NETCONF_QNAME, "get-config");
- public static val NETCONF_EDIT_CONFIG_QNAME = QName.create(NETCONF_QNAME, "edit-config");
- public static val NETCONF_DELETE_CONFIG_QNAME = QName.create(NETCONF_QNAME, "delete-config");
- public static val NETCONF_OPERATION_QNAME = QName.create(NETCONF_QNAME, "operation");
- public static val NETCONF_COMMIT_QNAME = QName.create(NETCONF_QNAME, "commit");
-
- public static val NETCONF_CONFIG_QNAME = QName.create(NETCONF_QNAME, "config");
- public static val NETCONF_SOURCE_QNAME = QName.create(NETCONF_QNAME, "source");
- public static val NETCONF_TARGET_QNAME = QName.create(NETCONF_QNAME, "target");
-
- public static val NETCONF_CANDIDATE_QNAME = QName.create(NETCONF_QNAME, "candidate");
- public static val NETCONF_RUNNING_QNAME = QName.create(NETCONF_QNAME, "running");
-
-
- public static val NETCONF_RPC_REPLY_QNAME = QName.create(NETCONF_QNAME, "rpc-reply");
- public static val NETCONF_OK_QNAME = QName.create(NETCONF_QNAME, "ok");
- public static val NETCONF_DATA_QNAME = QName.create(NETCONF_QNAME, "data");
- public static val NETCONF_CREATE_SUBSCRIPTION_QNAME = QName.create(NETCONF_NOTIFICATION_URI,null,"create-subscription");
- public static val NETCONF_CANCEL_SUBSCRIPTION_QNAME = QName.create(NETCONF_NOTIFICATION_URI,null,"cancel-subscription");
- public static val IETF_NETCONF_MONITORING_MODULE = QName.create(NETCONF_MONITORING_URI, "2010-10-04","ietf-netconf-monitoring");
-
- static List<Node<?>> RUNNING = Collections.<Node<?>>singletonList(
- new SimpleNodeTOImpl(NETCONF_RUNNING_QNAME, null, null));
- public static val CONFIG_SOURCE_RUNNING = new CompositeNodeTOImpl(NETCONF_SOURCE_QNAME, null, RUNNING);
-
- static val messageId = new AtomicInteger(0);
-
- static def Node<?> toFilterStructure(InstanceIdentifier identifier) {
- var Node<?> previous = null;
- if(identifier.path.empty) {
- return null;
- }
-
- for (component : identifier.path.reverseView) {
- val Node<?> current = component.toNode(previous);
- previous = current;
- }
- return filter("subtree",previous);
- }
-
- static def dispatch Node<?> toNode(NodeIdentifierWithPredicates argument, Node<?> node) {
- val list = new ArrayList<Node<?>>();
- for (arg : argument.keyValues.entrySet) {
- list.add = new SimpleNodeTOImpl(arg.key, null, arg.value);
- }
- if (node != null) {
- list.add(node);
- }
- return new CompositeNodeTOImpl(argument.nodeType, null, list)
- }
-
- static def dispatch Node<?> toNode(PathArgument argument, Node<?> node) {
- if (node != null) {
- return new CompositeNodeTOImpl(argument.nodeType, null, Collections.singletonList(node));
- } else {
- return new SimpleNodeTOImpl(argument.nodeType, null, null);
- }
- }
-
- static def CompositeNode toCompositeNode(NetconfMessage message,Optional<SchemaContext> ctx) {
- //TODO: implement general normalization to normalize incoming Netconf Message
- // for Schema Context counterpart
- return null
- }
-
- static def CompositeNode toNotificationNode(NetconfMessage message,Optional<SchemaContext> ctx) {
- if (ctx.present) {
- val schemaContext = ctx.get
- val notifications = schemaContext.notifications
- val document = message.document
- return XmlDocumentUtils.notificationToDomNodes(document, Optional.<Set<NotificationDefinition>>fromNullable(notifications))
- }
- return null
- }
-
- static def NetconfMessage toRpcMessage(QName rpc, CompositeNode node,Optional<SchemaContext> ctx) {
- val rpcPayload = wrap(NETCONF_RPC_QNAME, flattenInput(node))
- val w3cPayload = XmlDocumentUtils.toDocument(rpcPayload, XmlDocumentUtils.defaultValueCodecProvider)
- w3cPayload.documentElement.setAttribute("message-id", "m-" + messageId.andIncrement)
- return new NetconfMessage(w3cPayload);
- }
-
- def static flattenInput(CompositeNode node) {
- val inputQName = QName.create(node.nodeType,"input");
- val input = node.getFirstCompositeByName(inputQName);
- if(input == null) return node;
- if(input instanceof CompositeNode) {
-
- val nodes = ImmutableList.builder() //
- .addAll(input.children) //
- .addAll(node.children.filter[nodeType != inputQName]) //
- .build()
- return ImmutableCompositeNode.create(node.nodeType,nodes);
- }
-
- }
-
- static def RpcResult<CompositeNode> toRpcResult(NetconfMessage message,QName rpc,Optional<SchemaContext> context) {
- var CompositeNode rawRpc;
- if(context.present) {
- if(isDataRetrievalReply(rpc)) {
-
- val xmlData = message.document.dataSubtree
- val dataNodes = XmlDocumentUtils.toDomNodes(xmlData, Optional.of(context.get.dataDefinitions))
-
- val it = ImmutableCompositeNode.builder()
- setQName(NETCONF_RPC_REPLY_QNAME)
- add(ImmutableCompositeNode.create(NETCONF_DATA_QNAME, dataNodes));
-
- rawRpc = it.toInstance;
- //sys(xmlData)
- } else {
- val rpcSchema = context.get.operations.findFirst[QName == rpc]
- rawRpc = message.document.toCompositeNode() as CompositeNode;
- }
- } else {
- rawRpc = message.document.toCompositeNode() as CompositeNode;
- }
- //rawRpc.
- return Rpcs.getRpcResult(true, rawRpc, Collections.emptySet());
- }
-
- def static Element getDataSubtree(Document doc) {
- doc.getElementsByTagNameNS(NETCONF_URI.toString,"data").item(0) as Element
- }
-
- def static boolean isDataRetrievalReply(QName it) {
- return NETCONF_URI == namespace && ( localName == NETCONF_GET_CONFIG_QNAME.localName || localName == NETCONF_GET_QNAME.localName)
- }
-
- static def wrap(QName name, Node<?> node) {
- if (node != null) {
- return new CompositeNodeTOImpl(name, null, Collections.singletonList(node));
- } else {
- return new CompositeNodeTOImpl(name, null, Collections.emptyList());
- }
- }
-
- static def wrap(QName name, Node<?> additional, Node<?> node) {
- if (node != null) {
- return new CompositeNodeTOImpl(name, null, ImmutableList.of(additional, node));
- } else {
- return new CompositeNodeTOImpl(name, null, ImmutableList.of(additional));
- }
- }
-
- static def filter(String type, Node<?> node) {
- val it = ImmutableCompositeNode.builder(); //
- setQName(NETCONF_FILTER_QNAME);
- setAttribute(NETCONF_TYPE_QNAME,type);
- if (node != null) {
- return add(node).toInstance();
- } else {
- return toInstance();
- }
- }
-
- public static def Node<?> toCompositeNode(Document document) {
- return XmlDocumentUtils.toDomNode(document) as Node<?>
- }
-
- public static def checkValidReply(NetconfMessage input, NetconfMessage output) {
- val inputMsgId = input.document.documentElement.getAttribute("message-id")
- val outputMsgId = output.document.documentElement.getAttribute("message-id")
- Preconditions.checkState(inputMsgId == outputMsgId,"Rpc request and reply message IDs must be same.");
-
- }
-
-}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider<String> {
private final NetconfDevice device;
+ private final Logger logger;
+
public NetconfRemoteSchemaSourceProvider(NetconfDevice device) {
this.device = Preconditions.checkNotNull(device);
+ logger = LoggerFactory.getLogger(NetconfDevice.class + "#" + device.getName());
}
@Override
request.addLeaf("version", revision.get());
}
- device.logger.trace("Loading YANG schema source for {}:{}", moduleName, revision);
+ logger.trace("Loading YANG schema source for {}:{}", moduleName, revision);
try {
RpcResult<CompositeNode> schemaReply = device.invokeRpc(GET_SCHEMA_QNAME, request.toInstance()).get();
if (schemaReply.isSuccessful()) {
return Optional.of(schemaBody);
}
}
- device.logger.warn("YANG shcema was not successfully retrieved.");
+ logger.warn("YANG shcema was not successfully retrieved.");
} catch (InterruptedException | ExecutionException e) {
- device.logger.warn("YANG shcema was not successfully retrieved.", e);
+ logger.warn("YANG shcema was not successfully retrieved.", e);
}
return Optional.absent();
}
<properties>
<stax.version>1.0.1</stax.version>
- <yang.jmx.plugin>0.2.4-SNAPSHOT</yang.jmx.plugin>
<zeromq.version>0.3.1</zeromq.version>
</properties>
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${yang.jmx.plugin}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
<executions>
<execution>
<goals>
// it could be identityref Built-In Type
URI namespace = getNamespaceFor(value);
if (namespace != null) {
- return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null);
+ return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null,value);
}
// it is not "prefix:value" but just "value"
return value;
if (xPathParts.length < 2) { // must be at least "/pr:node"
return null;
}
- IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO();
+ IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO(value);
for (int i = 1; i < xPathParts.length; i++) {
String xPathPartTrimmed = xPathParts[i].trim();
if (namespaceAndValue.length == 2) {
String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
if (namespace != null && !namespace.isEmpty()) {
- return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0]);
+ return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0],value);
}
}
// it is not "prefix:value" but just "value"
public final class IdentityValuesDTO {
private final List<IdentityValue> elementData = new ArrayList<>();
+ private final String originValue;
- public IdentityValuesDTO(String namespace, String value, String prefix) {
+ public IdentityValuesDTO(String namespace, String value, String prefix,String originValue) {
elementData.add(new IdentityValue(namespace, value, prefix));
+ this.originValue = originValue;
+ }
+
+ public IdentityValuesDTO(String originValue) {
+ this.originValue = originValue;
}
public IdentityValuesDTO() {
-
+ originValue = null;
}
public void add(String namespace, String value, String prefix) {
public String toString() {
return elementData.toString();
}
+
+ public String getOriginValue() {
+ return originValue;
+ }
public static final class IdentityValue {
input == null ? "null" : input.getClass(), String.valueOf(input));
return null;
} else if (type instanceof LeafrefTypeDefinition) {
+ if (input instanceof IdentityValuesDTO) {
+ return LEAFREF_DEFAULT_CODEC.deserialize(((IdentityValuesDTO)input).getOriginValue());
+ }
return LEAFREF_DEFAULT_CODEC.deserialize(input);
} else if (type instanceof InstanceIdentifierTypeDefinition) {
if (input instanceof IdentityValuesDTO) {
TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec
.from(type);
if (typeAwarecodec != null) {
+ if (input instanceof IdentityValuesDTO) {
+ return typeAwarecodec.deserialize(((IdentityValuesDTO)input).getOriginValue());
+ }
return typeAwarecodec.deserialize(String.valueOf(input));
} else {
logger.debug("Codec for type \"" + type.getQName().getLocalName()
@Override
public IdentityValuesDTO serialize(QName data) {
- return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix());
+ return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix(),null);
}
@Override
if (schema.typeDefinition instanceof IdentityrefTypeDefinition) {
if (value instanceof String) {
- inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null)
+ inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null,value as String);
} // else value is already instance of IdentityValuesDTO
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+
+public class XmlAndJsonToCnSnLeafRefTest extends YangAndXmlAndDataSchemaLoader {
+
+ @BeforeClass
+ public static void initialize() {
+ dataLoad("/leafref/yang", 2, "leafref-module", "cont");
+ }
+
+ @Test
+ public void loadXmlToCnSn() throws WebApplicationException, IOException, URISyntaxException {
+ CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/xml/xmldata.xml", XmlToCompositeNodeProvider.INSTANCE);
+ TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
+ verifyContPredicate(cnSn, "/ns:cont/ns:lf1", "/cont/lf1", "/ns:cont/ns:lf1", "../lf1");
+ }
+
+ @Test
+ public void loadJsonToCnSn() throws WebApplicationException, IOException, URISyntaxException {
+ CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/json/jsondata.json",
+ JsonToCompositeNodeProvider.INSTANCE);
+ TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
+ verifyContPredicate(cnSn, "/leafref-module:cont/leafref-module:lf1", "/leafref-module:cont/leafref-module:lf1",
+ "/referenced-module:cont/referenced-module:lf1", "/leafref-module:cont/leafref-module:lf1");
+ }
+
+ private void verifyContPredicate(CompositeNode cnSn, String... values) throws URISyntaxException {
+ Object lf2Value = null;
+ Object lf3Value = null;
+ Object lf4Value = null;
+ Object lf5Value = null;
+
+ for (Node<?> node : cnSn.getValue()) {
+ if (node.getNodeType().getLocalName().equals("lf2")) {
+ lf2Value = ((SimpleNode<?>) node).getValue();
+ } else if (node.getNodeType().getLocalName().equals("lf3")) {
+ lf3Value = ((SimpleNode<?>) node).getValue();
+ } else if (node.getNodeType().getLocalName().equals("lf4")) {
+ lf4Value = ((SimpleNode<?>) node).getValue();
+ } else if (node.getNodeType().getLocalName().equals("lf5")) {
+ lf5Value = ((SimpleNode<?>) node).getValue();
+ }
+ }
+ assertEquals(values[0], lf2Value);
+ assertEquals(values[1], lf3Value);
+ assertEquals(values[2], lf4Value);
+ assertEquals(values[3], lf5Value);
+ }
+
+}
--- /dev/null
+{
+ "leafref-module:cont" : {
+ "lf4" : "/referenced-module:cont/referenced-module:lf1",
+ "lf2" : "/leafref-module:cont/leafref-module:lf1",
+ "lf3" : "/leafref-module:cont/leafref-module:lf1",
+ "lf5" : "/leafref-module:cont/leafref-module:lf1"
+ }
+}
\ No newline at end of file
--- /dev/null
+<cont xmlns="leafref:module">
+ <lf4 xmlns:ns="referenced:module">/ns:cont/ns:lf1</lf4>
+ <lf2 xmlns:ns="leafref:module">/ns:cont/ns:lf1</lf2>
+ <lf3 xmlns:ns="leafref:module">/cont/lf1</lf3>
+ <lf5 xmlns:ns="leafref:module">../lf1</lf5>
+</cont>
--- /dev/null
+module leafref-module {
+ namespace "leafref:module";
+
+
+ prefix "lfrfmodule";
+
+ import referenced-module { prefix refmod; revision-date 2014-04-17;}
+
+
+ revision 2014-04-17 {
+ }
+
+
+ container cont {
+ leaf lf1 {
+ type instance-identifier;
+ }
+
+ leaf lf2 {
+ type leafref {
+ path "../lf1";
+ }
+ }
+
+ leaf lf3 {
+ type leafref {
+ path "/refmod:cont/refmod:lf1";
+ }
+ }
+
+ leaf lf4 {
+ type leafref {
+ path "/cont/lf1";
+ }
+ }
+
+ leaf lf5 {
+ type leafref {
+ path "../lf1";
+ }
+ }
+
+ }
+}
\ No newline at end of file
--- /dev/null
+module referenced-module {
+ namespace "referenced:module";
+
+ prefix "refmodule";
+ revision 2014-04-17 {
+ }
+
+ container cont {
+ leaf lf1 {
+ type instance-identifier;
+ }
+ }
+}
\ No newline at end of file
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+
import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService;
import org.opendaylight.controller.sample.l2switch.md.util.InstanceIdentifierUtils;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
.setBufferId(0L) //
.setHardTimeout(0) //
.setIdleTimeout(0) //
- .setCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement()))
+ .setCookie(new FlowCookie(BigInteger.valueOf(flowCookieInc.getAndIncrement())))
.setFlags(new FlowModFlags(false, false, false, false, false));
return macToMacFlow.build();
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${config.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- </dependency>
- </dependencies>
<executions>
<execution>
<id>config</id>
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${config.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- </dependency>
- </dependencies>
<executions>
<execution>
<id>config</id>
private final TimerTask task = new TimerTask() {
@Override
public void run() {
- requestPeriodicStatistics();
- cleanStaleStatistics();
+ try{
+ requestPeriodicStatistics();
+ cleanStaleStatistics();
+ }catch(Exception e){
+ logger.warn("Exception occured while sending statistics request : {}",e);
+ }
}
};
<groupId>equinoxSDK381</groupId>
<artifactId>org.eclipse.osgi</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
<manifestLocation>${project.basedir}/META-INF</manifestLocation>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
</plugins>
</build>
<scm>
--- /dev/null
+/**
+ * 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.md.controller.topology.lldp;
+
+import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.osgi.framework.BundleContext;
+
+public class LLDPActivator extends AbstractBindingAwareProvider {
+ private static LLDPDiscoveryProvider provider = new LLDPDiscoveryProvider();
+
+ public void onSessionInitiated(final ProviderContext session) {
+ DataProviderService dataService = session.<DataProviderService>getSALService(DataProviderService.class);
+ provider.setDataService(dataService);
+ NotificationProviderService notificationService = session.<NotificationProviderService>getSALService(NotificationProviderService.class);
+ provider.setNotificationService(notificationService);
+ provider.start();
+ }
+
+ protected void stopImpl(final BundleContext context) {
+ provider.close();
+ }
+}
+++ /dev/null
-/*
- * 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.md.controller.topology.lldp
-
-import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.osgi.framework.BundleContext
-
-class LLDPActivator extends AbstractBindingAwareProvider {
-
- static var LLDPDiscoveryProvider provider = new LLDPDiscoveryProvider();
-
- override onSessionInitiated(ProviderContext session) {
- provider.dataService = session.getSALService(DataProviderService)
- provider.notificationService = session.getSALService(NotificationProviderService)
- provider.start();
- }
-
- override protected stopImpl(BundleContext context) {
- provider.close();
- }
-
-}
--- /dev/null
+/**
+ * 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.md.controller.topology.lldp;
+
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LLDPDiscoveryProvider implements AutoCloseable {
+ private final static Logger LOG = LoggerFactory.getLogger(LLDPDiscoveryProvider.class);
+ private DataProviderService dataService;
+ private NotificationProviderService notificationService;
+ private final LLDPDiscoveryListener commiter = new LLDPDiscoveryListener(LLDPDiscoveryProvider.this);
+ private Registration<NotificationListener> listenerRegistration;
+
+ public DataProviderService getDataService() {
+ return this.dataService;
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+
+ public NotificationProviderService getNotificationService() {
+ return this.notificationService;
+ }
+
+ public void setNotificationService(final NotificationProviderService notificationService) {
+ this.notificationService = notificationService;
+ }
+
+ public void start() {
+ Registration<NotificationListener> registerNotificationListener = this.getNotificationService().registerNotificationListener(this.commiter);
+ this.listenerRegistration = registerNotificationListener;
+ LLDPLinkAger.getInstance().setManager(this);
+ LOG.info("LLDPDiscoveryListener Started.");
+ }
+
+ public void close() {
+ try {
+ LOG.info("LLDPDiscoveryListener stopped.");
+ if (this.listenerRegistration!=null) {
+ this.listenerRegistration.close();
+ }
+ LLDPLinkAger.getInstance().close();
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+}
+++ /dev/null
-/*
- * 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.md.controller.topology.lldp
-
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yangtools.concepts.Registration
-import org.opendaylight.yangtools.yang.binding.NotificationListener
-import org.slf4j.LoggerFactory
-
-class LLDPDiscoveryProvider implements AutoCloseable {
-
-
- static val LOG = LoggerFactory.getLogger(LLDPDiscoveryProvider);
-
- @Property
- DataProviderService dataService;
-
- @Property
- NotificationProviderService notificationService;
-
- val LLDPDiscoveryListener commiter = new LLDPDiscoveryListener(this);
-
- Registration<NotificationListener> listenerRegistration
-
- def void start() {
- listenerRegistration = notificationService.registerNotificationListener(commiter);
- LLDPLinkAger.instance.manager = this;
- LOG.info("LLDPDiscoveryListener Started.");
-
- }
-
- override close() {
- LOG.info("LLDPDiscoveryListener stopped.");
- listenerRegistration?.close();
- LLDPLinkAger.instance.close();
- }
-
-}
-
-
org.opendaylight.controller.netconf.confignetconfconnector.transactions,
org.opendaylight.controller.netconf.confignetconfconnector.util,
org.opendaylight.controller.netconf.confignetconfconnector.osgi,
- org.opendaylight.controller.config.util,</Private-Package>
+ org.opendaylight.controller.config.util,
+ org.opendaylight.controller.netconf.confignetconfconnector.exception,</Private-Package>
<Import-Package>com.google.common.base,
com.google.common.collect,
javax.annotation,
org.opendaylight.controller.netconf.mapping.api,
org.opendaylight.controller.netconf.util.mapping,
org.opendaylight.controller.netconf.util.xml,
+ org.opendaylight.controller.netconf.util.exception,
org.opendaylight.yangtools.yang.common,
org.opendaylight.yangtools.yang.model.api,
org.osgi.framework,
com.google.common.io,
org.opendaylight.yangtools.yang.model.api.type,
org.opendaylight.yangtools.sal.binding.generator.spi,
- org.opendaylight.yangtools.sal.binding.yang.types</Import-Package>
+ org.opendaylight.yangtools.sal.binding.yang.types,</Import-Package>
<Export-Package></Export-Package>
</instructions>
</configuration>
--- /dev/null
+/*
+ * 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.confignetconfconnector.exception;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class NetconfConfigHandlingException extends NetconfDocumentedException {
+
+ public NetconfConfigHandlingException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity) {
+ this(message, errorType, errorTag, errorSeverity, Collections.<String, String>emptyMap());
+ }
+
+ public NetconfConfigHandlingException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity, final Map<String, String> errorInfo){
+ super(message,errorType,errorTag,errorSeverity,errorInfo);
+ }
+}
--- /dev/null
+/*
+ * 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.confignetconfconnector.exception;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class NoTransactionFoundException extends NetconfDocumentedException {
+
+ public NoTransactionFoundException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity) {
+ this(message, errorType, errorTag, errorSeverity, Collections.<String, String> emptyMap());
+ }
+
+ public NoTransactionFoundException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity, final Map<String, String> errorInfo){
+ super(message,errorType,errorTag,errorSeverity,errorInfo);
+ }
+
+}
--- /dev/null
+/*
+ * 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.confignetconfconnector.exception;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class OperationNotPermittedException extends NetconfDocumentedException {
+
+ public OperationNotPermittedException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity) {
+ this(message, errorType, errorTag, errorSeverity, Collections.<String, String> emptyMap());
+ }
+
+ public OperationNotPermittedException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity, final Map<String, String> errorInfo){
+ super(message,errorType,errorTag,errorSeverity,errorInfo);
+ }
+}
public abstract class AttributeIfcSwitchStatement<T> {
- protected AttributeIfc lastAttribute;
+ private AttributeIfc lastAttribute;
public T switchAttribute(AttributeIfc attributeIfc) {
return caseJavaUnionAttribute(openType);
} else if(((JavaAttribute)attributeIfc).isIdentityRef()) {
return caseJavaIdentityRefAttribute(openType);
- } else
+ } else {
return caseJavaAttribute(openType);
+ }
} catch (UnknownOpenTypeException e) {
throw getIllegalArgumentException(attributeIfc);
}
throw getIllegalArgumentException(attributeIfc);
}
+ public AttributeIfc getLastAttribute() {
+ return lastAttribute;
+ }
+
protected T caseJavaIdentityRefAttribute(OpenType<?> openType) {
return caseJavaAttribute(openType);
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import java.util.List;
}
@Override
- public AttributeConfigElement readElement(List<XmlElement> configNodes) {
- if (configNodes.size() == 0)
+ public AttributeConfigElement readElement(List<XmlElement> configNodes) throws NetconfDocumentedException {
+ if (configNodes.size() == 0){
return AttributeConfigElement.createNullValue(postprocessNullableDefault(nullableDefault));
-
+ }
return readElementHook(configNodes);
}
- abstract AttributeConfigElement readElementHook(List<XmlElement> configNodes);
+ abstract AttributeConfigElement readElementHook(List<XmlElement> configNodes) throws NetconfDocumentedException;
protected Object postprocessNullableDefault(String nullableDefault) {
return nullableDefault;
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
import com.google.common.collect.Lists;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import java.util.List;
}
@Override
- AttributeConfigElement readElementHook(List<XmlElement> configNodes) {
+ AttributeConfigElement readElementHook(List<XmlElement> configNodes) throws NetconfDocumentedException {
List<Object> innerList = Lists.newArrayList();
for (int i = 0; i < configNodes.size(); i++) {
innerList.add(innerStrategy.readElement(Lists.newArrayList(configNodes.get(i))).getValue());
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
import javax.management.openmbean.OpenType;
}
public void resolveValue(AttributeResolvingStrategy<?, ? extends OpenType<?>> attributeResolvingStrategy,
- String attrName) {
+ String attrName) throws NetconfDocumentedException {
resolvedValue = attributeResolvingStrategy.parseAttribute(attrName, value);
Optional<?> resolvedDefault = attributeResolvingStrategy.parseAttribute(attrName, dafaultValue);
resolvedDefaultValue = resolvedDefault.isPresent() ? resolvedDefault.get() : null;
import java.util.List;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
public interface AttributeReadingStrategy {
- public abstract AttributeConfigElement readElement(List<XmlElement> element);
+ public abstract AttributeConfigElement readElement(List<XmlElement> element) throws NetconfDocumentedException;
}
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import java.util.List;
}
@Override
- AttributeConfigElement readElementHook(List<XmlElement> configNodes) {
+ AttributeConfigElement readElementHook(List<XmlElement> configNodes) throws NetconfDocumentedException {
Preconditions.checkState(configNodes.size() == 1, "This element should be present only once %s", configNodes);
List<XmlElement> recognisedChildren = Lists.newArrayList();
for (Entry<String, AttributeReadingStrategy> innerAttrEntry : innerStrategies.entrySet()) {
- List<XmlElement> childItem = complexElement.getChildElementsWithSameNamespace(innerAttrEntry.getKey());
+ List<XmlElement> childItem = null;
+ childItem = complexElement.getChildElementsWithSameNamespace(innerAttrEntry.getKey());
recognisedChildren.addAll(childItem);
AttributeConfigElement resolvedInner = innerAttrEntry.getValue().readElement(childItem);
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
import com.google.common.base.Preconditions;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
private static final Object PREFIX_SEPARATOR = ":";
+ private static final Logger logger = LoggerFactory.getLogger(ObjectNameAttributeReadingStrategy.class);
public ObjectNameAttributeReadingStrategy(String nullableDefault) {
super(nullableDefault);
}
@Override
- AttributeConfigElement readElementHook(List<XmlElement> configNodes) {
+ AttributeConfigElement readElementHook(List<XmlElement> configNodes) throws NetconfDocumentedException {
XmlElement firstChild = configNodes.get(0);
Preconditions.checkState(configNodes.size() == 1, "This element should be present only once " + firstChild
return AttributeConfigElement.create(getNullableDefault(), resolve(firstChild));
}
- private ObjectNameAttributeMappingStrategy.MappedDependency resolve(XmlElement firstChild) {
- XmlElement typeElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+ private ObjectNameAttributeMappingStrategy.MappedDependency resolve(XmlElement firstChild) throws NetconfDocumentedException{
+ XmlElement typeElement = null;
+ typeElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
Map.Entry<String, String> prefixNamespace = typeElement.findNamespaceOfTextContent();
String serviceName = checkPrefixAndExtractServiceName(typeElement, prefixNamespace);
dependencyName);
}
- public static String checkPrefixAndExtractServiceName(XmlElement typeElement, Map.Entry<String, String> prefixNamespace) {
+ public static String checkPrefixAndExtractServiceName(XmlElement typeElement, Map.Entry<String, String> prefixNamespace) throws NetconfDocumentedException {
String serviceName = typeElement.getTextContent();
- Preconditions.checkState(prefixNamespace.equals("") == false, "Service %s value not prefixed with namespace",
+ Preconditions.checkState(!prefixNamespace.equals(""), "Service %s value not prefixed with namespace",
XmlNetconfConstants.TYPE_KEY);
String prefix = prefixNamespace.getKey() + PREFIX_SEPARATOR;
Preconditions.checkState(serviceName.startsWith(prefix),
@Override
protected AttributeReadingStrategy caseJavaBinaryAttribute(OpenType<?> openType) {
- return new SimpleBinaryAttributeReadingStrategy(lastAttribute.getNullableDefault());
+ return new SimpleBinaryAttributeReadingStrategy(getLastAttribute().getNullableDefault());
}
@Override
protected AttributeReadingStrategy caseJavaUnionAttribute(OpenType<?> openType) {
String mappingKey = JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
- return new SimpleUnionAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey);
+ return new SimpleUnionAttributeReadingStrategy(getLastAttribute().getNullableDefault(), mappingKey);
}
@Override
public AttributeReadingStrategy caseJavaSimpleAttribute(SimpleType<?> openType) {
- return new SimpleAttributeReadingStrategy(lastAttribute.getNullableDefault());
+ return new SimpleAttributeReadingStrategy(getLastAttribute().getNullableDefault());
}
@Override
public AttributeReadingStrategy caseJavaArrayAttribute(ArrayType<?> openType) {
- SimpleAttributeReadingStrategy innerStrategy = new SimpleAttributeReadingStrategy(lastAttribute.getNullableDefault());
- return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
+ SimpleAttributeReadingStrategy innerStrategy = new SimpleAttributeReadingStrategy(getLastAttribute().getNullableDefault());
+ return new ArrayAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategy);
}
@Override
public AttributeReadingStrategy caseJavaCompositeAttribute(CompositeType openType) {
Preconditions.checkState(openType.keySet().size() == 1, "Unexpected number of elements for open type %s, should be 1", openType);
String mappingKey = openType.keySet().iterator().next();
- return new SimpleCompositeAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey);
+ return new SimpleCompositeAttributeReadingStrategy(getLastAttribute().getNullableDefault(), mappingKey);
}
@Override
Set<String> keys = ((CompositeType) openType).keySet();
Preconditions.checkState(keys.size() == 1, "Unexpected number of elements for open type %s, should be 1", openType);
String mappingKey = keys.iterator().next();
- return new SimpleIdentityRefAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey, identityMap);
+ return new SimpleIdentityRefAttributeReadingStrategy(getLastAttribute().getNullableDefault(), mappingKey, identityMap);
}
@Override
protected AttributeReadingStrategy caseDependencyAttribute(SimpleType<?> openType) {
- return new ObjectNameAttributeReadingStrategy(lastAttribute.getNullableDefault());
+ return new ObjectNameAttributeReadingStrategy(getLastAttribute().getNullableDefault());
}
@Override
protected AttributeReadingStrategy caseTOAttribute(CompositeType openType) {
- Preconditions.checkState(lastAttribute instanceof TOAttribute);
- Map<String, AttributeIfc> inner = ((TOAttribute)lastAttribute).getYangPropertiesToTypesMap();
+ Preconditions.checkState(getLastAttribute() instanceof TOAttribute);
+ Map<String, AttributeIfc> inner = ((TOAttribute)getLastAttribute()).getYangPropertiesToTypesMap();
Map<String, AttributeReadingStrategy> innerStrategies = Maps.newHashMap();
innerStrategies.put(innerAttrEntry.getKey(), innerStrat);
}
- return new CompositeAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategies);
+ return new CompositeAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategies);
}
@Override
protected AttributeReadingStrategy caseListAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListAttribute);
- AttributeReadingStrategy innerStrategy = prepareReadingStrategy(key, ((ListAttribute) lastAttribute).getInnerAttribute());
- return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
+ Preconditions.checkState(getLastAttribute() instanceof ListAttribute);
+ AttributeReadingStrategy innerStrategy = prepareReadingStrategy(key, ((ListAttribute) getLastAttribute()).getInnerAttribute());
+ return new ArrayAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategy);
}
@Override
protected AttributeReadingStrategy caseListDependeciesAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListDependenciesAttribute);
AttributeReadingStrategy innerStrategy = caseDependencyAttribute(SimpleType.OBJECTNAME);
- return new ArrayAttributeReadingStrategy(lastAttribute.getNullableDefault(), innerStrategy);
+ return new ArrayAttributeReadingStrategy(getLastAttribute().getNullableDefault(), innerStrategy);
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
import com.google.common.base.Preconditions;
+import java.util.List;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.List;
-
public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
private static final Logger logger = LoggerFactory.getLogger(SimpleAttributeReadingStrategy.class);
}
@Override
- AttributeConfigElement readElementHook(List<XmlElement> configNodes) {
+ AttributeConfigElement readElementHook(List<XmlElement> configNodes) throws NetconfDocumentedException {
XmlElement xmlElement = configNodes.get(0);
Preconditions.checkState(configNodes.size() == 1, "This element should be present only once " + xmlElement
+ " but was " + configNodes.size());
logger.warn("Ignoring exception caused by failure to read text element", e);
}
- Preconditions.checkNotNull(textContent, "This element should contain text %s", xmlElement);
+ if (null == textContent){
+ throw new NetconfDocumentedException(String.format("This element should contain text %s", xmlElement),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
return AttributeConfigElement.create(postprocessNullableDefault(getNullableDefault()),
postprocessParsedValue(textContent));
}
- protected String readElementContent(XmlElement xmlElement) {
+ protected String readElementContent(XmlElement xmlElement) throws NetconfDocumentedException {
return xmlElement.getTextContent();
}
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.yangtools.yang.common.QName;
}
@Override
- protected String readElementContent(XmlElement xmlElement) {
+ protected String readElementContent(XmlElement xmlElement) throws NetconfDocumentedException {
// TODO test
Map.Entry<String, String> namespaceOfTextContent = xmlElement.findNamespaceOfTextContent();
String content = xmlElement.getTextContent();
revision = date;
}
}
- } else
+ } else {
revision = revisions.keySet().iterator().next();
-
+ }
return QName.create(URI.create(namespace), revision, localName).toString();
}
@Override
public Optional<List<Object>> mapAttribute(Object value) {
- if (value == null)
+ if (value == null){
return Optional.absent();
+ }
Preconditions.checkArgument(value.getClass().isArray(), "Value has to be instanceof Array ");
for (int i = 0; i < Array.getLength(value); i++) {
Object innerValue = Array.get(value, i);
- // String expectedClassName =
- // getOpenType().getElementOpenType().getClassName();
- // String realClassName = value.getClass().getName();
-
- // Preconditions.checkState(realClassName.contains(expectedClassName),
- // "Element in collection/array should be of type " +
- // expectedClassName + " but was "
- // + realClassName + " for attribute: " + getOpenType());
-
Optional<?> mapAttribute = innerElementStrategy.mapAttribute(innerValue);
- if (mapAttribute.isPresent())
+ if (mapAttribute.isPresent()){
retVal.add(mapAttribute.get());
+ }
}
return Optional.of(retVal);
@Override
public Optional<Map<String, Object>> mapAttribute(Object value) {
- if (value == null)
+ if (value == null){
return Optional.absent();
+ }
Util.checkType(value, CompositeDataSupport.class);
for (String jmxName : jmxToJavaNameMapping.keySet()) {
Optional<?> mapped = mapInnerAttribute(compositeData, jmxName, expectedType.getDescription(jmxName));
- if(mapped.isPresent())
+ if(mapped.isPresent()){
retVal.put(jmxToJavaNameMapping.get(jmxName), mapped.get());
+ }
}
return Optional.of(retVal);
AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = innerStrategies
.get(jmxName);
- Optional<?> mapAttribute = attributeMappingStrategy.mapAttribute(innerValue);
- return mapAttribute;
+ return attributeMappingStrategy.mapAttribute(innerValue);
}
}
@Override
protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseDependencyAttribute(
SimpleType<?> openType) {
- return new ObjectNameAttributeMappingStrategy(openType, dependencyTracker,
+ return new ObjectNameAttributeMappingStrategy(openType,
serviceNameOfDepAttr, namespaceOfDepAttr);
}
protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseTOAttribute(CompositeType openType) {
Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> innerStrategies = Maps.newHashMap();
- Preconditions.checkState(lastAttribute instanceof TOAttribute);
- TOAttribute lastTO = (TOAttribute) lastAttribute;
+ Preconditions.checkState(getLastAttribute() instanceof TOAttribute);
+ TOAttribute lastTO = (TOAttribute) getLastAttribute();
- for (Entry<String, AttributeIfc> innerAttrEntry : ((TOAttribute)lastAttribute).getJmxPropertiesToTypesMap().entrySet()) {
+ for (Entry<String, AttributeIfc> innerAttrEntry : ((TOAttribute)getLastAttribute()).getJmxPropertiesToTypesMap().entrySet()) {
innerStrategies.put(innerAttrEntry.getKey(), prepareStrategy(innerAttrEntry.getValue()));
}
@Override
protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseListAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListAttribute);
return new ArrayAttributeMappingStrategy(openType,
- prepareStrategy(((ListAttribute) lastAttribute).getInnerAttribute()));
+ prepareStrategy(((ListAttribute) getLastAttribute()).getInnerAttribute()));
}
@Override
protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseListDependeciesAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListDependenciesAttribute);
return new ArrayAttributeMappingStrategy(openType, caseDependencyAttribute(SimpleType.OBJECTNAME));
}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
-import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
-
import javax.management.ObjectName;
import javax.management.openmbean.SimpleType;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
public class ObjectNameAttributeMappingStrategy extends
AbstractAttributeMappingStrategy<ObjectNameAttributeMappingStrategy.MappedDependency, SimpleType<?>> {
- private final ServiceRegistryWrapper tracker;
private final String serviceName;
private final String namespace;
- public ObjectNameAttributeMappingStrategy(SimpleType<?> openType, ServiceRegistryWrapper dependencyTracker, String serviceName, String namespace) {
+ public ObjectNameAttributeMappingStrategy(SimpleType<?> openType, String serviceName, String namespace) {
super(openType);
- this.tracker = dependencyTracker;
this.serviceName = serviceName;
this.namespace = namespace;
}
@Override
public Optional<MappedDependency> mapAttribute(Object value) {
- if (value == null)
+ if (value == null){
return Optional.absent();
+ }
String expectedClass = getOpenType().getClassName();
String realClass = value.getClass().getName();
@Override
public Optional<String> mapAttribute(Object value) {
- if (value == null)
+ if (value == null){
return Optional.absent();
+ }
String expectedClass = getOpenType().getClassName();
String realClass = value.getClass().getName();
@Override
protected Optional<?> mapInnerAttribute(CompositeDataSupport compositeData, String jmxName, String description) {
- if(description.equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION) == false)
+ if(!description.equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION)){
return Optional.absent();
-
+ }
return super.mapInnerAttribute(compositeData, jmxName, description);
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving;
import com.google.common.base.Optional;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
@Override
- public Optional<Object> parseAttribute(String attrName, Object value) {
+ public Optional<Object> parseAttribute(String attrName, Object value) throws NetconfDocumentedException {
if (value == null) {
return Optional.absent();
}
if (innerTypeResolvingStrategy.getOpenType() instanceof CompositeType) {
innerTypeClass = CompositeDataSupport.class;
- } else
+ } else {
try {
innerTypeClass = Class.forName(getOpenType().getElementOpenType().getClassName());
} catch (ClassNotFoundException e) {
- throw new RuntimeException("Unable to locate class for "
+ throw new IllegalStateException("Unable to locate class for "
+ getOpenType().getElementOpenType().getClassName(), e);
}
+ }
Object parsedArray = null;
if (getOpenType().isPrimitiveArray()) {
Class<?> primitiveType = getPrimitiveType(innerTypeClass);
parsedArray = Array.newInstance(primitiveType, valueList.size());
- } else
+ } else {
parsedArray = Array.newInstance(innerTypeClass, valueList.size());
+ }
int i = 0;
for (Object innerValue : valueList) {
Optional<?> parsedElement = innerTypeResolvingStrategy.parseAttribute(attrName + "_" + i, innerValue);
-
- if (!parsedElement.isPresent())
+ if (!parsedElement.isPresent()){
continue;
-
+ }
Array.set(parsedArray, i, parsedElement.get());
- // parsedArray[i] = parsedElement.get();
i++;
}
try {
return (Class<?>) innerTypeClass.getField("TYPE").get(null);
} catch (Exception e) {
- throw new RuntimeException("Unable to determine primitive type to " + innerTypeClass);
+ throw new IllegalStateException("Unable to determine primitive type to " + innerTypeClass);
}
}
import com.google.common.base.Optional;
import javax.management.openmbean.OpenType;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
/**
* Create real object from String or Map that corresponds to given opentype.
public interface AttributeResolvingStrategy<T, O extends OpenType<?>> {
O getOpenType();
- Optional<T> parseAttribute(String attrName, Object value);
+ Optional<T> parseAttribute(String attrName, Object value) throws NetconfDocumentedException;
}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
@Override
- public Optional<CompositeDataSupport> parseAttribute(String attrName, Object value) {
+ public Optional<CompositeDataSupport> parseAttribute(String attrName, Object value) throws NetconfDocumentedException {
if (value == null) {
return Optional.absent();
try {
parsedValue = new CompositeDataSupport(getOpenType(), items);
} catch (OpenDataException e) {
- throw new RuntimeException("An error occured during restoration of composite type " + this
+ throw new IllegalStateException("An error occured during restoration of composite type " + this
+ " for attribute " + attrName + " from value " + value, e);
}
@Override
protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseTOAttribute(CompositeType openType) {
- Preconditions.checkState(lastAttribute instanceof TOAttribute);
- TOAttribute toAttribute = (TOAttribute) lastAttribute;
+ Preconditions.checkState(getLastAttribute() instanceof TOAttribute);
+ TOAttribute toAttribute = (TOAttribute) getLastAttribute();
Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerMap = Maps.newHashMap();
@Override
protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseListAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListAttribute);
- AttributeIfc innerAttribute = ((ListAttribute) lastAttribute).getInnerAttribute();
+ Preconditions.checkState(getLastAttribute() instanceof ListAttribute);
+ AttributeIfc innerAttribute = ((ListAttribute) getLastAttribute()).getInnerAttribute();
return new ArrayAttributeResolvingStrategy(prepareStrategy(innerAttribute), openType);
}
@Override
protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseListDependeciesAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListDependenciesAttribute);
return new ArrayAttributeResolvingStrategy(caseDependencyAttribute(SimpleType.OBJECTNAME), openType);
}
import com.google.common.base.Optional;
import com.google.common.collect.Maps;
+import java.lang.reflect.InvocationTargetException;
+import java.text.ParseException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
@Override
- public Optional<Object> parseAttribute(String attrName, Object value) {
+ public Optional<Object> parseAttribute(String attrName, Object value) throws NetconfDocumentedException {
if (value == null) {
return Optional.absent();
}
}
static interface Resolver {
- Object resolveObject(Class<?> type, String attrName, String value);
+ Object resolveObject(Class<?> type, String attrName, String value) throws NetconfDocumentedException;
}
static class DefaultResolver implements Resolver {
@Override
- public Object resolveObject(Class<?> type, String attrName, String value) {
+ public Object resolveObject(Class<?> type, String attrName, String value) throws NetconfDocumentedException {
try {
- Object parsedValue = parseObject(type, value);
- return parsedValue;
+ return parseObject(type, value);
} catch (Exception e) {
- throw new RuntimeException("Unable to resolve attribute " + attrName + " from " + value, e);
+ throw new NetconfDocumentedException("Unable to resolve attribute " + attrName + " from " + value,
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
}
- protected Object parseObject(Class<?> type, String value) throws Exception {
- Method method = type.getMethod("valueOf", String.class);
- Object parsedValue = method.invoke(null, value);
- return parsedValue;
+ protected Object parseObject(Class<?> type, String value) throws NetconfDocumentedException {
+ Method method = null;
+ try {
+ method = type.getMethod("valueOf", String.class);
+ return method.invoke(null, value);
+ } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+ logger.trace("Error parsing object {}",e);
+ throw new NetconfDocumentedException("Error parsing object.",
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
}
}
static class StringResolver extends DefaultResolver {
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
+ protected Object parseObject(Class<?> type, String value) {
return value;
}
}
static class BigIntegerResolver extends DefaultResolver {
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
+ protected Object parseObject(Class<?> type, String value) {
return new BigInteger(value);
}
}
static class BigDecimalResolver extends DefaultResolver {
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
+ protected Object parseObject(Class<?> type, String value) {
return new BigDecimal(value);
}
}
static class CharResolver extends DefaultResolver {
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
+ protected Object parseObject(Class<?> type, String value) {
return new Character(value.charAt(0));
}
}
static class DateResolver extends DefaultResolver {
-
@Override
- protected Object parseObject(Class<?> type, String value) throws Exception {
- return Util.readDate(value);
+ protected Object parseObject(Class<?> type, String value) throws NetconfDocumentedException {
+ try {
+ return Util.readDate(value);
+ } catch (ParseException e) {
+ logger.trace("Unable parse value {} due to {}",value, e);
+ throw new NetconfDocumentedException("Unable to parse value "+value+" as date.",
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
}
}
Map<String, Object> newMap = Maps.newHashMap();
for (String key : openType.keySet()) {
- if (openType.getDescription(key).equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION))
+ if (openType.getDescription(key).equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION)){
newMap.put(key, valueMap.get(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION));
- else
+ } else {
newMap.put(key, null);
+ }
}
return newMap;
}
--- /dev/null
+/*
+ * 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.confignetconfconnector.mapping.attributes.toxml;
+
+public abstract class AbstractAttributeWritingStrategy {
+ protected Object preprocess(Object value) {
+ return value;
+ }
+}
public class CompositeAttributeWritingStrategy implements AttributeWritingStrategy {
- protected final String key;
- protected final Document document;
- protected final Map<String, AttributeWritingStrategy> innerStrats;
+ private final String key;
+ private final Document document;
+ private final Map<String, AttributeWritingStrategy> innerStrats;
public CompositeAttributeWritingStrategy(Document document, String key,
Map<String, AttributeWritingStrategy> innerStrats) {
}
parentElement.appendChild(innerNode);
}
+
+ public String getKey() {
+ return key;
+ }
+
+ public Document getDocument() {
+ return document;
+ }
+
+ public Map<String, AttributeWritingStrategy> getInnerStrats() {
+ return innerStrats;
+ }
}
@Override
protected AttributeWritingStrategy caseTOAttribute(CompositeType openType) {
- Preconditions.checkState(lastAttribute instanceof TOAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof TOAttribute);
Map<String, AttributeWritingStrategy> innerStrats = Maps.newHashMap();
String currentKey = key;
- for (Entry<String, AttributeIfc> innerAttrEntry : ((TOAttribute) lastAttribute).getYangPropertiesToTypesMap().entrySet()) {
+ for (Entry<String, AttributeIfc> innerAttrEntry : ((TOAttribute) getLastAttribute()).getYangPropertiesToTypesMap().entrySet()) {
AttributeWritingStrategy innerStrategy = prepareWritingStrategy(innerAttrEntry.getKey(),
innerAttrEntry.getValue(), document);
@Override
protected AttributeWritingStrategy caseListAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListAttribute);
- AttributeIfc innerAttribute = ((ListAttribute) lastAttribute).getInnerAttribute();
+ Preconditions.checkState(getLastAttribute() instanceof ListAttribute);
+ AttributeIfc innerAttribute = ((ListAttribute) getLastAttribute()).getInnerAttribute();
AttributeWritingStrategy innerStrategy = prepareWritingStrategy(key, innerAttribute, document);
return new ArrayAttributeWritingStrategy(innerStrategy);
@Override
protected AttributeWritingStrategy caseListDependeciesAttribute(ArrayType<?> openType) {
- Preconditions.checkState(lastAttribute instanceof ListDependenciesAttribute);
+ Preconditions.checkState(getLastAttribute() instanceof ListDependenciesAttribute);
AttributeWritingStrategy innerStrategy = caseDependencyAttribute(SimpleType.OBJECTNAME);
return new ArrayAttributeWritingStrategy(innerStrategy);
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
-import java.util.Map;
-import java.util.Map.Entry;
-
+import com.google.common.base.Optional;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
+import java.util.Map;
+import java.util.Map.Entry;
public class RuntimeBeanEntryWritingStrategy extends CompositeAttributeWritingStrategy {
public void writeElement(Element parentElement, String namespace, Object value) {
Util.checkType(value, Map.class);
- Element innerNode = XmlUtil.createElement(document, key, Optional.<String>absent());
+ Element innerNode = XmlUtil.createElement(getDocument(), getKey(), Optional.<String>absent());
Map<?, ?> map = (Map<?, ?>) value;
// bean
Util.checkType(runtimeBeanInstanceMappingEntry.getValue(), Map.class);
Map<?, ?> innerMap = (Map<?, ?>) runtimeBeanInstanceMappingEntry.getValue();
- Element runtimeInstanceNode = XmlUtil.createElement(document, "_"
+ Element runtimeInstanceNode = XmlUtil.createElement(getDocument(), "_"
+ (String) runtimeBeanInstanceMappingEntry.getKey(), Optional.<String>absent());
innerNode.appendChild(runtimeInstanceNode);
String innerKey = (String) innerObjectEntry.getKey();
Object innerValue = innerObjectEntry.getValue();
- innerStrats.get(innerKey).writeElement(runtimeInstanceNode, namespace, innerValue);
+ getInnerStrats().get(innerKey).writeElement(runtimeInstanceNode, namespace, innerValue);
}
}
parentElement.appendChild(innerNode);
typeElement.appendChild(document.createTextNode(value));
return typeElement;
}
-
protected Object preprocess(Object value) {
return value;
}
super(document, key);
}
+ @Override
protected Object preprocess(Object value) {
Util.checkType(value, List.class);
BaseEncoding en = BaseEncoding.base64();
public class SimpleIdentityRefAttributeWritingStrategy extends SimpleAttributeWritingStrategy {
- private static final char QNAME_SEPARATOR = ':';
private static final String PREFIX = "prefix";
/**
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-
import javax.management.ObjectName;
-
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import static com.google.common.base.Preconditions.checkState;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
public class Config {
- private final Logger logger = LoggerFactory.getLogger(Config.class);
private final Map<String/* Namespace from yang file */,
Map<String /* Name of module entry from yang file */, ModuleConfig>> moduleConfigs;
- private final Map<String, ModuleConfig> moduleNamesToConfigs;
private final Map<String, Map<Date, EditConfig.IdentityMapping>> identityMap;
public Config(Map<String, Map<String, ModuleConfig>> moduleConfigs, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
this.moduleConfigs = moduleConfigs;
- Map<String, ModuleConfig> moduleNamesToConfigs = new HashMap<>();
- for (Entry<String, Map<String, ModuleConfig>> entry : moduleConfigs.entrySet()) {
- moduleNamesToConfigs.putAll(entry.getValue());
- }
- this.moduleNamesToConfigs = Collections.unmodifiableMap(moduleNamesToConfigs);
this.identityMap = identityMap;
}
// TODO, this code does not support same module names from different namespaces
// Namespace should be present in ObjectName
- if (instances == null)
+ if (instances == null){
continue;
+ }
innerRetVal.put(moduleName, instances);
return retVal;
}
- // public Element toXml(Set<ObjectName> instancesToMap, String namespace,
- // Document document) {
- // return toXml(instancesToMap, Optional.of(namespace), document);
- // }
-
public Element toXml(Set<ObjectName> instancesToMap, Optional<String> maybeNamespace, Document document,
Element dataElement, ServiceRegistryWrapper serviceTracker) {
// TODO refactor, replace Map->Multimap with e.g. ConfigElementResolved
// class
- public Map<String, Multimap<String, ModuleElementResolved>> fromXmlModulesResolved(XmlElement xml, EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) {
+ public Map<String, Multimap<String, ModuleElementResolved>> fromXmlModulesResolved(XmlElement xml, EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) throws NetconfDocumentedException {
Optional<XmlElement> modulesElement = getModulesElement(xml);
List<XmlElement> moduleElements = getModulesElementList(modulesElement);
for (XmlElement moduleElement : moduleElements) {
ResolvingStrategy<ModuleElementResolved> resolvingStrategy = new ResolvingStrategy<ModuleElementResolved>() {
@Override
- public ModuleElementResolved resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) {
+ public ModuleElementResolved resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) throws NetconfDocumentedException {
return moduleMapping.fromXml(moduleElement, serviceTracker,
instanceName, moduleNamespace, defaultStrategy, identityMap);
}
* return a map containing namespace -> moduleName -> instanceName map. Attribute parsing is omitted.
*/
public Map<String, Multimap<String, ModuleElementDefinition>> fromXmlModulesMap(XmlElement xml,
- EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) {
+ EditStrategyType defaultEditStrategyType, ServiceRegistryWrapper serviceTracker) throws NetconfDocumentedException {
Optional<XmlElement> modulesElement = getModulesElement(xml);
List<XmlElement> moduleElements = getModulesElementList(modulesElement);
XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
}
- private List<XmlElement> getModulesElementList(Optional<XmlElement> modulesElement) {
+ private List<XmlElement> getModulesElementList(Optional<XmlElement> modulesElement) throws NetconfDocumentedException {
List<XmlElement> moduleElements;
if (modulesElement.isPresent()) {
}
private <T> void resolveModule(Map<String, Multimap<String, T>> retVal, ServiceRegistryWrapper serviceTracker,
- XmlElement moduleElement, EditStrategyType defaultStrategy, ResolvingStrategy<T> resolvingStrategy) {
- XmlElement typeElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+ XmlElement moduleElement, EditStrategyType defaultStrategy, ResolvingStrategy<T> resolvingStrategy) throws NetconfDocumentedException {
+ XmlElement typeElement = null;
+ typeElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
Entry<String, String> prefixToNamespace = typeElement.findNamespaceOfTextContent();
String moduleNamespace = prefixToNamespace.getValue();
- XmlElement nameElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
+ XmlElement nameElement = null;
+ nameElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
String instanceName = nameElement.getTextContent();
String factoryNameWithPrefix = typeElement.getTextContent();
String prefixOrEmptyString = prefixToNamespace.getKey();
innerMap.put(factoryName, resolvedElement);
}
- public Services fromXmlServices(XmlElement xml) {
+ public Services fromXmlServices(XmlElement xml) throws NetconfDocumentedException {
Optional<XmlElement> servicesElement = getServicesElement(xml);
Services services;
XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
}
- public static void checkUnrecognisedChildren(XmlElement parent) {
+ public static void checkUnrecognisedChildren(XmlElement parent) throws NetconfDocumentedException {
Optional<XmlElement> servicesOpt = getServicesElement(parent);
Optional<XmlElement> modulesOpt = getModulesElement(parent);
List<XmlElement> recognised = Lists.newArrayList();
- if(servicesOpt.isPresent())
+ if(servicesOpt.isPresent()){
recognised.add(servicesOpt.get());
- if(modulesOpt.isPresent())
+ }
+ if(modulesOpt.isPresent()){
recognised.add(modulesOpt.get());
+ }
parent.checkUnrecognisedElements(recognised);
}
private String getFactoryName(String factoryNameWithPrefix, String prefixOrEmptyString) {
checkState(
factoryNameWithPrefix.startsWith(prefixOrEmptyString),
- format("Internal error: text " + "content '%s' of type node does not start with prefix '%s'",
+ String.format("Internal error: text " + "content '%s' of type node does not start with prefix '%s'",
factoryNameWithPrefix, prefixOrEmptyString));
int factoryNameAfterPrefixIndex;
private interface ResolvingStrategy<T> {
public T resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker,
- String instanceName, String moduleNamespace, EditStrategyType defaultStrategy);
+ String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) throws NetconfDocumentedException;
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
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.Multimap;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeReadingStrategy;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader;
Map<String, Object> toXml = Maps.newHashMap();
for (Entry<String, AttributeIfc> configDefEntry : jmxToAttrConfig.entrySet()) {
-
// Skip children runtime beans as they are mapped by InstanceRuntime
- if (configDefEntry.getValue() instanceof RuntimeBeanEntry)
+ if (configDefEntry.getValue() instanceof RuntimeBeanEntry){
continue;
-
+ }
Object value = configRegistryClient.getAttributeCurrentValue(on, configDefEntry.getKey());
try {
AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = mappingStrategies
.get(configDefEntry.getKey());
Optional<?> a = attributeMappingStrategy.mapAttribute(value);
- if (a.isPresent() == false)
+ if (!a.isPresent()){
continue;
-
+ }
toXml.put(configDefEntry.getValue().getAttributeYangName(), a.get());
} catch (Exception e) {
throw new IllegalStateException("Unable to map value " + value + " to attribute "
+ configDefEntry.getKey(), e);
}
}
-
return toXml;
}
}
public InstanceConfigElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper services, String moduleNamespace,
- EditStrategyType defaultStrategy, Multimap<String, String> providedServices, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
+ EditStrategyType defaultStrategy, Multimap<String, String> providedServices, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) throws NetconfDocumentedException {
Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig, identityMap);
List<XmlElement> recognisedChildren = Lists.newArrayList();
- XmlElement type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
- XmlElement name = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
+ XmlElement type = null;
+ XmlElement name = null;
+ type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+ name = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
List<XmlElement> typeAndName = Lists.newArrayList(type, name);
for (Entry<String, AttributeReadingStrategy> readStratEntry : strats.entrySet()) {
}
private List<XmlElement> getConfigNodes(XmlElement moduleElement, String moduleNamespace, String name,
- List<XmlElement> recognisedChildren, List<XmlElement> typeAndName) {
+ List<XmlElement> recognisedChildren, List<XmlElement> typeAndName) throws NetconfDocumentedException {
List<XmlElement> foundConfigNodes = moduleElement.getChildElementsWithinNamespace(name, moduleNamespace);
if (foundConfigNodes.isEmpty()) {
logger.debug("No config nodes {}:{} found in {}", moduleNamespace, name, moduleElement);
List<XmlElement> foundWithoutNamespaceNodes = moduleElement.getChildElementsWithinNamespace(name,
XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
foundWithoutNamespaceNodes.removeAll(typeAndName);
- Preconditions.checkState(foundWithoutNamespaceNodes.isEmpty(),
- "Element %s present multiple times with different namespaces: %s, %s", name, foundConfigNodes,
- foundWithoutNamespaceNodes);
+ if (!foundWithoutNamespaceNodes.isEmpty()){
+ throw new NetconfDocumentedException(String.format("Element %s present multiple times with different namespaces: %s, %s", name, foundConfigNodes,
+ foundWithoutNamespaceNodes),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
}
recognisedChildren.addAll(foundConfigNodes);
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Multimap;
+import java.util.Map;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigStrategy;
-import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
-import java.util.Map;
-
/**
* Parsed xml element containing whole configuration for an instance of some
* module. Contains preferred edit strategy type.
private final Map<String, AttributeConfigElement> configuration;
private final Multimap<String, String> providedServices;
- public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
- EditStrategyType valueOf = parseStrategy(currentStrategy, defaultStrategy);
+ public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) throws NetconfDocumentedException {
+ EditStrategyType valueOf = null;
+ valueOf = parseStrategy(currentStrategy, defaultStrategy);
this.editStrategy = valueOf;
this.configuration = configuration;
this.providedServices = providedServices;
}
- static EditStrategyType parseStrategy(String currentStrategy, EditStrategyType defaultStrategy) {
+ static EditStrategyType parseStrategy(String currentStrategy, EditStrategyType defaultStrategy) throws OperationNotPermittedException {
EditStrategyType parsedStrategy = EditStrategyType.valueOf(currentStrategy);
- if (defaultStrategy.isEnforcing()) {
- Preconditions
- .checkArgument(
- parsedStrategy == defaultStrategy,
- "With "
- + defaultStrategy
- + " as "
- + EditConfigXmlParser.DEFAULT_OPERATION_KEY
- + " operations on module elements are not permitted since the default option is restrictive");
- }
+ EditStrategyType.compareParsedStrategyToDefaultEnforcing(parsedStrategy,defaultStrategy);
return parsedStrategy;
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-
-import javax.management.ObjectName;
-
+import com.google.common.base.Optional;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import javax.management.ObjectName;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
public class ModuleConfig {
Element root = XmlUtil.createElement(document, XmlNetconfConstants.MODULE_KEY, Optional.<String>absent());
// Xml.addNamespaceAttr(document, root, namespace);
- final String prefix = getPrefix(namespace);
+ final String prefix = getPrefix();
Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(prefix, XmlNetconfConstants.TYPE_KEY), prefix,
moduleName, Optional.<String>of(namespace));
// Xml.addNamespaceAttr(document, typeElement,
return root;
}
- private String getPrefix(String namespace) {
- // if(namespace.contains(":")==false)
+ private String getPrefix() {
return XmlNetconfConstants.PREFIX;
- // return namespace.substring(namespace.lastIndexOf(':') + 1,
- // namespace.length());
-
}
public ModuleElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper depTracker, String instanceName,
- String moduleNamespace, EditStrategyType defaultStrategy, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
+ String moduleNamespace, EditStrategyType defaultStrategy, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) throws NetconfDocumentedException {
InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices, identityMap);
return new ModuleElementResolved(instanceName, ice);
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigStrategy;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.MissingInstanceHandlingStrategy;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.NoneEditConfigStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class ModuleElementDefinition {
private final String instanceName;
private final EditStrategyType editStrategy;
+ private static final Logger logger = LoggerFactory.getLogger(ModuleElementDefinition.class);
public ModuleElementDefinition(String instanceName, String currentStrategy, EditStrategyType defaultStrategy) {
this.instanceName = instanceName;
- if (currentStrategy == null || currentStrategy.isEmpty())
+ if (currentStrategy == null || currentStrategy.isEmpty()) {
this.editStrategy = defaultStrategy;
- else
- this.editStrategy = InstanceConfigElementResolved.parseStrategy(currentStrategy, defaultStrategy);
+ } else {
+ EditStrategyType _edStrategy = null;
+ try {
+ _edStrategy = InstanceConfigElementResolved.parseStrategy(currentStrategy, defaultStrategy);
+ } catch (OperationNotPermittedException e) {
+ _edStrategy = defaultStrategy;
+ logger.warn("Operation not permitted on current strategy {} while default strategy is {}. Element definition strategy set to default.",
+ currentStrategy,
+ defaultStrategy,
+ e);
+ }
+ this.editStrategy = _edStrategy;
+ }
+
}
public String getInstanceName() {
public boolean hasRefName(String namespace, String serviceName, ObjectName on) {
String qname = configServiceRefRegistry.getServiceInterfaceName(namespace, serviceName);
Map<String, ObjectName> forQName = configServiceRefRegistry.getServiceMapping().get(qname);
- if(forQName==null) return false;
+ if(forQName==null){
+ return false;
+ }
return forQName.values().contains(on);
}
Map<String, Map<String, Map<String, String>>> retVal = Maps.newHashMap();
Map<String, Map<String, ObjectName>> serviceMapping = configServiceRefRegistry.getServiceMapping();
- for (String serviceQName : serviceMapping.keySet())
+ for (String serviceQName : serviceMapping.keySet()){
for (String refName : serviceMapping.get(serviceQName).keySet()) {
ObjectName on = serviceMapping.get(serviceQName).get(refName);
serviceToRefs.put(localName, refsToSis);
}
- Preconditions.checkState(refsToSis.containsKey(refName) == false,
+ Preconditions.checkState(!refsToSis.containsKey(refName),
"Duplicate reference name %s for service %s:%s, now for instance %s", refName, namespace,
localName, on);
refsToSis.put(refName, si.toString());
}
+ }
return retVal;
}
Map<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
Map<String, String> refNameToInstance;
- if(serviceNameToRefNameToInstance == null || serviceNameToRefNameToInstance.containsKey(serviceName) == false) {
+ if(serviceNameToRefNameToInstance == null || !serviceNameToRefNameToInstance.containsKey(serviceName)) {
refNameToInstance = Collections.emptyMap();
- } else
+ } else {
refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
+ }
final Set<String> refNamesAsSet = toSet(refNameToInstance.keySet());
if (refNamesAsSet.contains(refName)) {
}
private String findAvailableRefName(String refName, Set<String> refNamesAsSet) {
- String intitialRefName = refName;
+ String availableRefName = "";
while (true) {
- refName = intitialRefName + "_" + suffix++;
- if (refNamesAsSet.contains(refName) == false)
- return refName;
+ availableRefName = refName + "_" + suffix++;
+ if (!refNamesAsSet.contains(availableRefName)){
+ return availableRefName;
+ }
}
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.management.ObjectName;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectNameAttributeReadingStrategy;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
+import javax.management.ObjectName;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public final class Services {
- private static final Logger logger = LoggerFactory.getLogger(Services.class);
-
private static final String PROVIDER_KEY = "provider";
private static final String NAME_KEY = "name";
public static final String TYPE_KEY = "type";
// TODO support edit strategies on services
- public static Services fromXml(XmlElement xml) {
+ public static Services fromXml(XmlElement xml) throws NetconfDocumentedException {
Map<String, Map<String, Map<String, String>>> retVal = Maps.newHashMap();
List<XmlElement> services = xml.getChildElements(SERVICE_KEY);
XmlElement typeElement = service.getOnlyChildElement(TYPE_KEY);
Entry<String, String> prefixNamespace = typeElement.findNamespaceOfTextContent();
- Preconditions.checkState(prefixNamespace.getKey()!=null && prefixNamespace.getKey().equals("") == false, "Type attribute was not prefixed");
+ Preconditions.checkState(prefixNamespace.getKey()!=null && !prefixNamespace.getKey().equals(""), "Type attribute was not prefixed");
Map<String, Map<String, String>> namespaceToServices = retVal.get(prefixNamespace.getValue());
if(namespaceToServices == null) {
public static ServiceInstance fromString(String instanceId) {
instanceId = instanceId.trim();
Matcher matcher = p.matcher(instanceId);
- if(matcher.matches() == false) {
+ if(!matcher.matches()) {
matcher = pDeprecated.matcher(instanceId);
}
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj){
return true;
- if (obj == null)
+ }
+ if (obj == null){
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()){
return false;
+ }
ServiceInstance other = (ServiceInstance) obj;
if (instanceName == null) {
- if (other.instanceName != null)
+ if (other.instanceName != null){
return false;
- } else if (!instanceName.equals(other.instanceName))
+ }
+ } else if (!instanceName.equals(other.instanceName)){
return false;
+ }
if (moduleName == null) {
- if (other.moduleName != null)
+ if (other.moduleName != null){
return false;
- } else if (!moduleName.equals(other.moduleName))
+ }
+ } else if (!moduleName.equals(other.moduleName)){
return false;
+ }
return true;
}
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeReadingStrategy;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader;
}
}
- public Map<String, AttributeConfigElement> fromXml(XmlElement configRootNode) {
+ public Map<String, AttributeConfigElement> fromXml(XmlElement configRootNode) throws NetconfDocumentedException {
Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
// FIXME add identity map to runtime data
public final class ModuleRpcs {
- Map<String, String> yangToJavaNames = Maps.newHashMap();
- Map<String, Map<String, InstanceRuntimeRpc>> rpcMapping = Maps.newHashMap();
+ private final Map<String, String> yangToJavaNames = Maps.newHashMap();
+ private final Map<String, Map<String, InstanceRuntimeRpc>> rpcMapping = Maps.newHashMap();
public void addNameMapping(RuntimeBeanEntry runtimeEntry) {
String yangName = runtimeEntry.getYangName();
- Preconditions.checkState(yangToJavaNames.containsKey(yangName) == false,
+ Preconditions.checkState(!yangToJavaNames.containsKey(yangName),
"RuntimeBean %s found twice in same namespace", yangName);
yangToJavaNames.put(yangName, runtimeEntry.getJavaNamePrefix());
}
rpcMapping.put(yangName, map);
}
- Preconditions.checkState(map.containsKey(rpc.getYangName()) == false, "Rpc %s for runtime bean %s added twice",
+ Preconditions.checkState(!map.containsKey(rpc.getYangName()), "Rpc %s for runtime bean %s added twice",
rpc.getYangName(), yangName);
map.put(rpc.getYangName(), new InstanceRuntimeRpc(rpc));
}
Preconditions.checkState(rpc != null, "No rpc found for runtime bean %s with name %s", rbeName, rpcName);
return rpc;
}
+
+ public Map<String, String> getYangToJavaNames() {
+ return yangToJavaNames;
+ }
+
+ public Map<String, Map<String, InstanceRuntimeRpc>> getRpcMapping() {
+ return rpcMapping;
+ }
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import javax.management.ObjectName;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Sets;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Sets;
+import javax.management.ObjectName;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
public class InstanceRuntime {
* root + any number of additional properties
*/
private Set<ObjectName> findChildren(ObjectName innerRootBean, Set<ObjectName> childRbeOns) {
- final Hashtable<String, String> wantedProperties = innerRootBean.getKeyPropertyList();
+ final Map<String, String> wantedProperties = innerRootBean.getKeyPropertyList();
return Sets.newHashSet(Collections2.filter(childRbeOns, new Predicate<ObjectName>() {
@Override
public boolean apply(ObjectName on) {
- Hashtable<String, String> localProperties = on.getKeyPropertyList();
+ Map<String, String> localProperties = on.getKeyPropertyList();
for (Entry<String, String> propertyEntry : wantedProperties.entrySet()) {
- if (!localProperties.containsKey(propertyEntry.getKey()))
+ if (!localProperties.containsKey(propertyEntry.getKey())){
return false;
- if (!localProperties.get(propertyEntry.getKey()).equals(propertyEntry.getValue()))
+ }
+ if (!localProperties.get(propertyEntry.getKey()).equals(propertyEntry.getValue())){
return false;
- if (localProperties.size() <= wantedProperties.size())
+ }
+ if (localProperties.size() <= wantedProperties.size()){
return false;
+ }
}
return true;
}
@Override
public boolean apply(ObjectName on) {
- if (on.getKeyPropertyList().size() != keyListSize + 1)
+ if (on.getKeyPropertyList().size() != keyListSize + 1){
return false;
- if (!on.getKeyPropertyList().containsKey(string))
+ }
+ if (!on.getKeyPropertyList().containsKey(string)){
return false;
+ }
return true;
}
}));
public class ModuleRuntime {
- private final String moduleName;
private final InstanceRuntime instanceRuntime;
public ModuleRuntime(String moduleName, InstanceRuntime instanceRuntime) {
- this.moduleName = moduleName;
this.instanceRuntime = instanceRuntime;
}
private ObjectName findRoot(Collection<ObjectName> runtimeBeanOns) {
for (ObjectName objectName : runtimeBeanOns) {
- if (objectName.getKeyPropertyList().size() == 3)
+ if (objectName.getKeyPropertyList().size() == 3){
return objectName;
+ }
}
throw new IllegalStateException("Root runtime bean not found among " + runtimeBeanOns);
}
Element runtimeXml;
ModuleConfig moduleConfig = moduleConfigs.get(localNamespace).get(moduleName);
- if(instanceToRbe==null || instanceToRbe.containsKey(instanceName) == false) {
+ if(instanceToRbe==null || !instanceToRbe.containsKey(instanceName)) {
runtimeXml = moduleConfig.toXml(instanceON, serviceRegistry, document, localNamespace);
} else {
ModuleRuntime moduleRuntime = moduleRuntimes.get(localNamespace).get(moduleName);
return root;
}
- private ObjectName findInstance(Collection<ObjectName> objectNames, String instanceName) {
- for (ObjectName objectName : objectNames) {
- String name = ObjectNameUtil.getInstanceName(objectName);
- if(name.equals(instanceName))
- return objectName;
- }
-
- throw new UnsupportedOperationException("Unable to find config bean instance under name " + instanceName + " among " + objectNames);
- }
-
}
public abstract class AbstractConfigNetconfOperation extends AbstractLastNetconfOperation {
- protected final ConfigRegistryClient configRegistryClient;
+ private final ConfigRegistryClient configRegistryClient;
protected AbstractConfigNetconfOperation(ConfigRegistryClient configRegistryClient,
String netconfSessionIdForReporting) {
super(netconfSessionIdForReporting);
this.configRegistryClient = configRegistryClient;
}
+
+ public ConfigRegistryClient getConfigRegistryClient() {
+ return configRegistryClient;
+ }
}
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;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
this.transactionProvider = transactionProvider;
}
- private static void checkXml(XmlElement xml) {
+ private static void checkXml(XmlElement xml) throws NetconfDocumentedException {
xml.checkName(XmlNetconfConstants.COMMIT);
xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
}
@Override
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
- checkXml(xml);
+ checkXml(xml);
CommitStatus status;
try {
status = this.transactionProvider.commitTransaction();
- } catch (final IllegalStateException e) {
- // TODO Illegal state thrown when no transaction yet for user
- // Throw other exception type, or create transaction automatically
- logger.warn("Commit failed: ", e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.operation_failed.name(),
- "Operation failed. Use 'get-config' or 'edit-config' before triggering 'commit' operation");
- throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, ErrorTag.operation_failed,
- ErrorSeverity.error, errorInfo);
- } catch (ValidationException e) {
+ logger.trace("Datastore {} committed successfully: {}", Datastore.candidate, status);
+ } catch (ConflictingVersionException | ValidationException e) {
throw NetconfDocumentedException.wrap(e);
- } catch (ConflictingVersionException e) {
- throw NetconfDocumentedException.wrap(e);
-
}
logger.trace("Datastore {} committed successfully: {}", Datastore.candidate, status);
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.confignetconfconnector.operations;
-
-import java.util.HashMap;
-import java.util.Map;
+ package org.opendaylight.controller.netconf.confignetconfconnector.operations;
+import com.google.common.base.Optional;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
+import java.util.HashMap;
+import java.util.Map;
+
public class DiscardChanges extends AbstractConfigNetconfOperation {
this.transactionProvider = transactionProvider;
}
- private static void fromXml(XmlElement xml) {
+ private static void fromXml(XmlElement xml) throws NetconfDocumentedException {
xml.checkName(DISCARD);
xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
}
@Override
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
- try {
- fromXml(xml);
- } catch (final IllegalArgumentException e) {
- //FIXME where can IllegalStateException be thrown?
- logger.warn("Rpc error: {}", ErrorTag.bad_attribute, e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage());
- throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute,
- ErrorSeverity.error, errorInfo);
- }
-
+ fromXml(xml);
try {
this.transactionProvider.abortTransaction();
} catch (final IllegalStateException e) {
- //FIXME where can IllegalStateException be thrown?
logger.warn("Abort failed: ", e);
final Map<String, String> errorInfo = new HashMap<>();
errorInfo
}
logger.trace("Changes discarded successfully from datastore {}", Datastore.candidate);
+
return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.<String>absent());
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations;
-import java.util.HashMap;
-import java.util.Map;
-
+import com.google.common.base.Optional;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import java.util.HashMap;
+import java.util.Map;
public class Validate extends AbstractConfigNetconfOperation {
this.transactionProvider = transactionProvider;
}
- private void checkXml(XmlElement xml) {
+ private void checkXml(XmlElement xml) throws NetconfDocumentedException {
xml.checkName(VALIDATE);
xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
String datastoreValue = sourceChildNode.getName();
Datastore sourceDatastore = Datastore.valueOf(datastoreValue);
- Preconditions.checkState(sourceDatastore == Datastore.candidate, "Only " + Datastore.candidate
- + " is supported as source for " + VALIDATE + " but was " + datastoreValue);
+ if (sourceDatastore != Datastore.candidate){
+ throw new NetconfDocumentedException( "Only " + Datastore.candidate
+ + " is supported as source for " + VALIDATE + " but was " + datastoreValue,ErrorType.application,ErrorTag.data_missing,ErrorSeverity.error);
+ }
}
@Override
@Override
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
- try {
- checkXml(xml);
- } catch (IllegalStateException e) {
- //FIXME where can IllegalStateException be thrown? I see precondition that guards for programming bugs..
- logger.warn("Rpc error: {}", ErrorTag.missing_attribute, e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.missing_attribute.name(), "Missing value of datastore attribute");
- throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.missing_attribute,
- ErrorSeverity.error, errorInfo);
- } catch (final IllegalArgumentException e) {
- // FIXME use checked exception if it has domain meaning
- logger.warn("Rpc error: {}", ErrorTag.bad_attribute, e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage());
- throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute,
- ErrorSeverity.error, errorInfo);
- }
-
+ checkXml(xml);
try {
transactionProvider.validateTransaction();
} catch (ValidationException e) {
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.slf4j.Logger;
@Override
public void executeConfiguration(String module, String instance, Map<String, AttributeConfigElement> configuration,
- ConfigTransactionClient ta, ServiceRegistryWrapper services) {
+ ConfigTransactionClient ta, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
try {
ObjectName on = ta.lookupConfigBean(module, instance);
// edit configs should not handle missing
abstract void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
- String module, String instance, ServiceRegistryWrapper services);
+ String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException;
abstract void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
- ObjectName objectName, ServiceRegistryWrapper services);
+ ObjectName objectName, ServiceRegistryWrapper services) throws NetconfConfigHandlingException;
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import java.util.Map;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Map;
-
public class DeleteEditConfigStrategy extends AbstractEditConfigStrategy {
private static final Logger logger = LoggerFactory.getLogger(DeleteEditConfigStrategy.class);
- private final Multimap<String, String> providedServices;
-
- public DeleteEditConfigStrategy() {
- this.providedServices = HashMultimap.create();
- }
-
- public DeleteEditConfigStrategy(Multimap<String, String> providedServices) {
- this.providedServices = providedServices;
- }
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
- String module, String instance, ServiceRegistryWrapper services) {
- throw new IllegalStateException("Unable to delete " + module + ":" + instance + " , ServiceInstance not found");
+ String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
+ throw new NetconfConfigHandlingException(String.format("Unable to delete %s : %s , ServiceInstance not found", module ,instance),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
@Override
- void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) {
+ void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
try {
ta.destroyModule(on);
logger.debug("ServiceInstance {} deleted successfully", on);
} catch (InstanceNotFoundException e) {
- throw new IllegalStateException("Unable to delete " + on, e);
+ throw new NetconfConfigHandlingException(
+ String.format("Unable to delete %s because of exception %s" + on, e.getMessage()),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
-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 com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
public class EditConfig extends AbstractConfigNetconfOperation {
@VisibleForTesting
Element getResponseInternal(final Document document,
- final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
+ final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException, NetconfConfigHandlingException {
if (editConfigExecution.shouldTest()) {
- executeTests(configRegistryClient, editConfigExecution);
+ executeTests(getConfigRegistryClient(), editConfigExecution);
}
if (editConfigExecution.shouldSet()) {
- executeSet(configRegistryClient, editConfigExecution);
+ executeSet(getConfigRegistryClient(), editConfigExecution);
}
logger.trace("Operation {} successful", EditConfigXmlParser.EDIT_CONFIG);
private void executeSet(ConfigRegistryClient configRegistryClient,
EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
- try {
- set(configRegistryClient, editConfigExecution);
-
- } catch (IllegalStateException e) {
- //FIXME: when can IllegalStateException be thrown?
- // JmxAttributeValidationException is wrapped in DynamicWritableWrapper with ValidationException
- // ValidationException is not thrown until validate or commit is issued
- logger.warn("Set phase for {} failed", EditConfigXmlParser.EDIT_CONFIG, e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.operation_failed.name(), e.getMessage());
- throw new NetconfDocumentedException("Test phase: " + e.getMessage(), e, ErrorType.application,
- ErrorTag.operation_failed, ErrorSeverity.error, errorInfo);
- }
+ set(configRegistryClient, editConfigExecution);
logger.debug("Set phase for {} operation successful", EditConfigXmlParser.EDIT_CONFIG);
}
EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
try {
test(configRegistryClient, editConfigExecution, editConfigExecution.getDefaultStrategy());
- } catch (IllegalStateException | ValidationException e) {
- //FIXME: when can IllegalStateException be thrown?
+ } catch (final ValidationException e) {
logger.warn("Test phase for {} failed", EditConfigXmlParser.EDIT_CONFIG, e);
final Map<String, String> errorInfo = new HashMap<>();
errorInfo.put(ErrorTag.operation_failed.name(), e.getMessage());
}
private void test(ConfigRegistryClient configRegistryClient, EditConfigExecution execution,
- EditStrategyType editStrategyType) throws ValidationException {
+ EditStrategyType editStrategyType) throws ValidationException, NetconfDocumentedException {
ObjectName taON = transactionProvider.getTestTransaction();
try {
-
// default strategy = replace wipes config
if (editStrategyType == EditStrategyType.replace) {
transactionProvider.wipeTestTransaction(taON);
}
private void set(ConfigRegistryClient configRegistryClient,
- EditConfigXmlParser.EditConfigExecution editConfigExecution) {
+ EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
ObjectName taON = transactionProvider.getOrCreateTransaction();
// default strategy = replace wipes config
setOnTransaction(ta, editConfigExecution);
}
- private void setServicesOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) {
+ private void setServicesOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) throws NetconfDocumentedException {
Services services = execution.getServices();
logger.debug("Saving service {} with on {} under name {} with service on {}", qnameOfService,
on, refName, saved);
} catch (InstanceNotFoundException e) {
- throw new IllegalStateException("Unable to save ref name " + refName + " for instance " + on, e);
+ throw new NetconfDocumentedException(String.format("Unable to save ref name " + refName + " for instance " + on, e),
+ ErrorType.application,
+ ErrorTag.operation_failed,
+ ErrorSeverity.error);
}
}
}
return ta.getServiceInterfaceName(namespace, serviceName);
}
- private void setOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) {
+ private void setOnTransaction(ConfigTransactionClient ta, EditConfigExecution execution) throws NetconfDocumentedException {
for (Multimap<String, ModuleElementResolved> modulesToResolved : execution.getResolvedXmlElements(ta).values()) {
- for (Entry<String, ModuleElementResolved> moduleToResolved : modulesToResolved.entries()) {
+ for (Map.Entry<String, ModuleElementResolved> moduleToResolved : modulesToResolved.entries()) {
String moduleName = moduleToResolved.getKey();
ModuleElementResolved moduleElementResolved = moduleToResolved.getValue();
}
private void handleMisssingInstancesOnTransaction(ConfigTransactionClient ta,
- EditConfigExecution execution) {
+ EditConfigExecution execution) throws NetconfDocumentedException {
for (Multimap<String,ModuleElementDefinition> modulesToResolved : execution.getModulesDefinition(ta).values()) {
- for (Entry<String, ModuleElementDefinition> moduleToResolved : modulesToResolved.entries()) {
+ for (Map.Entry<String, ModuleElementDefinition> moduleToResolved : modulesToResolved.entries()) {
String moduleName = moduleToResolved.getKey();
ModuleElementDefinition moduleElementDefinition = moduleToResolved.getValue();
void addIdSchemaNode(IdentitySchemaNode node) {
String name = node.getQName().getLocalName();
- Preconditions.checkState(identityNameToSchemaNode.containsKey(name) == false);
+ Preconditions.checkState(!identityNameToSchemaNode.containsKey(name));
identityNameToSchemaNode.put(name, node);
}
}
Date revision = module.getRevision();
- Preconditions.checkState(revisionsByNamespace.containsKey(revision) == false,
+ Preconditions.checkState(!revisionsByNamespace.containsKey(revision),
"Duplicate revision %s for namespace %s", revision, namespace);
IdentityMapping identityMapping = revisionsByNamespace.get(revision);
Map<String, Map<String, ModuleConfig>> namespaceToModuleNameToModuleConfig = Maps.newHashMap();
for (String namespace : mBeanEntries.keySet()) {
- for (Entry<String, ModuleMXBeanEntry> moduleNameToMbe : mBeanEntries.get(namespace).entrySet()) {
+ for (Map.Entry<String, ModuleMXBeanEntry> moduleNameToMbe : mBeanEntries.get(namespace).entrySet()) {
String moduleName = moduleNameToMbe.getKey();
ModuleMXBeanEntry moduleMXBeanEntry = moduleNameToMbe.getValue();
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
EditConfigXmlParser.EditConfigExecution editConfigExecution;
- Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot);
- try {
- editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, configRegistryClient);
- } catch (IllegalStateException e) {
- logger.warn("Error parsing xml", e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.missing_attribute.name(), "Error parsing xml: " + e.getMessage());
- throw new NetconfDocumentedException(e.getMessage(), ErrorType.rpc, ErrorTag.missing_attribute,
- ErrorSeverity.error, errorInfo);
- } catch (final IllegalArgumentException e) {
- logger.warn("Error parsing xml", e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage());
- throw new NetconfDocumentedException(e.getMessage(), ErrorType.rpc, ErrorTag.bad_attribute,
- ErrorSeverity.error, errorInfo);
- } catch (final UnsupportedOperationException e) {
- logger.warn("Unsupported", e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.operation_not_supported.name(), "Unsupported option for 'edit-config'");
- throw new NetconfDocumentedException(e.getMessage(), ErrorType.application,
- ErrorTag.operation_not_supported, ErrorSeverity.error, errorInfo);
- }
+ Config cfg = getConfigMapping(getConfigRegistryClient(), yangStoreSnapshot);
+ editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, getConfigRegistryClient());
- return getResponseInternal(document, editConfigExecution);
+ Element responseInternal;
+ responseInternal = getResponseInternal(document, editConfigExecution);
+ return responseInternal;
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
public interface EditConfigStrategy {
void executeConfiguration(String module, String instance, Map<String, AttributeConfigElement> configuration,
- ConfigTransactionClient ta, ServiceRegistryWrapper services);
+ ConfigTransactionClient ta, ServiceRegistryWrapper services) throws NetconfConfigHandlingException;
}
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Multimap;
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
+import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
+import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.slf4j.Logger;
xml.checkName(EditConfigXmlParser.EDIT_CONFIG);
xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
- XmlElement targetElement = xml.getOnlyChildElementWithSameNamespace(EditConfigXmlParser.TARGET_KEY);
- XmlElement targetChildNode = targetElement.getOnlyChildElementWithSameNamespace();
+
+ XmlElement targetElement = null;
+ XmlElement targetChildNode = null;
+ try {
+ targetElement = xml.getOnlyChildElementWithSameNamespace(EditConfigXmlParser.TARGET_KEY);
+ targetChildNode = targetElement.getOnlyChildElementWithSameNamespace();
+ } catch (final MissingNameSpaceException | UnexpectedNamespaceException e) {
+ logger.trace("Can't get only child element with same namespace due to {}",e);
+ throw NetconfDocumentedException.wrap(e);
+ }
String datastoreValue = targetChildNode.getName();
Datastore targetDatastore = Datastore.valueOf(datastoreValue);
logger.debug("Setting {} to '{}'", EditConfigXmlParser.TARGET_KEY, targetDatastore);
// check target
- Preconditions.checkArgument(targetDatastore == Datastore.candidate,
- "Only %s datastore supported for edit config but was: %s", Datastore.candidate, targetDatastore);
+ if (targetDatastore != Datastore.candidate){
+ throw new NetconfDocumentedException(String.format(
+ "Only %s datastore supported for edit config but was: %s",
+ Datastore.candidate,
+ targetDatastore),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
// Test option
TestOption testOption;
.getOnlyChildElementWithSameNamespaceOptionally(EditConfigXmlParser.ERROR_OPTION_KEY);
if (errorOptionElement.isPresent()) {
String errorOptionParsed = errorOptionElement.get().getTextContent();
- if (false == errorOptionParsed.equals(EditConfigXmlParser.DEFAULT_ERROR_OPTION))
+ if (!errorOptionParsed.equals(EditConfigXmlParser.DEFAULT_ERROR_OPTION)){
throw new UnsupportedOperationException("Only " + EditConfigXmlParser.DEFAULT_ERROR_OPTION
+ " supported for " + EditConfigXmlParser.ERROR_OPTION_KEY + ", was " + errorOptionParsed);
+ }
}
// Default op
editStrategyType = EditStrategyType.valueOf(mergeStrategyString);
}
- XmlElement configElement = xml.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.CONFIG_KEY);
+ XmlElement configElement = null;
+ try {
+ configElement = xml.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.CONFIG_KEY);
+ } catch (MissingNameSpaceException e) {
+ logger.trace("Can't get only child element with same namespace due to {}",e);
+ throw NetconfDocumentedException.wrap(e);
+ }
return new EditConfigXmlParser.EditConfigExecution(cfgMapping, configElement, testOption, editStrategyType);
}
private final Config configResolver;
private final XmlElement configElement;
- EditConfigExecution(Config configResolver, XmlElement configElement, TestOption testOption, EditStrategyType defaultStrategy) {
+ EditConfigExecution(Config configResolver, XmlElement configElement, TestOption testOption, EditStrategyType defaultStrategy) throws NetconfDocumentedException {
Config.checkUnrecognisedChildren(configElement);
this.configResolver = configResolver;
this.configElement = configElement;
return testOption == TestOption.set || testOption == TestOption.testThenSet;
}
- Map<String, Multimap<String, ModuleElementResolved>> getResolvedXmlElements(ServiceReferenceReadableRegistry serviceRegistry) {
+ Map<String, Multimap<String, ModuleElementResolved>> getResolvedXmlElements(ServiceReferenceReadableRegistry serviceRegistry) throws NetconfDocumentedException {
return configResolver.fromXmlModulesResolved(configElement, defaultEditStrategyType, getServiceRegistryWrapper(serviceRegistry));
}
return new ServiceRegistryWrapper(serviceRegistry);
}
- Map<String, Multimap<String,ModuleElementDefinition>> getModulesDefinition(ServiceReferenceReadableRegistry serviceRegistry) {
+ Map<String, Multimap<String,ModuleElementDefinition>> getModulesDefinition(ServiceReferenceReadableRegistry serviceRegistry) throws NetconfDocumentedException {
return configResolver.fromXmlModulesMap(configElement, defaultEditStrategyType, getServiceRegistryWrapper(serviceRegistry));
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
import com.google.common.collect.Multimap;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
import java.util.EnumSet;
import java.util.Set;
+ this);
}
}
+ public static void compareParsedStrategyToDefaultEnforcing(EditStrategyType parsedStrategy,
+ EditStrategyType defaultStrategy) throws OperationNotPermittedException {
+ if (defaultStrategy.isEnforcing()) {
+ if (parsedStrategy != defaultStrategy){
+ throw new OperationNotPermittedException(String.format("With "
+ + defaultStrategy
+ + " as "
+ + EditConfigXmlParser.DEFAULT_OPERATION_KEY
+ + " operations on module elements are not permitted since the default option is restrictive"),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
+ }
+ }
public EditConfigStrategy getFittingStrategy(Multimap<String, String> providedServices) {
switch (this) {
case merge:
case replace:
return new ReplaceEditConfigStrategy(providedServices);
case delete:
- return new DeleteEditConfigStrategy(providedServices);
+ return new DeleteEditConfigStrategy();
case remove:
return new RemoveEditConfigStrategy();
case none:
import com.google.common.collect.Multimap;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.slf4j.Logger;
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
- String module, String instance, ServiceRegistryWrapper services) {
- throw new IllegalStateException(
- "Unable to handle missing instance, no missing instances should appear at this point, missing: "
- + module + ":" + instance);
+ String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
+ throw new NetconfConfigHandlingException(
+ String.format("Unable to handle missing instance, no missing instances should appear at this point, missing: %s : %s ",
+ module,
+ instance),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
private void addRefNames(ServiceRegistryWrapper services, Multimap<String, String> providedServices, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
for (Entry<String, String> namespaceToService : providedServices.entries()) {
if(services.hasRefName(namespaceToService.getKey(),
- namespaceToService.getValue(), on))
+ namespaceToService.getValue(), on)){
continue;
+ }
String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on));
}
@Override
- void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) {
+ void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
try {
addRefNames(services, providedServices, ta, on);
} catch (InstanceNotFoundException e) {
- throw new IllegalStateException("Unable to save default ref name for instance " + on, e);
+ throw new NetconfConfigHandlingException(String.format("Unable to save default ref name for instance %s. Instance was not found.",e),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
ta.setAttribute(on, ace.getJmxName(), new Attribute(ace.getJmxName(), value));
logger.debug("Attribute {} set to {} for {}", configAttributeEntry.getKey(), value, on);
} catch (Exception e) {
- throw new IllegalStateException("Unable to set attributes for " + on + ", Error with attribute "
- + configAttributeEntry.getKey() + ":" + configAttributeEntry.getValue(), e);
+ throw new NetconfConfigHandlingException(String.format("Unable to set attributes for %s, Error with attribute %s : %s ",
+ on,
+ configAttributeEntry.getKey(),
+ configAttributeEntry.getValue()),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.slf4j.Logger;
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
- String module, String instance, ServiceRegistryWrapper services) {
+ String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
ObjectName on = null;
try {
on = ta.createModule(module, instance);
logger.trace("New instance for {} {} created under name {}", module, instance, on);
} catch (InstanceAlreadyExistsException e1) {
- throw new IllegalStateException("Unable to create instance for " + module + " : " + instance);
+ throw new NetconfConfigHandlingException(String.format("Unable to create instance for %s : %s.", module, instance),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
}
import com.google.common.collect.Multimap;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.slf4j.Logger;
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
- String module, String instance, ServiceRegistryWrapper services) {
- throw new IllegalStateException(
- "Unable to handle missing instance, no missing instances should appear at this point, missing: "
- + module + ":" + instance);
+ String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
+ throw new NetconfConfigHandlingException(
+ String.format("Unable to handle missing instance, no missing instances should appear at this point, missing: %s : %s ",
+ module,
+ instance),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
private void addRefNames(ServiceRegistryWrapper services, Multimap<String, String> providedServices, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
for (Entry<String, String> namespaceToService : providedServices.entries()) {
if(services.hasRefName(namespaceToService.getKey(),
- namespaceToService.getValue(), on))
+ namespaceToService.getValue(), on)){
continue;
+ }
String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on));
}
@Override
- void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) {
+ void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
try {
addRefNames(services, providedServices, ta, on);
} catch (InstanceNotFoundException e) {
- throw new IllegalStateException("Unable to save default ref name for instance " + on, e);
+ throw new NetconfConfigHandlingException(String.format("Unable to save default ref name for instance %s. Instance not found. ",on),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
}
for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
package org.opendaylight.controller.netconf.confignetconfconnector.operations.get;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.ObjectName;
-
+import com.google.common.collect.Maps;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
+import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
+import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
+import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.collect.Maps;
+import javax.management.ObjectName;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
public class Get extends AbstractConfigNetconfOperation {
RuntimeBeanEntry root = null;
for (RuntimeBeanEntry rbe : mbe.getRuntimeBeans()) {
cache.put(rbe, new InstanceConfig(configRegistryClient, rbe.getYangPropertiesToTypesMap()));
- if (rbe.isRoot())
+ if (rbe.isRoot()){
root = rbe;
+ }
}
- if (root == null)
+ if (root == null){
continue;
+ }
InstanceRuntime rootInstanceRuntime = createInstanceRuntime(root, cache);
ModuleRuntime moduleRuntime = new ModuleRuntime(module, rootInstanceRuntime);
return jmxToYangNamesForChildRbe;
}
- private static void checkXml(XmlElement xml) {
+ private static void checkXml(XmlElement xml) throws UnexpectedElementException, UnexpectedNamespaceException, MissingNameSpaceException {
xml.checkName(XmlNetconfConstants.GET);
xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
// Filter option - unsupported
- if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0)
+ if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0){
throw new UnsupportedOperationException("Unsupported option " + XmlNetconfConstants.FILTER + " for " + XmlNetconfConstants.GET);
+ }
}
@Override
@Override
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
- try {
- checkXml(xml);
- } catch (final IllegalArgumentException e) {
- logger.warn("Error parsing xml", e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage());
- throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute,
- ErrorSeverity.error, errorInfo);
- } catch (final UnsupportedOperationException e) {
- logger.warn("Unsupported", e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.operation_not_supported.name(), "Unsupported option for 'get'");
- throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application,
- ErrorTag.operation_not_supported, ErrorSeverity.error, errorInfo);
- }
+ checkXml(xml);
- final Set<ObjectName> runtimeBeans = configRegistryClient.lookupRuntimeBeans();
+ final Set<ObjectName> runtimeBeans = getConfigRegistryClient().lookupRuntimeBeans();
//Transaction provider required only for candidate datastore
final Set<ObjectName> configBeans = Datastore.getInstanceQueryStrategy(Datastore.running, null)
- .queryInstances(configRegistryClient);
+ .queryInstances(getConfigRegistryClient());
- final Map<String, Map<String, ModuleRuntime>> moduleRuntimes = createModuleRuntimes(configRegistryClient,
+ final Map<String, Map<String, ModuleRuntime>> moduleRuntimes = createModuleRuntimes(getConfigRegistryClient(),
yangStoreSnapshot.getModuleMXBeanEntryMap());
final Map<String, Map<String, ModuleConfig>> moduleConfigs = EditConfig.transformMbeToModuleConfigs(
- configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap());
+ getConfigRegistryClient(), yangStoreSnapshot.getModuleMXBeanEntryMap());
final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs);
ObjectName txOn = transactionProvider.getOrCreateTransaction();
- ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(txOn);
+ ConfigTransactionClient ta = getConfigRegistryClient().getConfigTransactionClient(txOn);
final Element element = runtime.toXml(runtimeBeans, configBeans, document, new ServiceRegistryWrapper(ta));
logger.trace("{} operation successful", XmlNetconfConstants.GET);
package org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.ObjectName;
-
+import com.google.common.base.Optional;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
+import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
+import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
+import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
+import javax.management.ObjectName;
+import java.util.Set;
public class GetConfig extends AbstractConfigNetconfOperation {
this.transactionProvider = transactionProvider;
}
- public static Datastore fromXml(XmlElement xml) {
+ public static Datastore fromXml(XmlElement xml) throws UnexpectedNamespaceException, UnexpectedElementException, MissingNameSpaceException, NetconfDocumentedException {
+
xml.checkName(GET_CONFIG);
xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
Datastore sourceDatastore = Datastore.valueOf(sourceParsed);
// Filter option - unsupported
- if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0)
+ if (xml.getChildElements(XmlNetconfConstants.FILTER).size() != 0){
throw new UnsupportedOperationException("Unsupported option " + XmlNetconfConstants.FILTER + " for "
+ GET_CONFIG);
+ }
return sourceDatastore;
@Override
public Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
Datastore source;
- try {
- source = fromXml(xml);
- } catch (final IllegalArgumentException e) {
- logger.warn("Rpc error: {}", ErrorTag.bad_attribute, e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.bad_attribute.name(), e.getMessage());
- throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.bad_attribute,
- ErrorSeverity.error, errorInfo);
- } catch (final IllegalStateException e) {
- logger.warn("Rpc error: {}", ErrorTag.missing_attribute, e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.missing_attribute.name(), "Missing datasource attribute value");
- throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.rpc, ErrorTag.missing_attribute,
- ErrorSeverity.error, errorInfo);
- } catch (final UnsupportedOperationException e) {
- logger.warn("Unsupported", e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(ErrorTag.operation_not_supported.name(), "Unsupported option for get");
- throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application,
- ErrorTag.operation_not_supported, ErrorSeverity.error, errorInfo);
- }
- return getResponseInternal(document, configRegistryClient, source);
+ source = fromXml(xml);
+ return getResponseInternal(document, getConfigRegistryClient(), source);
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc;
-import java.util.Map;
-
-import javax.management.ObjectName;
-import javax.management.openmbean.OpenType;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit;
import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
+import javax.management.ObjectName;
+import javax.management.openmbean.OpenType;
+import java.util.Map;
public class RuntimeRpc extends AbstractConfigNetconfOperation {
this.yangStoreSnapshot = yangStoreSnapshot;
}
- private Element toXml(Document doc, Object result, AttributeIfc returnType, String namespace, String elementName) {
+ private Element toXml(Document doc, Object result, AttributeIfc returnType, String namespace, String elementName) throws NetconfDocumentedException {
AttributeMappingStrategy<?, ? extends OpenType<?>> mappingStrategy = new ObjectMapper(null).prepareStrategy(returnType);
Optional<?> mappedAttributeOpt = mappingStrategy.mapAttribute(result);
Preconditions.checkState(mappedAttributeOpt.isPresent(), "Unable to map return value %s as %s", result, returnType.getOpenType());
}
public NetconfOperationExecution fromXml(final XmlElement xml) throws NetconfDocumentedException {
- final String namespace = xml.getNamespace();
+ final String namespace;
+ try {
+ namespace = xml.getNamespace();
+ } catch (MissingNameSpaceException e) {
+ logger.trace("Can't get namespace from xml element due to {}",e);
+ throw NetconfDocumentedException.wrap(e);
+ }
final XmlElement contextInstanceElement = xml.getOnlyChildElement(CONTEXT_INSTANCE);
final String operationName = xml.getName();
}
@Override
- public HandlingPriority canHandle(Document message) {
- XmlElement requestElement = getRequestElementWithCheck(message);
+ public HandlingPriority canHandle(Document message) throws NetconfDocumentedException {
+ XmlElement requestElement = null;
+ requestElement = getRequestElementWithCheck(message);
XmlElement operationElement = requestElement.getOnlyChildElement();
final String netconfOperationName = operationElement.getName();
- final String netconfOperationNamespace = operationElement.getNamespace();
+ final String netconfOperationNamespace;
+ try {
+ netconfOperationNamespace = operationElement.getNamespace();
+ } catch (MissingNameSpaceException e) {
+ logger.debug("Cannot retrieve netconf operation namespace from message due to {}", e);
+ return HandlingPriority.CANNOT_HANDLE;
+ }
final Optional<XmlElement> contextInstanceElement = operationElement
.getOnlyChildElementOptionally(CONTEXT_INSTANCE);
- if (contextInstanceElement.isPresent() == false)
+ if (!contextInstanceElement.isPresent()){
return HandlingPriority.CANNOT_HANDLE;
+ }
final RuntimeRpcElementResolved id = RuntimeRpcElementResolved.fromXpath(contextInstanceElement.get()
.getTextContent(), netconfOperationName, netconfOperationNamespace);
@Override
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
-
- // TODO exception handling
// TODO check for namespaces and unknown elements
-
final NetconfOperationExecution execution = fromXml(xml);
logger.debug("Invoking operation {} on {} with arguments {}", execution.operationName, execution.on,
execution.attributes);
- final Object result = executeOperation(configRegistryClient, execution.on, execution.operationName,
+ final Object result = executeOperation(getConfigRegistryClient(), execution.on, execution.operationName,
execution.attributes);
logger.trace("Operation {} called successfully on {} with arguments {} with result {}", execution.operationName,
for (XmlElement xmlElement : xml.getChildElements()) {
final String name = xmlElement.getName();
- if (CONTEXT_INSTANCE.equals(name) == false) { // skip context
+ if (!CONTEXT_INSTANCE.equals(name)) { // skip context
// instance child node
// because it
// specifies
RuntimeRpc.CONTEXT_INSTANCE, xpath, elementName, xpathPatternBlueprint);
PatternGroupResolver groups = new PatternGroupResolver(matcher.group("key1"), matcher.group("value1"),
- matcher.group("key2"), matcher.group("value2"), matcher.group("additional"));
+ matcher.group("value2"), matcher.group("additional"));
String moduleName = groups.getModuleName();
String instanceName = groups.getInstanceName();
- HashMap<String, String> additionalAttributes = groups.getAdditionalKeys(elementName, moduleName);
+ Map<String, String> additionalAttributes = groups.getAdditionalKeys(elementName, moduleName);
return new RuntimeRpcElementResolved(namespace, moduleName, instanceName, groups.getRuntimeBeanYangName(),
additionalAttributes);
private static final class PatternGroupResolver {
- private final String key1, key2, value1, value2;
+ private final String key1, value1, value2;
private final String additional;
private String runtimeBeanYangName;
- PatternGroupResolver(String key1, String value1, String key2, String value2, String additional) {
+ PatternGroupResolver(String key1, String value1, String value2, String additional) {
this.key1 = Preconditions.checkNotNull(key1);
this.value1 = Preconditions.checkNotNull(value1);
- this.key2 = Preconditions.checkNotNull(key2);
this.value2 = Preconditions.checkNotNull(value2);
this.additional = Preconditions.checkNotNull(additional);
return key1.equals(XmlNetconfConstants.NAME_KEY) ? value1 : value2;
}
- HashMap<String, String> getAdditionalKeys(String elementName, String moduleName) {
+ Map<String, String> getAdditionalKeys(String elementName, String moduleName) {
HashMap<String, String> additionalAttributes = Maps.newHashMap();
runtimeBeanYangName = moduleName;
for (String additionalKeyValue : additional.split("/")) {
- if (Strings.isNullOrEmpty(additionalKeyValue))
+ if (Strings.isNullOrEmpty(additionalKeyValue)){
continue;
+ }
Matcher matcher = additionalPattern.matcher(additionalKeyValue);
Preconditions
.checkState(
}
@Override
- public void stop(BundleContext context) throws Exception {
+ public void stop(BundleContext context) {
if (configRegistryLookup != null) {
configRegistryLookup.interrupt();
}
import java.util.Set;
final class NetconfOperationProvider {
- private final YangStoreSnapshot yangStoreSnapshot;
private final Set<NetconfOperation> operations;
- private final ConfigRegistryClient configRegistryClient;
- private final TransactionProvider transactionProvider;
NetconfOperationProvider(YangStoreSnapshot yangStoreSnapshot, ConfigRegistryClient configRegistryClient,
TransactionProvider transactionProvider, String netconfSessionIdForReporting) {
- this.yangStoreSnapshot = yangStoreSnapshot;
- this.configRegistryClient = configRegistryClient;
- this.transactionProvider = transactionProvider;
operations = setUpOperations(yangStoreSnapshot, configRegistryClient, transactionProvider,
netconfSessionIdForReporting);
}
Thread.sleep(ATTEMPT_TIMEOUT_MS);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
- throw new RuntimeException("Interrupted while reattempting connection", e1);
+ throw new IllegalStateException("Interrupted while reattempting connection", e1);
}
}
}
for (Map<String, ModuleMXBeanEntry> moduleNameToMBE : moduleMXBeanEntryMap.values()) {
for (ModuleMXBeanEntry moduleMXBeanEntry : moduleNameToMBE.values()) {
String moduleSeenByYangStore = moduleMXBeanEntry.getYangModuleQName().toString();
- if(modulesSeenByConfig.contains(moduleSeenByYangStore) == false)
+ if(!modulesSeenByConfig.contains(moduleSeenByYangStore)){
missingModulesFromConfig.add(moduleSeenByYangStore);
+ }
}
}
}
}
- private static class YangStoreCapability extends BasicCapability {
+ private static final class YangStoreCapability extends BasicCapability {
private final String content;
private final String revision;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.NoTransactionFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final String netconfSessionIdForReporting;
private ObjectName transaction;
private final List<ObjectName> allOpenedTransactions = new ArrayList<>();
+ private static final String NO_TRANSACTION_FOUND_FOR_SESSION = "No transaction found for session ";
public TransactionProvider(ConfigRegistryClient configRegistryClient, String netconfSessionIdForReporting) {
this.configRegistryClient = configRegistryClient;
public Optional<ObjectName> getTransaction() {
- if (transaction == null)
+ if (transaction == null){
return Optional.absent();
+ }
// Transaction was already closed somehow
- if (isStillOpenTransaction(transaction) == false) {
+ if (!isStillOpenTransaction(transaction)) {
logger.warn("Fixing illegal state: transaction {} was closed in {}", transaction,
netconfSessionIdForReporting);
transaction = null;
}
private boolean isStillOpenTransaction(ObjectName transaction) {
- boolean isStillOpenTransaction = configRegistryClient.getOpenConfigs().contains(transaction);
- return isStillOpenTransaction;
+ return configRegistryClient.getOpenConfigs().contains(transaction);
}
public synchronized ObjectName getOrCreateTransaction() {
/**
* Commit and notification send must be atomic
*/
- public synchronized CommitStatus commitTransaction() throws ValidationException, ConflictingVersionException {
+ public synchronized CommitStatus commitTransaction() throws ValidationException, ConflictingVersionException, NoTransactionFoundException {
+ if (!getTransaction().isPresent()){
+ throw new NoTransactionFoundException("No transaction found for session " + netconfSessionIdForReporting,
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
final Optional<ObjectName> maybeTaON = getTransaction();
- Preconditions.checkState(maybeTaON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
ObjectName taON = maybeTaON.get();
try {
CommitStatus status = configRegistryClient.commitConfig(taON);
public synchronized void abortTransaction() {
logger.debug("Aborting current transaction");
Optional<ObjectName> taON = getTransaction();
- Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
+ Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get());
transactionClient.abortConfig();
public void validateTransaction() throws ValidationException {
Optional<ObjectName> taON = getTransaction();
- Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
+ Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON.get());
transactionClient.validateConfig();
try {
transactionClient.destroyModule(instance);
} catch (InstanceNotFoundException e) {
- if (isTest)
+ if (isTest){
logger.debug("Unable to clean configuration in transactiom {}", taON, e);
- else
+ } else {
logger.warn("Unable to clean configuration in transactiom {}", taON, e);
+ }
throw new IllegalStateException("Unable to clean configuration in transactiom " + taON, e);
}
public void wipeTransaction() {
Optional<ObjectName> taON = getTransaction();
- Preconditions.checkState(taON.isPresent(), "No transaction found for session " + netconfSessionIdForReporting);
+ Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
wipeInternal(taON.get(), false, null);
}
package org.opendaylight.controller.netconf.confignetconfconnector;
-import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
-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 static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement;
-import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
-import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement;
-
-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.Collections;
-import java.util.HashSet;
-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 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 org.custommonkey.xmlunit.AbstractNodeTester;
import org.custommonkey.xmlunit.NodeTest;
import org.custommonkey.xmlunit.NodeTestException;
import org.opendaylight.controller.config.yang.test.impl.Peers;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.DiscardChanges;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
import org.w3c.dom.traversal.DocumentTraversal;
import org.xml.sax.SAXException;
-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 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.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+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 static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement;
+import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
+import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement;
public class NetconfMappingTest extends AbstractConfigTest {
this.factory = new NetconfTestImplModuleFactory();
this.factory2 = new DepTestImplModuleFactory();
this.factory3 = new IdentityTestModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.factory, this.factory2,
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, this.factory, this.factory2,
this.factory3));
transactionProvider = new TransactionProvider(this.configRegistryClient, NETCONF_SESSION_ID);
assertThat(string, JUnitMatchers.containsString(substring));
}
- private void checkEnum(final Document response) {
+ private void checkEnum(final Document response) throws NetconfDocumentedException {
XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data")
.getOnlyChildElement("modules");
assertEquals(2, testingDepsSize);
}
- private void checkTypeConfigAttribute(Document response) {
+ private void checkTypeConfigAttribute(Document response) throws NetconfDocumentedException {
XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data")
.getOnlyChildElement("modules");
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.ValidateTest;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser.EditConfigExecution;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
any(ConfigTransactionClient.class), any(ServiceRegistryWrapper.class));
}
- private EditConfigExecution mockExecution(EditConfigStrategy editStrat) {
+ private EditConfigExecution mockExecution(EditConfigStrategy editStrat) throws NetconfDocumentedException {
EditConfigExecution mock = mock(EditConfigExecution.class);
doReturn(getMapping(editStrat)).when(mock).getResolvedXmlElements(any(ConfigTransactionClient.class));
doReturn(getMappingDefinition(editStrat)).when(mock).getModulesDefinition(any(ConfigTransactionClient.class));
try {
mBeanServerConnection.addNotificationListener(DefaultCommitOperationMXBean.OBJECT_NAME, listener, null, null);
} catch (InstanceNotFoundException | IOException e) {
- throw new RuntimeException("Cannot register as JMX listener to netconf", e);
+ throw new IllegalStateException("Cannot register as JMX listener to netconf", e);
}
}
@Override
public void handleNotification(Notification notification, Object handback) {
- if (notification instanceof NetconfJMXNotification == false) {
+ if (!(notification instanceof NetconfJMXNotification))
return;
- }
// Socket should not be closed at this point
// Activator unregisters this as JMX listener before close is called
this.conflictingVersionTimeoutMillis = conflictingVersionTimeoutMillis;
}
- public synchronized LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> pushConfigs(List<ConfigSnapshotHolder> configs) {
+ public synchronized LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> pushConfigs(List<ConfigSnapshotHolder> configs) throws NetconfDocumentedException {
logger.debug("Last config snapshots to be pushed to netconf: {}", configs);
LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> result = new LinkedHashMap<>();
// start pushing snapshots:
* is caught, whole process is retried - new service instance need to be obtained from the factory. Closes
* {@link NetconfOperationService} after each use.
*/
- private synchronized EditAndCommitResponse pushConfigWithConflictingVersionRetries(ConfigSnapshotHolder configSnapshotHolder) {
+ private synchronized EditAndCommitResponse pushConfigWithConflictingVersionRetries(ConfigSnapshotHolder configSnapshotHolder) throws NetconfDocumentedException {
ConflictingVersionException lastException;
Stopwatch stopwatch = new Stopwatch().start();
do {
} else {
serviceCandidate.close();
logger.trace("Netconf server did not provide required capabilities for {} " +
- "Expected but not found: {}, all expected {}, current {}",
+ "Expected but not found: {}, all expected {}, current {}",
idForReporting, notFoundDiff, expectedCapabilities, serviceCandidate.getCapabilities()
);
throw new NotEnoughCapabilitiesException("Not enough capabilities for " + idForReporting + ". Expected but not found: " + notFoundDiff);
* @throws java.lang.RuntimeException if edit-config or commit fails otherwise
*/
private synchronized EditAndCommitResponse pushConfig(ConfigSnapshotHolder configSnapshotHolder, NetconfOperationService operationService)
- throws ConflictingVersionException {
+ throws ConflictingVersionException, NetconfDocumentedException {
Element xmlToBePersisted;
try {
return new EditAndCommitResponse(editResponseMessage, commitResponseMessage);
}
- private NetconfOperation findOperation(NetconfMessage request, NetconfOperationService operationService) {
+ private NetconfOperation findOperation(NetconfMessage request, NetconfOperationService operationService) throws NetconfDocumentedException {
TreeMap<HandlingPriority, NetconfOperation> allOperations = new TreeMap<>();
Set<NetconfOperation> netconfOperations = operationService.getNetconfOperations();
if (netconfOperations.isEmpty()) {
private Document sendRequestGetResponseCheckIsOK(NetconfMessage request, NetconfOperationService operationService,
String operationNameForReporting, String configIdForReporting)
- throws ConflictingVersionException {
+ throws ConflictingVersionException, NetconfDocumentedException {
NetconfOperation operation = findOperation(request, operationService);
Document response;
}
// load editConfig.xml template, populate /rpc/edit-config/config with parameter
- private static NetconfMessage createEditConfigMessage(Element dataElement) {
+ private static NetconfMessage createEditConfigMessage(Element dataElement) throws NetconfDocumentedException {
String editConfigResourcePath = "/netconfOp/editConfig.xml";
try (InputStream stream = ConfigPersisterNotificationHandler.class.getResourceAsStream(editConfigResourcePath)) {
Preconditions.checkNotNull(stream, "Unable to load resource " + editConfigResourcePath);
package org.opendaylight.controller.netconf.persist.impl;
import com.google.common.annotations.VisibleForTesting;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
import org.opendaylight.controller.config.persist.api.Persister;
+import org.opendaylight.controller.config.persist.api.PropertiesProvider;
import org.opendaylight.controller.config.persist.api.StorageAdapter;
import org.opendaylight.controller.netconf.persist.impl.osgi.ConfigPersisterActivator;
-import org.opendaylight.controller.netconf.persist.impl.osgi.PropertiesProviderBaseImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.ListIterator;
-
/**
* {@link Persister} implementation that delegates persisting functionality to
* underlying {@link Persister} storages. Each storage has unique id, class, readonly value.
}
}
- private static PersisterWithConfiguration loadConfiguration(final String index, final PropertiesProviderBaseImpl propertiesProvider) {
+ private static PersisterWithConfiguration loadConfiguration(final String index, final PropertiesProvider propertiesProvider) {
String classKey = index + "." + ConfigPersisterActivator.STORAGE_ADAPTER_CLASS_PROP_SUFFIX;
String storageAdapterClass = propertiesProvider.getProperty(classKey);
try {
Class<?> clazz = Class.forName(storageAdapterClass);
boolean implementsCorrectIfc = StorageAdapter.class.isAssignableFrom(clazz);
- if (implementsCorrectIfc == false) {
+ if (!implementsCorrectIfc) {
throw new IllegalArgumentException("Storage adapter " + clazz + " does not implement " + StorageAdapter.class);
}
storageAdapter = StorageAdapter.class.cast(clazz.newInstance());
}
- public static PersisterAggregator createFromProperties(PropertiesProviderBaseImpl propertiesProvider) {
+ public static PersisterAggregator createFromProperties(PropertiesProvider propertiesProvider) {
List<PersisterWithConfiguration> persisterWithConfigurations = new ArrayList<>();
String prefixes = propertiesProvider.getProperty("active");
- if (prefixes!=null && prefixes.isEmpty() == false) {
+ if (prefixes!=null && !prefixes.isEmpty()) {
String [] keys = prefixes.split(",");
for (String index: keys) {
persisterWithConfigurations.add(PersisterAggregator.loadConfiguration(index, propertiesProvider));
} catch (IOException e) {
throw new RuntimeException("Error while calling loadLastConfig on " + persisterWithConfiguration, e);
}
- if (configs.isEmpty() == false) {
+ if (!configs.isEmpty()) {
logger.debug("Found non empty configs using {}:{}", persisterWithConfiguration, configs);
return configs;
}
package org.opendaylight.controller.netconf.persist.impl;
import org.opendaylight.controller.config.persist.api.PropertiesProvider;
-import org.opendaylight.controller.netconf.persist.impl.osgi.PropertiesProviderBaseImpl;
public class PropertiesProviderAdapterImpl implements PropertiesProvider {
- private final PropertiesProviderBaseImpl inner;
+ private final PropertiesProvider inner;
private final String index;
- public PropertiesProviderAdapterImpl(PropertiesProviderBaseImpl inner, String index) {
+ public PropertiesProviderAdapterImpl(PropertiesProvider inner, String index) {
this.inner = inner;
this.index = index;
}
return inner.getPrefix() + "." + index + ".properties";
}
+ @Override
+ public String getPropertyWithoutPrefix(String fullKey) {
+ return inner.getPropertyWithoutPrefix(fullKey);
+ }
+
+
@Override
public String getFullKeyForReporting(String key) {
return getPrefix() + "." + key;
import com.google.common.annotations.VisibleForTesting;
import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
long maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesMillis(propertiesProvider);
List<ConfigSnapshotHolder> configs = persisterAggregator.loadLastConfigs();
long conflictingVersionTimeoutMillis = getConflictingVersionTimeoutMillis(propertiesProvider);
- logger.trace("Following configs will be pushed: {}", configs);
+ logger.debug("Following configs will be pushed: {}", configs);
InnerCustomizer innerCustomizer = new InnerCustomizer(configs, maxWaitForCapabilitiesMillis,
conflictingVersionTimeoutMillis, persisterAggregator);
final Thread pushingThread = new Thread(new Runnable() {
@Override
public void run() {
- configPusher.pushConfigs(configs);
+ try {
+ configPusher.pushConfigs(configs);
+ } catch (NetconfDocumentedException e) {
+ logger.error("Error pushing configs {}",configs);
+ throw new IllegalStateException(e);
+ }
logger.info("Configuration Persister initialization completed.");
ConfigPersisterNotificationHandler jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator);
synchronized (ConfigPersisterActivator.this) {
// this means pushing of config was successful
public void assertCannotRegisterAsJMXListener_pushWasSuccessful() {
- handler.assertException(RuntimeException.class, "Cannot register as JMX listener to netconf");
+ handler.assertException(IllegalStateException.class, "Cannot register as JMX listener to netconf");
}
public NetconfOperationService getWorkingService(Document document) throws SAXException, IOException, NetconfDocumentedException {
/**
**/
-public class LocationBuilder {
+public final class LocationBuilder {
public static Location getDefaultInstance(String defaultValue) {
return defaultValue.equals("NETCONF") ? new Location(Location.Enumeration.NETCONF) : new Location(new Uri(
this.errorInfo = errorInfo;
}
+ public static <E extends Exception> NetconfDocumentedException wrap(E exception) throws NetconfDocumentedException {
+ final Map<String, String> errorInfo = new HashMap<>();
+ errorInfo.put(ErrorTag.operation_failed.name(), "Exception thrown");
+ throw new NetconfDocumentedException(exception.getMessage(), exception, ErrorType.application, ErrorTag.operation_failed,
+ ErrorSeverity.error, errorInfo);
+ }
public static NetconfDocumentedException wrap(ValidationException e) throws NetconfDocumentedException {
final Map<String, String> errorInfo = new HashMap<>();
errorInfo.put(ErrorTag.operation_failed.name(), "Validation failed");
--- /dev/null
+/*
+ * 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.client;
+
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GlobalEventExecutor;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.TimedReconnectStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Sets;
+
+/**
+ * @deprecated Use {@link NetconfClientDispatcher.createClient()} or {@link NetconfClientDispatcher.createReconnectingClient()} instead.
+ */
+@Deprecated
+public class NetconfClient implements Closeable {
+
+ private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class);
+
+ public static final int DEFAULT_CONNECT_TIMEOUT = 5000;
+ private final NetconfClientDispatcher dispatch;
+ private final String label;
+ private final NetconfClientSession clientSession;
+ private final NetconfClientSessionListener sessionListener;
+ private final long sessionId;
+ private final InetSocketAddress address;
+
+ // TODO test reconnecting constructor
+ public NetconfClient(String clientLabelForLogging, InetSocketAddress address, int connectionAttempts,
+ int attemptMsTimeout, NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ this(clientLabelForLogging, address, getReconnectStrategy(connectionAttempts, attemptMsTimeout),
+ netconfClientDispatcher);
+ }
+
+ private NetconfClient(String clientLabelForLogging, InetSocketAddress address, ReconnectStrategy strat, NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ this.label = clientLabelForLogging;
+ dispatch = netconfClientDispatcher;
+ sessionListener = new SimpleNetconfClientSessionListener();
+ Future<NetconfClientSession> clientFuture = dispatch.createClient(address, sessionListener, strat);
+ this.address = address;
+ clientSession = get(clientFuture);
+ this.sessionId = clientSession.getSessionId();
+ }
+
+ private NetconfClientSession get(Future<NetconfClientSession> clientFuture) throws InterruptedException {
+ try {
+ return clientFuture.get();
+ } catch (CancellationException e) {
+ throw new RuntimeException("Cancelling " + this, e);
+ } catch (ExecutionException e) {
+ throw new IllegalStateException("Unable to create " + this, e);
+ }
+ }
+
+ public static NetconfClient clientFor(String clientLabelForLogging, InetSocketAddress address, ReconnectStrategy strategy, NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ return new NetconfClient(clientLabelForLogging,address,strategy,netconfClientDispatcher);
+ }
+
+ public static NetconfClient clientFor(String clientLabelForLogging, InetSocketAddress address,
+ ReconnectStrategy strategy, NetconfClientDispatcher netconfClientDispatcher, NetconfClientSessionListener listener) throws InterruptedException {
+ return new NetconfClient(clientLabelForLogging,address,strategy,netconfClientDispatcher,listener);
+ }
+
+ public NetconfClient(String clientLabelForLogging, InetSocketAddress address, int connectTimeoutMs,
+ NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ this(clientLabelForLogging, address,
+ new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, connectTimeoutMs), netconfClientDispatcher);
+ }
+
+ public NetconfClient(String clientLabelForLogging, InetSocketAddress address,
+ NetconfClientDispatcher netconfClientDispatcher) throws InterruptedException {
+ this(clientLabelForLogging, address, new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE,
+ DEFAULT_CONNECT_TIMEOUT), netconfClientDispatcher);
+ }
+
+ public NetconfClient(String clientLabelForLogging, InetSocketAddress address, ReconnectStrategy strategy,
+ NetconfClientDispatcher netconfClientDispatcher, NetconfClientSessionListener listener) throws InterruptedException{
+ this.label = clientLabelForLogging;
+ dispatch = netconfClientDispatcher;
+ sessionListener = listener;
+ Future<NetconfClientSession> clientFuture = dispatch.createClient(address, sessionListener, strategy);
+ this.address = address;
+ clientSession = get(clientFuture);
+ this.sessionId = clientSession.getSessionId();
+ }
+
+ public Future<NetconfMessage> sendRequest(NetconfMessage message) {
+ return ((SimpleNetconfClientSessionListener)sessionListener).sendRequest(message);
+ }
+
+ /**
+ * @deprecated Use {@link sendRequest} instead
+ */
+ @Deprecated
+ public NetconfMessage sendMessage(NetconfMessage message) throws ExecutionException, InterruptedException, TimeoutException {
+ return sendMessage(message, 5, 1000);
+ }
+
+ /**
+ * @deprecated Use {@link sendRequest} instead
+ */
+ @Deprecated
+ public NetconfMessage sendMessage(NetconfMessage message, int attempts, int attemptMsDelay) throws ExecutionException, InterruptedException, TimeoutException {
+ final Stopwatch stopwatch = new Stopwatch().start();
+
+ try {
+ return sendRequest(message).get(attempts * attemptMsDelay, TimeUnit.MILLISECONDS);
+ } finally {
+ stopwatch.stop();
+ logger.debug("Total time spent waiting for response from {}: {} ms", address, stopwatch.elapsed(TimeUnit.MILLISECONDS));
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ clientSession.close();
+ }
+
+ public NetconfClientDispatcher getNetconfClientDispatcher() {
+ return dispatch;
+ }
+
+ private static ReconnectStrategy getReconnectStrategy(int connectionAttempts, int attemptMsTimeout) {
+ return new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, attemptMsTimeout, 1000, 1.0, null,
+ Long.valueOf(connectionAttempts), null);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("NetconfClient{");
+ sb.append("label=").append(label);
+ sb.append(", sessionId=").append(sessionId);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public long getSessionId() {
+ return sessionId;
+ }
+
+ public Set<String> getCapabilities() {
+ Preconditions.checkState(clientSession != null, "Client was not initialized successfully");
+ return Sets.newHashSet(clientSession.getServerCapabilities());
+ }
+
+ public NetconfClientSession getClientSession() {
+ return clientSession;
+ }
+}
});
}
- private static class ClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
+ private static final class ClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
private final NetconfClientSessionNegotiatorFactory negotiatorFactory;
private final NetconfClientSessionListener sessionListener;
package org.opendaylight.controller.netconf.client;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelFutureListener;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
public class NetconfClientSessionNegotiator extends
AbstractNetconfSessionNegotiator<NetconfClientSessionPreferences, NetconfClientSession, NetconfClientSessionListener>
}
@Override
- protected void handleMessage(NetconfHelloMessage netconfMessage) {
+ protected void handleMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException {
NetconfClientSession session = super.getSessionForHelloMessage(netconfMessage);
if (shouldUseExi(netconfMessage.getDocument())){
- logger.info("Netconf session: {} should use exi.", session);
+ logger.debug("Netconf session: {} should use exi.", session);
tryToStartExi(session);
} else {
- logger.info("Netconf session {} isn't capable using exi.", session);
+ logger.debug("Netconf session {} isn't capable using exi.", session);
negotiationSuccessful(session);
}
}
}
@Override
- protected NetconfClientSession getSession(NetconfClientSessionListener sessionListener, Channel channel, NetconfHelloMessage message) {
+ protected NetconfClientSession getSession(NetconfClientSessionListener sessionListener, Channel channel, NetconfHelloMessage message) throws NetconfDocumentedException {
return new NetconfClientSession(sessionListener, channel, extractSessionId(message.getDocument()),
NetconfMessageUtil.extractCapabilitiesFromHello(message.getDocument()));
}
package org.opendaylight.controller.netconf.client;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import io.netty.channel.Channel;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.openexi.proc.common.AlignmentType;
import org.openexi.proc.common.EXIOptions;
import org.openexi.proc.common.EXIOptionsException;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-
-import io.netty.channel.Channel;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class NetconfClientSessionNegotiatorFactory implements SessionNegotiatorFactory<NetconfMessage, NetconfClientSession, NetconfClientSessionListener> {
public static final java.util.Set<String> CLIENT_CAPABILITIES = Sets.newHashSet(
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_1,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1,
XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0);
private static final String START_EXI_MESSAGE_ID = "default-start-exi";
private final long connectionTimeoutMillis;
private final Timer timer;
private final EXIOptions options;
+ private static final Logger logger = LoggerFactory.getLogger(NetconfClientSessionNegotiatorFactory.class);
public NetconfClientSessionNegotiatorFactory(Timer timer,
Optional<NetconfHelloMessageAdditionalHeader> additionalHeader,
Promise<NetconfClientSession> promise) {
NetconfMessage startExiMessage = NetconfStartExiMessage.create(options, START_EXI_MESSAGE_ID);
- NetconfHelloMessage helloMessage = NetconfHelloMessage.createClientHello(CLIENT_CAPABILITIES, additionalHeader);
+ NetconfHelloMessage helloMessage = null;
+ try {
+ helloMessage = NetconfHelloMessage.createClientHello(CLIENT_CAPABILITIES, additionalHeader);
+ } catch (NetconfDocumentedException e) {
+ logger.error("Unable to create client hello message with capabilities {} and additional handler {}",CLIENT_CAPABILITIES,additionalHeader);
+ throw new IllegalStateException(e);
+ }
NetconfClientSessionPreferences proposal = new NetconfClientSessionPreferences(helloMessage,startExiMessage);
return new NetconfClientSessionNegotiator(proposal, promise, channel, timer,
public class SimpleNetconfClientSessionListener implements NetconfClientSessionListener {
private static final class RequestEntry {
- final Promise<NetconfMessage> promise;
- final NetconfMessage request;
+ private final Promise<NetconfMessage> promise;
+ private final NetconfMessage request;
public RequestEntry(Promise<NetconfMessage> future, NetconfMessage request) {
this.promise = Preconditions.checkNotNull(future);
org.opendaylight.controller.netconf.util.mapping,
org.opendaylight.controller.netconf.util.osgi,
org.opendaylight.controller.netconf.util.xml,
+ org.opendaylight.controller.netconf.util.exception,
org.opendaylight.controller.netconf.util.handler,
org.opendaylight.protocol.framework,
org.osgi.framework,
final Set<Capability> caps = netconfOperationService.getCapabilities();
for (Capability cap : caps) {
- if (cap.getModuleName().isPresent() == false)
- continue;
- if (cap.getRevision().isPresent() == false)
- continue;
- if (cap.getCapabilitySchema().isPresent() == false)
+ if (!cap.getModuleName().isPresent()
+ || !cap.getRevision().isPresent()
+ || !cap.getCapabilitySchema().isPresent()){
continue;
+ }
final String currentModuleName = cap.getModuleName().get();
Map<String, String> revisionMap = mappedModulesToRevisionToSchema.get(currentModuleName);
public DefaultCommitNotificationProducer(MBeanServer mBeanServer) {
this.mbeanServer = mBeanServer;
+ logger.debug("Registering to JMX under {}", on);
registerMBean(this, mbeanServer, on);
}
try {
mbs.registerMBean(instance, on);
} catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
- throw new RuntimeException("Unable to register " + instance + " as " + on, e);
+ throw new IllegalStateException("Unable to register " + instance + " as " + on, e);
}
}
package org.opendaylight.controller.netconf.impl;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-
public class NetconfServerSessionListener implements NetconfSessionListener<NetconfServerSession> {
static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionListener.class);
// TODO: should send generic error or close session?
logger.error("Unexpected exception", e);
session.onIncommingRpcFail();
- throw new RuntimeException("Unable to process incoming message " + netconfMessage, e);
+ throw new IllegalStateException("Unable to process incoming message " + netconfMessage, e);
} catch (NetconfDocumentedException e) {
+ logger.trace("Error occured while processing mesage {}",e);
session.onOutgoingRpcError();
session.onIncommingRpcFail();
SendErrorExceptionUtil.sendErrorMessage(session, e, netconfMessage);
import static org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider.NetconfOperationProviderUtil.getNetconfSessionIdForReporting;
+import com.google.common.collect.ImmutableSet;
import java.util.Set;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
import io.netty.channel.Channel;
import io.netty.util.Timer;
import io.netty.util.concurrent.Promise;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorFactory<NetconfHelloMessage, NetconfServerSession, NetconfServerSessionListener> {
- private static final Set<String> DEFAULT_CAPABILITIES = Sets.newHashSet(
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
- XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0);
+ private static final Set<String> DEFAULT_BASE_CAPABILITIES = ImmutableSet.of(
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0
+ // FIXME, Chunk framing causes ConcurrentClientsTest to fail, investigate
+// XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1,
+ // FIXME, EXI causing issues with sal-netconf-connector, investigate
+// XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0
+ );
private final Timer timer;
private final long connectionTimeoutMillis;
private final DefaultCommitNotificationProducer commitNotificationProducer;
private final SessionMonitoringService monitoringService;
+ private static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionNegotiatorFactory.class);
+ // TODO too many params, refactor
public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider,
SessionIdProvider idProvider, long connectionTimeoutMillis,
- DefaultCommitNotificationProducer commitNot, SessionMonitoringService monitoringService) {
+ DefaultCommitNotificationProducer commitNot,
+ SessionMonitoringService monitoringService) {
this.timer = timer;
this.netconfOperationProvider = netconfOperationProvider;
this.idProvider = idProvider;
getNetconfSessionIdForReporting(sessionId));
CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot);
- NetconfServerSessionPreferences proposal = new NetconfServerSessionPreferences(
- createHelloMessage(sessionId, capabilityProvider), sessionId);
+ NetconfServerSessionPreferences proposal = null;
+ try {
+ proposal = new NetconfServerSessionPreferences(
+ createHelloMessage(sessionId, capabilityProvider), sessionId);
+ } catch (NetconfDocumentedException e) {
+ logger.error("Unable to create hello mesage for session {} with capability provider {}", sessionId,capabilityProvider);
+ throw new IllegalStateException(e);
+ }
NetconfServerSessionListenerFactory sessionListenerFactory = new NetconfServerSessionListenerFactory(
commitNotificationProducer, monitoringService,
sessionListenerFactory.getSessionListener(), connectionTimeoutMillis);
}
- private NetconfHelloMessage createHelloMessage(long sessionId, CapabilityProvider capabilityProvider) {
- return NetconfHelloMessage.createServerHello(Sets.union(capabilityProvider.getCapabilities(), DEFAULT_CAPABILITIES), sessionId);
+ private NetconfHelloMessage createHelloMessage(long sessionId, CapabilityProvider capabilityProvider) throws NetconfDocumentedException {
+ return NetconfHelloMessage.createServerHello(Sets.union(capabilityProvider.getCapabilities(), DEFAULT_BASE_CAPABILITIES), sessionId);
}
}
package org.opendaylight.controller.netconf.impl.mapping.operations;
-import java.io.InputStream;
-import java.util.Map;
-
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
+import java.io.InputStream;
public class DefaultCommit extends AbstractNetconfOperation {
@Override
public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
- Preconditions.checkArgument(subsequentOperation.isExecutionTermination() == false,
+ Preconditions.checkArgument(!subsequentOperation.isExecutionTermination(),
"Subsequent netconf operation expected by %s", this);
if (isCommitWithoutNotification(requestMessage)) {
logger.debug("Skipping commit notification");
} else {
// Send commit notification if commit was not issued by persister
- requestMessage = removePersisterAttributes(requestMessage);
+ removePersisterAttributes(requestMessage);
Element cfgSnapshot = getConfigSnapshot(operationRouter);
logger.debug("Config snapshot retrieved successfully {}", cfgSnapshot);
notificationProducer.sendCommitNotification("ok", cfgSnapshot, cap.getCapabilities());
return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.increasePriority(1);
}
- private Document removePersisterAttributes(Document message) {
- final Element documentElement = message.getDocumentElement();
- documentElement.removeAttribute(NOTIFY_ATTR);
- return message;
+ private void removePersisterAttributes(Document message) {
+ message.getDocumentElement().removeAttribute(NOTIFY_ATTR);
}
private boolean isCommitWithoutNotification(Document message) {
- XmlElement xmlElement = XmlElement.fromDomElementWithExpected(message.getDocumentElement(),
- XmlNetconfConstants.RPC_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+ XmlElement xmlElement = null;
+ try {
+ xmlElement = XmlElement.fromDomElementWithExpected(message.getDocumentElement(),
+ XmlNetconfConstants.RPC_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+ } catch (NetconfDocumentedException e) {
+ logger.trace("Commit operation is not valid due to {}",e);
+ return false;
+ }
String attr = xmlElement.getAttribute(NOTIFY_ATTR);
- if (attr == null || attr.equals(""))
+ if (attr == null || attr.equals("")){
return false;
- else if (attr.equals(Boolean.toString(false))) {
+ } else if (attr.equals(Boolean.toString(false))) {
logger.debug("Commit operation received with notify=false attribute {}", message);
return true;
} else {
getConfigMessage, null);
XmlElement dataElement;
- try {
- XmlElement xmlElement = XmlElement.fromDomElementWithExpected(responseDocument.getDocumentElement(),
- XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
- dataElement = xmlElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY);
- } catch (IllegalArgumentException e) {
- final String msg = "Unexpected response from get-config operation";
- logger.warn(msg, e);
- Map<String, String> info = Maps.newHashMap();
- info.put(NetconfDocumentedException.ErrorTag.operation_failed.toString(), e.getMessage());
- throw new NetconfDocumentedException(msg, e, NetconfDocumentedException.ErrorType.application,
- NetconfDocumentedException.ErrorTag.operation_failed,
- NetconfDocumentedException.ErrorSeverity.error, info);
- }
-
+ XmlElement xmlElement = XmlElement.fromDomElementWithExpected(responseDocument.getDocumentElement(),
+ XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+ dataElement = xmlElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY);
return dataElement.getDomElement();
}
package org.opendaylight.controller.netconf.impl.mapping.operations;
-import java.util.HashMap;
-import java.util.Map;
-
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
+import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.collect.Maps;
+import java.util.Map;
public final class DefaultGetSchema extends AbstractLastNetconfOperation {
public static final String GET_SCHEMA = "get-schema";
protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
GetSchemaEntry entry;
- try {
- entry = new GetSchemaEntry(xml);
- } catch (final IllegalArgumentException e) {
- logger.warn("Error parsing xml", e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(NetconfDocumentedException.ErrorTag.bad_attribute.name(), e.getMessage());
- throw new NetconfDocumentedException(e.getMessage(), e, NetconfDocumentedException.ErrorType.rpc,
- NetconfDocumentedException.ErrorTag.bad_attribute, NetconfDocumentedException.ErrorSeverity.error,
- errorInfo);
- } catch (final IllegalStateException e) {
- logger.warn("Error parsing xml", e);
- final Map<String, String> errorInfo = new HashMap<>();
- errorInfo.put(NetconfDocumentedException.ErrorTag.bad_attribute.name(), e.getMessage());
- throw new NetconfDocumentedException(e.getMessage(), e, NetconfDocumentedException.ErrorType.rpc,
- NetconfDocumentedException.ErrorTag.bad_attribute, NetconfDocumentedException.ErrorSeverity.error,
- errorInfo);
- }
+ entry = new GetSchemaEntry(xml);
String schema;
try {
private final String identifier;
private final Optional<String> version;
- GetSchemaEntry(XmlElement getSchemaElement) {
+ GetSchemaEntry(XmlElement getSchemaElement) throws NetconfDocumentedException {
getSchemaElement.checkName(GET_SCHEMA);
getSchemaElement.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING);
- XmlElement identifierElement = getSchemaElement.getOnlyChildElementWithSameNamespace(IDENTIFIER);
+ XmlElement identifierElement = null;
+ try {
+ identifierElement = getSchemaElement.getOnlyChildElementWithSameNamespace(IDENTIFIER);
+ } catch (MissingNameSpaceException e) {
+ logger.trace("Can't get identifier element as only child element with same namespace due to {}",e);
+ throw NetconfDocumentedException.wrap(e);
+ }
identifier = identifierElement.getTextContent();
Optional<XmlElement> versionElement = getSchemaElement
.getOnlyChildElementWithSameNamespaceOptionally(VERSION);
private ServiceRegistration<NetconfMonitoringService> regMonitoring;
@Override
- public void start(final BundleContext context) throws Exception {
+ public void start(final BundleContext context) {
InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
"TCP is not configured, netconf not available.", false);
}
@Override
- public void stop(final BundleContext context) throws Exception {
+ public void stop(final BundleContext context) {
logger.info("Shutting down netconf because YangStoreService service was removed");
commitNot.close();
@Override
public void onSessionUp(NetconfManagementSession session) {
logger.debug("Session {} up", session);
- Preconditions.checkState(sessions.contains(session) == false, "Session %s was already added", session);
+ Preconditions.checkState(!sessions.contains(session), "Session %s was already added", session);
sessions.add(session);
}
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultNetconfOperation;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi;
-import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultNetconfOperation;
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 java.util.Collections;
import java.util.HashSet;
import java.util.Map;
+import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;
for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
final Set<NetconfOperation> netOpsFromService = netconfOperationService.getNetconfOperations();
for (NetconfOperation netconfOperation : netOpsFromService) {
- Preconditions.checkState(result.contains(netconfOperation) == false,
+ Preconditions.checkState(!result.contains(netconfOperation),
"Netconf operation %s already present", netconfOperation);
result.add(netconfOperation);
}
Preconditions.checkNotNull(allNetconfOperations, "Operation router was not initialized properly");
NetconfOperationExecution netconfOperationExecution;
- String messageAsString = XmlUtil.toString(message);
+ String messageAsString = "";
try {
+ messageAsString = XmlUtil.toString(message);
netconfOperationExecution = getNetconfOperationWithHighestPriority(message, session);
} catch (IllegalArgumentException | IllegalStateException e) {
logger.warn("Unable to handle rpc {} on session {}", messageAsString, session, e);
}
private NetconfOperationExecution getNetconfOperationWithHighestPriority(
- Document message, NetconfServerSession session) {
+ Document message, NetconfServerSession session) throws NetconfDocumentedException {
- TreeMap<HandlingPriority, NetconfOperation> sortedByPriority = getSortedNetconfOperationsWithCanHandle(
+ NavigableMap<HandlingPriority, NetconfOperation> sortedByPriority = getSortedNetconfOperationsWithCanHandle(
message, session);
Preconditions.checkArgument(sortedByPriority.isEmpty() == false,
}
private TreeMap<HandlingPriority, NetconfOperation> getSortedNetconfOperationsWithCanHandle(Document message,
- NetconfServerSession session) {
+ NetconfServerSession session) throws NetconfDocumentedException {
TreeMap<HandlingPriority, NetconfOperation> sortedPriority = Maps.newTreeMap();
for (NetconfOperation netconfOperation : allNetconfOperations) {
if (netconfOperation instanceof DefaultNetconfOperation) {
((DefaultNetconfOperation) netconfOperation).setNetconfSession(session);
}
- if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
+ if (!handlingPriority.equals(HandlingPriority.CANNOT_HANDLE)) {
- Preconditions.checkState(sortedPriority.containsKey(handlingPriority) == false,
+ Preconditions.checkState(!sortedPriority.containsKey(handlingPriority),
"Multiple %s available to handle message %s with priority %s",
NetconfOperation.class.getName(), message, handlingPriority);
sortedPriority.put(handlingPriority, netconfOperation);
return sortedPriority;
}
+ public static final NetconfOperationChainedExecution EXECUTION_TERMINATION_POINT = new NetconfOperationChainedExecution() {
+ @Override
+ public boolean isExecutionTermination() {
+ return true;
+ }
+
+ @Override
+ public Document execute(Document requestMessage) throws NetconfDocumentedException {
+ throw new NetconfDocumentedException("This execution represents the termination point in operation execution and cannot be executed itself",
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
+ };
+
private static class NetconfOperationExecution implements NetconfOperationChainedExecution {
private final NetconfOperation netconfOperation;
private NetconfOperationChainedExecution subsequentExecution;
}
public static NetconfOperationExecution createExecutionChain(
- TreeMap<HandlingPriority, NetconfOperation> sortedByPriority, HandlingPriority handlingPriority) {
+ NavigableMap<HandlingPriority, NetconfOperation> sortedByPriority, HandlingPriority handlingPriority) {
NetconfOperation netconfOperation = sortedByPriority.get(handlingPriority);
HandlingPriority subsequentHandlingPriority = sortedByPriority.lowerKey(handlingPriority);
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.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 org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
import org.opendaylight.controller.netconf.mapping.api.Capability;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
+import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-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.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 {
SessionIdProvider idProvider = new SessionIdProvider();
hashedWheelTimer = new HashedWheelTimer();
+
NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
hashedWheelTimer, factoriesListener, idProvider, 5000, commitNot, createMockedMonitoringService());
commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
-
-
NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(serverNegotiatorFactory);
dispatch = new NetconfServerDispatcher(serverChannelInitializer, nettyGroup, nettyGroup);
return Sets.<NetconfOperation> newHashSet(new NetconfOperation() {
@Override
public HandlingPriority canHandle(Document message) {
- return HandlingPriority.getHandlingPriority(Integer.MAX_VALUE);
+ return XmlUtil.toString(message).contains(NetconfStartExiMessage.START_EXI) ?
+ HandlingPriority.CANNOT_HANDLE :
+ HandlingPriority.HANDLE_WITH_MAX_PRIORITY;
}
@Override
commitNot.close();
}
- @Test
+ @Test(timeout = 30 * 1000)
public void multipleClients() throws Exception {
List<TestingThread> threads = new ArrayList<>();
}
}
- @Test
+ @Test(timeout = 30 * 1000)
public void synchronizationTest() throws Exception {
new BlockingThread("foo").run2();
}
- @Test
+ @Test(timeout = 30 * 1000)
public void multipleBlockingClients() throws Exception {
List<BlockingThread> threads = new ArrayList<>();
for (int i = 0; i < CONCURRENCY; i++) {
+++ /dev/null
-
-#24
-<rpc message-id="101" xm
-#28
-lns="urn:ietf:params:xml:ns:
-#2
-ne
-#33
-tconf:base:1.0">
- <my-own-method
-#3
- xm
-#13
-lns="http://e
-#34
-xample.net/me/my-own/1.0">
- <my
-#8
--first-p
-#21
-arameter>14</my-first
-#26
--parameter>
- <another-p
-#23
-arameter>fred</another-
-#31
-parameter>
- </my-own-method>
- <
-#2
-/r
-#3
-pc>
-##
+++ /dev/null
-
-#22
-<rpc message-id="101"
-#24
-xmlns="urn:ietf:params:x
-#15
-ml:ns:netconf:b
-#54
-ase:1.0">
- <get-config>
- <source>
- <r
-#2
-un
-#9
-ning/>
-
-#18
- </source> <fi
-#33
-lter type="subtree">
- <top x
-#4
-mlns
-#31
-="http://example.com/schema/1.2
-#15
-/config">
-
-#19
- <users>
-
-#8
- <us
-#3
-er/
-#5
->
-
-#77
- </users>
- </top>
- </filter>
- </g
-#17
-et-config>
-</rpc>
-##
+++ /dev/null
-
-#43
-<rpc message-id="101" xmlns="urn:ietf:param
-#14
-s:xml:ns:netco
-#14
-nf:base:1.0">
-
-#26
-<get-config>
- <source>
-
-#35
- <running/>
- </source>
-
-#39
- <filter type="subtree">
- <
-#40
-top xmlns="http://example.com/schema/1.2
-#26
-/config">
- <users>
-
-#36
- <user>
- <name>f
-#56
-red</name>
- </user>
- </users>
-
-#28
- </top>
- </fil
-#1
-t
-#28
-er>
- </get-config>
- </rpc>
-##
+++ /dev/null
-
-#17
-<rpc message-id="
-#25
-101" xmlns="urn:ietf:para
-#19
-ms:xml:ns:netconf:b
-#3
-ase
-#19
-:1.0">
- <get-confi
-#61
-g>
- <source>
- <running/>
- </source>
-
-#43
- <filter type="subtree">
- <!-- requ
-#13
-est a text ve
-#22
-rsion of the configura
-#9
-tion -->
-
-#16
- <config-text
-#45
-xmlns="http://example.com/text/1.2/config"/>
-
-#22
- </filter>
- </
-#18
-get-config>
-</rpc>
-##
+++ /dev/null
-
-#43
-<rpc message-id="101" xmlns="urn:ietf:param
-#41
-s:xml:ns:netconf:base:1.0">
- <edit-confi
-#29
-g>
- <target>
- <ru
-#13
-nning/>
- <
-#4
-/tar
-#18
-get>
- <config>
-
-#41
- <top xmlns="http://example.com/schema/1
-#32
-.2/config">
- <interface>
-
-#29
- <name>Ethernet0/0</na
-#30
-me>
- <mtu>1500</mtu>
-
-#61
-</interface>
- </top>
- </config>
- </e
-#9
-dit-confi
-#9
-g>
-</rpc>
-##
+++ /dev/null
-curl http://localhost:17777/jolokia/read/org.opendaylight.controller:instanceName=fixed1,type=ConfigBean,interfaceName=testing-threadpool | jsonpp
-{
- "request": {
- "mbean": "org.opendaylight.controller:instanceName=fixed1,interfaceName=testing-threadpool,type=ConfigBean",
- "type": "read"
- },
- "status": 200,
- "timestamp": 1362416252,
- "value": {
- "ExportedInterfaces": [
- "testing-threadpool",
- "modifiable-threadpool"
- ],
- "ImplementationName": "fixed",
- "ThreadCount": 10,
- "TriggerNewInstanceCreation": false
- }
-}
\ No newline at end of file
+++ /dev/null
-$ curl 'http://localhost:17777/jolokia/exec/org.opendaylight.controller:type=ConfigRegistry/lookupConfigBeans()' | jsonpp
-{
- "request": {
- "mbean": "org.opendaylight.controller:type=ConfigRegistry",
- "operation": "lookupConfigBeans()",
- "type": "exec"
- },
- "status": 200,
- "timestamp": 1362417043,
- "value": [
- {
- "objectName": "org.opendaylight.controller:instanceName=fixed1,interfaceName=modifiable-threadpool,type=ConfigBean"
- },
- {
- "objectName": "org.opendaylight.controller:instanceName=fixed1,interfaceName=testing-threadpool,type=ConfigBean"
- }
- ]
-}
+++ /dev/null
-<rpc message-id="104"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <commit/>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="102"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <lock>
- <target>
- <candidate/>
- </target>
- </lock>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="101"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <lock>
- <target>
- <running/>
- </target>
- </lock>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="103"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <edit-config>
- <target>
- <candidate/>
- </target>
- <default-operation>none</default-operation>
- <test-option>test-then-set</test-option>
- <error-option>stop-on-error</error-option>
- <nc:config
- xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
- xmlns="uri-for-my-data-model-namespace">
- <some-existing-node>
- <my-new-node nc:operation="create">
- <my-new-leaf>7</my-new-leaf>
- </my-new-node>
- </some-existing-node>
- </nc:config>
- </edit-config>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="105"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <unlock>
- <target>
- <candidate/>
- </target>
- </unlock>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc message-id="106"
- xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <unlock>
- <target>
- <running/>
- </target>
- </unlock>
-</rpc>
\ No newline at end of file
+++ /dev/null
-<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <rpc-error>
- <error-type>rpc</error-type>
- <error-tag>missing-attribute</error-tag>
- <error-severity>error</error-severity>
- <error-info>
- <bad-attribute>message-id</bad-attribute>
- <bad-element>rpc</bad-element>
- </error-info>
- </rpc-error>
-</rpc-reply>
+++ /dev/null
-{
- "value":null,
- "status":200,
- "request": {
- "type":"exec",
- "mbean":"java.util.logging:type=Logging",
- "operation":"setLoggerLevel",
- "arguments":["global","INFO"]
- }
-}
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <arguments>abc,bcd.aas</arguments>
- <arguments>64</arguments>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <arguments>
- <elements>22</elements>
- <elements>69</elements>
- </arguments>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <arguments>
- <map>
- <topology-registry>single</topology-registry>
- <bgp-update>mock</bgp-update>
- </map>
- <array>2</array>
- <array>22</array>
- <anotherArg>arg</anotherArg>
- </arguments>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<config>
- <jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <attribute>abc,bcd.aas</attribute>
- <attribute>22</attribute>
- </jmxbean>
- <jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>WRITE</type>
- <attribute>attribute</attribute>
- <value>22</value>
- </jmxbean>
- <jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>EXEC</type>
- <operation>lookupConfigBeans</operation>
- <arguments>
- <map>
- <topology-registry>single</topology-registry>
- <bgp-update>mock</bgp-update>
- </map>
- <array>2</array>
- <array>22</array>
- <anotherArg>arg</anotherArg>
- </arguments>
- </jmxbean>
-</config>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>WRITE</type>
- <attribute>attribute</attribute>
- <value>22</value>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>WRITE</type>
- <attribute>attribute</attribute>
- <value>22</value>
- <value>222</value>
- <value>223</value>
-</jmxbean>
\ No newline at end of file
+++ /dev/null
-<jmxbean>
- <mBean>org.opendaylight.controller:type=AppDeployer</mBean>
- <type>WRITE</type>
- <attribute>setAtr</attribute>
- <value>
- <abc>1</abc>
- <bcd>2</bcd>
- </value>
-</jmxbean>
+++ /dev/null
-{
- "timestamp":1362488209,
- "status":200,
- "request":{
- "mbean":"org.opendaylight.controller:type=ConfigRegistry",
- "attribute":"AvailableInterfacesAndImplementations",
- "type":"read"
- },
- "value":{
- "topology-registry":[
- "single"
- ],
- "bgp-update":[
- "mock",
- "bgp-impl"
- ],
- "positioning-service":[
- "combine",
- "onehop",
- "ondemand",
- "pxe",
- "precompute"
- ],
- "serializer":[
- "serializer-impl"
- ],
- "network-topology-factory":[
- "mock-xml",
- "bgp-network-topology-factory",
- "transient"
- ],
- "dwe-topology":[
- "ebgp",
- "defaultmetric",
- "igp",
- "network"
- ],
- "thread-factory":[
- "naming-thread-factory"
- ],
- "bgp-parser":[
- "parser"
- ],
- "pcep-dispatcher":[
- "dispatcher"
- ],
- "threadpool":[
- "flexible",
- "fixed",
- "scheduled"
- ],
- "scheduled-threadpool":[
- "scheduled"
- ],
- "positioning-onehop":[
- "onehop"
- ],
- "bgp-dispatcher":[
- "bgp-dispatcher-impl"
- ],
- "cost-combiner":[
- "pxe"
- ],
- "apsp-provider":[
- "jgrapht",
- "parallel",
- "single-threaded"
- ],
- "topology":[
- "ebgp",
- "defaultmetric",
- "igp",
- "network"
- ],
- "soap-resource":[
- "positioning-adaptor-pxe"
- ],
- "database-provider-factory":[
- "transient"
- ],
- "bgp-proposal-checker":[
- "bgp-proposal-checker-impl"
- ],
- "bgp-proposal":[
- "bgp-proposal-impl"
- ],
- "listenable-network-topology-factory":[
- "transient"
- ],
- "event-bus":[
- "sync",
- "async"
- ],
- "topology-registry-provider":[
- "single"
- ],
- "topology-provider-factory":[
- "transient"
- ],
- "rest-resource":[
- "topology-resource-holder",
- "alto-resource-holder",
- "topology-visual-holder",
- "network-resource-holder",
- "path-resource-holder"
- ],
- "listenable-database-provider-factory":[
- "transient"
- ],
- "topology-validator":[
- "accept-all",
- "threshold"
- ],
- "replicator":[
- "replicator-impl"
- ],
- "server":[
- "soap",
- "rest"
- ],
- "combiner-pxe":[
- "pxe"
- ],
- "rest":[
- "rest"
- ],
- "soap":[
- "soap"
- ],
- "path-service":[
- "cariden"
- ]
- }
-}
\ No newline at end of file
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>sal-binding-it</artifactId>
- <version>${mdsal.version}</version>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(NetconfITTest.getModuleFactoriesS().toArray(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,NetconfITTest.getModuleFactoriesS().toArray(
new ModuleFactory[0])));
NetconfMonitoringServiceImpl monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider());
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(getModuleFactories().toArray(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,getModuleFactories().toArray(
new ModuleFactory[0])));
NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
-import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean;
import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
import org.opendaylight.controller.netconf.StubUserManager;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(getModuleFactories().toArray(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,getModuleFactories().toArray(
new ModuleFactory[0])));
loadMessages();
}
}
- private void assertIsOK(final Document rpcReply) {
+ private void assertIsOK(final Document rpcReply) throws NetconfDocumentedException {
assertEquals("rpc-reply", rpcReply.getDocumentElement().getLocalName());
assertEquals("ok", XmlElement.fromDomDocument(rpcReply).getOnlyChildElement().getName());
}
- private Document assertGetConfigWorks(final TestingNetconfClient netconfClient) throws InterruptedException, ExecutionException, TimeoutException {
+ private Document assertGetConfigWorks(final TestingNetconfClient netconfClient) throws InterruptedException, ExecutionException, TimeoutException, NetconfDocumentedException {
return assertGetConfigWorks(netconfClient, this.getConfig);
}
private Document assertGetConfigWorks(final TestingNetconfClient netconfClient, final NetconfMessage getConfigMessage)
- throws InterruptedException, ExecutionException, TimeoutException {
+ throws InterruptedException, ExecutionException, TimeoutException, NetconfDocumentedException {
final NetconfMessage rpcReply = netconfClient.sendMessage(getConfigMessage);
assertNotNull(rpcReply);
assertEquals("data", XmlElement.fromDomDocument(rpcReply.getDocument()).getOnlyChildElement().getName());
import org.mockito.Mock;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
@Before
public void setUp() throws Exception {
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(NetconfITTest.getModuleFactoriesS().toArray(
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, NetconfITTest.getModuleFactoriesS().toArray(
new ModuleFactory[0])));
monitoringService = new NetconfMonitoringServiceImpl(getNetconfOperationProvider());
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-public class HandlingPriority implements Comparable<HandlingPriority> {
+public final class HandlingPriority implements Comparable<HandlingPriority> {
public static final HandlingPriority CANNOT_HANDLE = new HandlingPriority();
public static final HandlingPriority HANDLE_WITH_DEFAULT_PRIORITY = new HandlingPriority(Integer.MIN_VALUE);
@Override
public int compareTo(HandlingPriority o) {
- if (this == o)
+ if (this == o){
return 0;
- if (this == CANNOT_HANDLE)
+ }
+ if (this.equals(CANNOT_HANDLE)){
return -1;
- if (o == CANNOT_HANDLE)
+ }
+ if (o.equals(CANNOT_HANDLE)){
return 1;
+ }
- if (priority > o.priority)
+ if (priority > o.priority){
return 1;
- if (priority == o.priority)
+ }
+ if (priority.equals(o.priority)){
return 0;
- if (priority < o.priority)
+ }
+ if (priority < o.priority){
return -1;
-
+ }
throw new IllegalStateException("Unexpected state");
}
@Override
public boolean equals(Object o) {
- if (this == o)
+ if (this == o){
return true;
- if (!(o instanceof HandlingPriority))
+ }
+ if (!(o instanceof HandlingPriority)){
return false;
+ }
HandlingPriority that = (HandlingPriority) o;
- if (priority != null ? !priority.equals(that.priority) : that.priority != null)
+ if (priority != null ? !priority.equals(that.priority) : that.priority != null){
return false;
+ }
return true;
}
* @param requestMessage
* @return
*/
- HandlingPriority canHandle(Document requestMessage);
+ HandlingPriority canHandle(Document message) throws NetconfDocumentedException;
/**
* Execute current netconf operation and trigger execution of subsequent
org.opendaylight.controller.netconf.api,
org.opendaylight.controller.netconf.mapping.api,
org.opendaylight.controller.netconf.util.mapping,
+ org.opendaylight.controller.netconf.util.exception,
org.osgi.framework,
org.slf4j,
org.w3c.dom,
*/
package org.opendaylight.controller.netconf.monitoring;
-import java.util.Map;
-
+import com.google.common.collect.Maps;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
+import java.util.Map;
public class Get extends AbstractNetconfOperation {
this.netconfMonitor = netconfMonitor;
}
- private Element getPlaceholder(Document innerResult) {
+ private Element getPlaceholder(Document innerResult) throws NetconfDocumentedException {
try {
- XmlElement rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(),
- XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+ XmlElement rootElement = null;
+ 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(
@Override
public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation)
throws NetconfDocumentedException {
- Preconditions.checkArgument(subsequentOperation.isExecutionTermination() == false,
- "Subsequent netconf operation expected by %s", this);
+ if (subsequentOperation.isExecutionTermination()){
+ throw new NetconfDocumentedException(String.format("Subsequent netconf operation expected by %s", this),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
try {
Document innerResult = subsequentOperation.execute(requestMessage);
*/
package org.opendaylight.controller.netconf.monitoring;
-public class MonitoringConstants {
+public final class MonitoringConstants {
+ private MonitoringConstants(){
+ // not called - private constructor for utility class
+ }
public static final String MODULE_NAME = "ietf-netconf-monitoring";
public static final String MODULE_REVISION = "2010-10-04";
private NetconfMonitoringServiceTracker monitor;
@Override
- public void start(final BundleContext context) throws Exception {
+ public void start(final BundleContext context) {
monitor = new NetconfMonitoringServiceTracker(context);
monitor.open();
}
@Override
- public void stop(final BundleContext context) throws Exception {
+ public void stop(final BundleContext context) {
if(monitor!=null) {
try {
monitor.close();
*/
package org.opendaylight.controller.netconf.monitoring.osgi;
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.HashSet;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
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.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 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 {
- public static final HashSet<Capability> CAPABILITIES = Sets.<Capability>newHashSet(new Capability() {
+ public static final Set<Capability> CAPABILITIES = Sets.<Capability>newHashSet(new Capability() {
@Override
public String getCapabilityUri() {
this.monitor = monitor;
}
- private static String readSchema() {
- String schemaLocation = "/META-INF/yang/ietf-netconf-monitoring.yang";
- URL resource = Schemas.class.getClassLoader().getResource(schemaLocation);
- Preconditions.checkNotNull(resource, "Unable to read schema content from %s", schemaLocation);
- File file = new File(resource.getFile());
- try {
- return Files.toString(file, Charsets.UTF_8);
- } catch (IOException e) {
- throw new RuntimeException("Unable to load schema from " + schemaLocation, e);
- }
- }
-
@Override
public Set<Capability> getCapabilities() {
return CAPABILITIES;
*/
package org.opendaylight.controller.netconf.ssh;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.util.concurrent.atomic.AtomicLong;
-import javax.annotation.concurrent.ThreadSafe;
import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
import org.opendaylight.controller.netconf.ssh.threads.SocketThread;
import org.opendaylight.controller.usermanager.IUserManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.util.concurrent.atomic.AtomicLong;
+
@ThreadSafe
-public class NetconfSSHServer implements Runnable {
+public final class NetconfSSHServer implements Runnable {
private ServerSocket ss = null;
private static final Logger logger = LoggerFactory.getLogger(NetconfSSHServer.class);
private final AuthProvider authProvider;
private boolean up = false;
- private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress, AuthProvider authProvider) throws Exception{
+ private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress, AuthProvider authProvider) throws IllegalStateException, IOException {
logger.trace("Creating SSH server socket on port {}",serverPort);
this.ss = new ServerSocket(serverPort);
if (!ss.isBound()){
- throw new Exception("Socket can't be bound to requested port :"+serverPort);
+ throw new IllegalStateException("Socket can't be bound to requested port :"+serverPort);
}
logger.trace("Server socket created.");
this.clientAddress = clientAddress;
this.up = true;
}
- public static NetconfSSHServer start(int serverPort, InetSocketAddress clientAddress,AuthProvider authProvider) throws Exception {
+ public static NetconfSSHServer start(int serverPort, InetSocketAddress clientAddress,AuthProvider authProvider) throws IllegalStateException, IOException {
return new NetconfSSHServer(serverPort, clientAddress,authProvider);
}
- public void stop() throws Exception {
+ public void stop() throws IOException {
up = false;
logger.trace("Closing SSH server socket.");
ss.close();
try {
SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(),authProvider);
} catch (IOException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ logger.error("Exception occurred during socket thread initialization {}",e);
}
}
}
}
@Override
- public boolean authenticated(String username, String password) throws Exception {
+ public boolean authenticated(String username, String password) {
if (AuthProvider.um == null) {
- throw new Exception("No usermanager service available.");
+ throw new IllegalStateException("No usermanager service available.");
}
AuthResultEnum authResult = AuthProvider.um.authenticate(username, password);
return authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC);
public interface AuthProviderInterface {
- public boolean authenticated(String username, String password) throws Exception;
+ public boolean authenticated(String username, String password) throws IllegalStateException;
public char[] getPEMAsCharArray() throws Exception;
public void removeUserManagerService();
public void addUserManagerService(IUserManager userManagerService);
private IUserManager iUserManager;
private BundleContext context = null;
- ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
+ private ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
@Override
public IUserManager addingService(ServiceReference<IUserManager> reference) {
logger.trace("Service {} added, let there be SSH bridge.", reference);
@Override
- public void start(BundleContext context) throws Exception {
+ public void start(BundleContext context) {
this.context = context;
listenForManagerService();
}
@Override
- public void stop(BundleContext context) throws Exception {
+ public void stop(BundleContext context) throws IOException {
if (server != null){
server.stop();
logger.trace("Netconf SSH bridge is down ...");
}
}
- private void startSSHServer() throws Exception {
+ private void startSSHServer() throws IllegalStateException, IOException {
logger.trace("Starting netconf SSH bridge.");
Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE);
InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
String path = NetconfConfigUtil.getPrivateKeyPath(context);
path = path.replace("\\", "/"); // FIXME: shouldn't this convert lines to system dependent path separator?
if (path.equals("")){
- throw new Exception("Missing netconf.ssh.pk.path key in configuration file.");
+ throw new IllegalStateException("Missing netconf.ssh.pk.path key in configuration file.");
}
File privateKeyFile = new File(path);
- String privateKeyPEMString;
+ String privateKeyPEMString = null;
if (privateKeyFile.exists() == false) {
// generate & save to file
- privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
+ try {
+ privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
+ } catch (Exception e) {
+ logger.error("Exception occured while generating PEM string {}",e);
+ }
} else {
// read from file
try (FileInputStream fis = new FileInputStream(path)) {
throw new IllegalStateException("Error reading RSA key from file " + path);
}
}
- AuthProvider authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
+ AuthProvider authProvider = null;
+ try {
+ authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
+ } catch (Exception e) {
+ logger.error("Error instantiating AuthProvider {}",e);
+ }
this.server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress,authProvider);
Thread serverThread = new Thread(server,"netconf SSH server thread");
logger.trace("Netconf SSH bridge up and running.");
} else {
logger.trace("No valid connection configuration for SSH bridge found.");
- throw new Exception("No valid connection configuration for SSH bridge found.");
+ throw new IllegalStateException("No valid connection configuration for SSH bridge found.");
}
}
- private void onUserManagerFound(IUserManager userManager) throws Exception{
+ private void onUserManagerFound(IUserManager userManager) throws IOException {
if (server!=null && server.isUp()){
server.addUserManagerService(userManager);
} else {
if (netconf_ssh_input != null) {
netconf_ssh_input.join();
}
- } catch (InterruptedException e) {
+ } catch (InterruptedException e1) {
Thread.currentThread().interrupt();
- logger.error("netconf_ssh_input join error ", e);
+ logger.error("netconf_ssh_input join error ", e1);
}
try {
if (netconf_ssh_output != null) {
netconf_ssh_output.join();
}
- } catch (InterruptedException e) {
+ } catch (InterruptedException e2) {
Thread.currentThread().interrupt();
- logger.error("netconf_ssh_output join error ", e);
+ logger.error("netconf_ssh_output join error ", e2);
}
}
} else {
org.opendaylight.controller.netconf.util.mapping,
org.opendaylight.controller.netconf.util.messages,
org.opendaylight.controller.netconf.util.handler,
- org.opendaylight.controller.netconf.util.handler.*,</Export-Package>
+ org.opendaylight.controller.netconf.util.handler.*,
+ org.opendaylight.controller.netconf.util.exception,</Export-Package>
<Import-Package>com.google.common.base,
com.google.common.collect,
ch.ethz.ssh2,
@Override
public ChannelFuture sendMessage(final NetconfMessage netconfMessage) {
final ChannelFuture future = channel.writeAndFlush(netconfMessage);
- if (delayedEncoder !=null) {
+ if (delayedEncoder != null) {
replaceMessageEncoder(delayedEncoder);
delayedEncoder = null;
}
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.Promise;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSessionListener;
import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
}
@Override
- protected void handleMessage(NetconfHelloMessage netconfMessage) {
- S session = getSessionForHelloMessage(netconfMessage);
+ protected void handleMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException {
+ S session = getSessionForHelloMessage(netconfMessage) ;
negotiationSuccessful(session);
}
- protected final S getSessionForHelloMessage(NetconfHelloMessage netconfMessage) {
+ protected final S getSessionForHelloMessage(NetconfHelloMessage netconfMessage) throws NetconfDocumentedException {
Preconditions.checkNotNull(netconfMessage, "netconfMessage");
final Document doc = netconfMessage.getDocument();
return channel.pipeline().replace(handlerKey, handlerKey, decoder);
}
- protected abstract S getSession(L sessionListener, Channel channel, NetconfHelloMessage message);
+ protected abstract S getSession(L sessionListener, Channel channel, NetconfHelloMessage message) throws NetconfDocumentedException;
protected synchronized void changeState(final State newState) {
logger.debug("Changing state from : {} to : {}", state, newState);
package org.opendaylight.controller.netconf.util;
import com.google.common.base.Preconditions;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
return (doc == null) ? null : new NetconfMessage(doc);
}
- public static Document checkIsMessageOk(NetconfMessage responseMessage) {
- return checkIsMessageOk(responseMessage.getDocument());
- }
-
- public static Document checkIsMessageOk(Document response) {
+ public static Document checkIsMessageOk(Document response) throws NetconfDocumentedException {
XmlElement element = XmlElement.fromDomDocument(response);
Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
element = element.getOnlyChildElement();
--- /dev/null
+/*
+ * 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.exception;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class MissingNameSpaceException extends NetconfDocumentedException {
+
+ public MissingNameSpaceException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity) {
+ this(message, errorType, errorTag, errorSeverity, Collections.<String, String> emptyMap());
+ }
+
+ public MissingNameSpaceException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity, final Map<String, String> errorInfo){
+ super(message,errorType,errorTag,errorSeverity,errorInfo);
+ }
+}
--- /dev/null
+/*
+ * 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.exception;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class UnexpectedElementException extends NetconfDocumentedException {
+
+ public UnexpectedElementException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity) {
+ this(message, errorType, errorTag, errorSeverity, Collections.<String, String> emptyMap());
+ }
+
+ public UnexpectedElementException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity, final Map<String, String> errorInfo){
+ super(message,errorType,errorTag,errorSeverity,errorInfo);
+ }
+}
--- /dev/null
+/*
+ * 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.exception;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class UnexpectedNamespaceException extends NetconfDocumentedException {
+
+ public UnexpectedNamespaceException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity) {
+ this(message, errorType, errorTag, errorSeverity, Collections.<String, String> emptyMap());
+ }
+
+ public UnexpectedNamespaceException(final String message, final ErrorType errorType, final ErrorTag errorTag,
+ final ErrorSeverity errorSeverity, final Map<String, String> errorInfo){
+ super(message,errorType,errorTag,errorSeverity,errorInfo);
+ }
+}
}
@Override
- protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
+ protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) {
while (msg.readableBytes() > chunkSize) {
ByteBuf chunk = Unpooled.buffer(chunkSize);
chunk.writeBytes(createChunkHeader(chunkSize));
public class EOMFramingMechanismEncoder extends MessageToByteEncoder<ByteBuf> {
@Override
- protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
+ protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) {
out.writeBytes(msg);
out.writeBytes(NetconfMessageConstants.END_OF_MESSAGE);
}
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.MessageToByteEncoder;
-public class FramingMechanismHandlerFactory {
+public final class FramingMechanismHandlerFactory {
private static final Logger logger = LoggerFactory.getLogger(FramingMechanismHandlerFactory.class);
- private FramingMechanismHandlerFactory() {}
+ private FramingMechanismHandlerFactory() {
+ // not called - private constructor for utility class
+ }
public static MessageToByteEncoder<ByteBuf> createHandler(FramingMechanism framingMechanism) {
logger.debug("{} framing mechanism was selected.", framingMechanism);
public class NetconfChunkAggregator extends ByteToMessageDecoder {
private final static Logger logger = LoggerFactory.getLogger(NetconfChunkAggregator.class);
+ private static final String GOT_PARAM_WHILE_WAITING_FOR_PARAM = "Got byte {} while waiting for {}";
+ private static final String GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM = "Got byte {} while waiting for {}-{}";
public static final int DEFAULT_MAXIMUM_CHUNK_SIZE = 16 * 1024 * 1024;
private static enum State {
private long chunkSize;
private CompositeByteBuf chunk;
+ private void checkNewLine(byte b,String errorMessage){
+ if (b != '\n') {
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM, b, (byte)'\n');
+ throw new IllegalStateException(errorMessage);
+ }
+ }
+
+ private void checkHash(byte b,String errorMessage){
+ if (b != '#') {
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM, b, (byte)'#');
+ throw new IllegalStateException(errorMessage);
+ }
+ }
+
+ private void checkChunkSize(){
+ if (chunkSize > maxChunkSize) {
+ logger.debug("Parsed chunk size {}, maximum allowed is {}", chunkSize, maxChunkSize);
+ throw new IllegalStateException("Maximum chunk size exceeded");
+ }
+
+ }
@Override
- protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws IllegalStateException {
while (in.isReadable()) {
switch (state) {
case HEADER_ONE:
{
final byte b = in.readByte();
- if (b != '\n') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
- throw new IllegalStateException("Malformed chunk header encountered (byte 0)");
- }
+ checkNewLine(b, "Malformed chunk header encountered (byte 0)");
state = State.HEADER_TWO;
case HEADER_TWO:
{
final byte b = in.readByte();
- if (b != '#') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'#');
- throw new IllegalStateException("Malformed chunk header encountered (byte 1)");
- }
+ checkHash(b, "Malformed chunk header encountered (byte 1)");
state = State.HEADER_LENGTH_FIRST;
break;
}
if (b < '0' || b > '9') {
- logger.debug("Got byte {} while waiting for {}-{}", b, (byte)'0', (byte)'9');
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM, b, (byte)'0', (byte)'9');
throw new IllegalStateException("Invalid chunk size encountered");
}
chunkSize *= 10;
chunkSize += b - '0';
-
- if (chunkSize > maxChunkSize) {
- logger.debug("Parsed chunk size {}, maximum allowed is {}", chunkSize, maxChunkSize);
- throw new IllegalStateException("Maximum chunk size exceeded");
- }
+ checkChunkSize();
break;
}
case DATA:
in.discardReadBytes();
return;
}
-
aggregateChunks(in.readBytes((int) chunkSize));
state = State.FOOTER_ONE;
break;
case FOOTER_ONE:
{
final byte b = in.readByte();
- if (b != '\n') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
- throw new IllegalStateException("Malformed chunk footer encountered (byte 0)");
- }
-
+ checkNewLine(b,"Malformed chunk footer encountered (byte 0)");
state = State.FOOTER_TWO;
chunkSize = 0;
break;
case FOOTER_TWO:
{
final byte b = in.readByte();
-
- if (b != '#') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'#');
- throw new IllegalStateException("Malformed chunk footer encountered (byte 1)");
- }
-
+ checkHash(b,"Malformed chunk footer encountered (byte 1)");
state = State.FOOTER_THREE;
break;
}
// In this state, either header-of-new-chunk or message-end is expected
// Depends on the next character
- if (isHeaderLengthFirst(b)) {
- // Extract header length#1 from new chunk
- chunkSize = processHeaderLengthFirst(b);
- // Proceed with next chunk processing
- state = State.HEADER_LENGTH_OTHER;
- } else if (b == '#') {
- state = State.FOOTER_FOUR;
- } else {
- logger.debug("Got byte {} while waiting for {} or {}-{}", b, (byte) '#', (byte) '1', (byte) '9');
- throw new IllegalStateException("Malformed chunk footer encountered (byte 2)");
- }
+ extractNewChunkOrMessageEnd(b);
break;
}
case FOOTER_FOUR:
{
final byte b = in.readByte();
- if (b != '\n') {
- logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
- throw new IllegalStateException("Malformed chunk footer encountered (byte 3)");
- }
-
+ checkNewLine(b,"Malformed chunk footer encountered (byte 3)");
state = State.HEADER_ONE;
out.add(chunk);
chunk = null;
in.discardReadBytes();
}
+ private void extractNewChunkOrMessageEnd(byte b) {
+ if (isHeaderLengthFirst(b)) {
+ // Extract header length#1 from new chunk
+ chunkSize = processHeaderLengthFirst(b);
+ // Proceed with next chunk processing
+ state = State.HEADER_LENGTH_OTHER;
+ } else if (b == '#') {
+ state = State.FOOTER_FOUR;
+ } else {
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM, b, (byte) '#', (byte) '1', (byte) '9');
+ throw new IllegalStateException("Malformed chunk footer encountered (byte 2)");
+ }
+ }
+
private void initChunk() {
chunk = Unpooled.compositeBuffer();
}
}
private static int processHeaderLengthFirst(byte b) {
- if (isHeaderLengthFirst(b) == false) {
- logger.debug("Got byte {} while waiting for {}-{}", b, (byte)'1', (byte)'9');
+ if (!isHeaderLengthFirst(b)) {
+ logger.debug(GOT_PARAM_WHILE_WAITING_FOR_PARAM_PARAM, b, (byte)'1', (byte)'9');
throw new IllegalStateException("Invalid chunk size encountered (byte 0)");
}
private final static Logger logger = LoggerFactory.getLogger(NetconfEOMAggregator.class);
@Override
- protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
int index = indexOfSequence(in, NetconfMessageConstants.END_OF_MESSAGE);
if (index == -1) {
logger.debug("Message is not complete, read again.");
*/
package org.opendaylight.controller.netconf.util.handler;
-import java.io.ByteArrayInputStream;
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufOutputStream;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToByteEncoder;
import java.io.OutputStream;
-
+import javax.xml.transform.Transformer;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.openexi.sax.Transmogrifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.xml.sax.InputSource;
-
-import com.google.common.base.Preconditions;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufOutputStream;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.MessageToByteEncoder;
public final class NetconfMessageToEXIEncoder extends MessageToByteEncoder<NetconfMessage> {
private static final Logger LOG = LoggerFactory.getLogger(NetconfMessageToEXIEncoder.class);
- //private static final SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
+ private static final SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
private final NetconfEXICodec codec;
public NetconfMessageToEXIEncoder(final NetconfEXICodec codec) {
final Transmogrifier transmogrifier = codec.getTransmogrifier();
transmogrifier.setOutputStream(os);
- // FIXME transformer not working, see EXILibTest
- transmogrifier.encode(new InputSource(new ByteArrayInputStream(XmlUtil.toString(msg.getDocument()).getBytes())));
- //final Transformer transformer = saxTransformerFactory.newTransformer();
- //transformer.transform(new DOMSource(msg.getDocument()), new SAXResult(transmogrifier.getSAXTransmogrifier()));
+ final Transformer transformer = saxTransformerFactory.newTransformer();
+ transformer.transform(new DOMSource(msg.getDocument()), new SAXResult(transmogrifier.getSAXTransmogrifier()));
}
}
}
import io.netty.handler.codec.ByteToMessageDecoder;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
+import org.xml.sax.SAXException;
/**
* Customized NetconfXMLToMessageDecoder that reads additional header with
@Override
@VisibleForTesting
- public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+ public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws IOException, SAXException, NetconfDocumentedException {
if (in.readableBytes() == 0) {
LOG.debug("No more content in incoming buffer.");
return;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
+import java.io.IOException;
import java.util.List;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
+import org.xml.sax.SAXException;
public final class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToMessageDecoder.class);
@Override
@VisibleForTesting
- public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+ public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws IOException, SAXException {
if (in.readableBytes() != 0) {
LOG.trace("Received to decode: {}", ByteBufUtil.hexDump(in));
out.add(new NetconfMessage(XmlUtil.readXmlToDocument(new ByteBufInputStream(in))));
public void authenticate(Connection connection) throws IOException {
boolean isAuthenticated = connection.authenticateWithPassword(username, password);
- if (isAuthenticated == false) {
+ if (!isAuthenticated) {
throw new IOException("Authentication failed.");
}
}
}
public void close() {
- for (SshSession session : openSessions.values())
+ for (SshSession session : openSessions.values()){
closeSession(session);
+ }
openSessions.clear();
}
}
- while (stopRequested.get() == false) {
+ while (!stopRequested.get()) {
byte[] readBuff = new byte[BUFFER_SIZE];
int c = stdOut.read(readBuff);
if (c == -1) {
// Netty closed connection prematurely.
// Just pass and move on.
} catch (Exception e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
} finally {
sshClient.close();
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
-
import java.io.IOException;
import java.io.InputStream;
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
}
}
return this.bb.readByte() & 0xFF;
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) {
@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);
+ if (!subsequentOperation.isExecutionTermination()){
+ throw new NetconfDocumentedException(String.format("No netconf operation expected to be subsequent to %s, but is %s", this, subsequentOperation),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.malformed_message,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
return handleWithNoSubsequentOperations(document, operationElement);
}
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public abstract class AbstractNetconfOperation implements NetconfOperation {
private final String netconfSessionIdForReporting;
+ private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfOperation.class);
protected AbstractNetconfOperation(String netconfSessionIdForReporting) {
this.netconfSessionIdForReporting = netconfSessionIdForReporting;
}
@Override
- public HandlingPriority canHandle(Document message) {
- OperationNameAndNamespace operationNameAndNamespace = new OperationNameAndNamespace(message);
+ public HandlingPriority canHandle(Document message) throws NetconfDocumentedException {
+ OperationNameAndNamespace operationNameAndNamespace = null;
+ operationNameAndNamespace = new OperationNameAndNamespace(message);
return canHandle(operationNameAndNamespace.getOperationName(), operationNameAndNamespace.getNamespace());
}
public static final class OperationNameAndNamespace {
private final String operationName, namespace;
- public OperationNameAndNamespace(Document message) {
- XmlElement requestElement = getRequestElementWithCheck(message);
+ public OperationNameAndNamespace(Document message) throws NetconfDocumentedException {
+ XmlElement requestElement = null;
+ requestElement = getRequestElementWithCheck(message);
XmlElement operationElement = requestElement.getOnlyChildElement();
operationName = operationElement.getName();
}
}
- protected static XmlElement getRequestElementWithCheck(Document message) {
+ protected static XmlElement getRequestElementWithCheck(Document message) throws NetconfDocumentedException {
return XmlElement.fromDomElementWithExpected(message.getDocumentElement(), XmlNetconfConstants.RPC_KEY,
XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
}
package org.opendaylight.controller.netconf.util.messages;
-import java.util.Set;
-
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import java.util.Set;
/**
* NetconfMessage that can carry additional header with session metadata. See {@link org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader}
private final NetconfHelloMessageAdditionalHeader additionalHeader;
- public NetconfHelloMessage(Document doc, NetconfHelloMessageAdditionalHeader additionalHeader) {
+ public NetconfHelloMessage(Document doc, NetconfHelloMessageAdditionalHeader additionalHeader) throws NetconfDocumentedException {
super(doc);
checkHelloMessage(doc);
this.additionalHeader = additionalHeader;
}
- public NetconfHelloMessage(Document doc) {
+ public NetconfHelloMessage(Document doc) throws NetconfDocumentedException {
this(doc, null);
}
return additionalHeader== null ? Optional.<NetconfHelloMessageAdditionalHeader>absent() : Optional.of(additionalHeader);
}
- private static void checkHelloMessage(Document doc) {
- try {
- XmlElement.fromDomElementWithExpected(doc.getDocumentElement(), HELLO_TAG,
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+ private static void checkHelloMessage(Document doc) throws NetconfDocumentedException {
+ XmlElement.fromDomElementWithExpected(doc.getDocumentElement(), HELLO_TAG,
+ XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
- } catch (IllegalArgumentException | IllegalStateException e) {
- throw new IllegalArgumentException(String.format(
- "Hello message invalid format, should contain %s tag from namespace %s, but is: %s", HELLO_TAG,
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, XmlUtil.toString(doc)), e);
- }
}
public static NetconfHelloMessage createClientHello(Iterable<String> capabilities,
- Optional<NetconfHelloMessageAdditionalHeader> additionalHeaderOptional) {
+ Optional<NetconfHelloMessageAdditionalHeader> additionalHeaderOptional) throws NetconfDocumentedException {
Document doc = createHelloMessageDoc(capabilities);
return additionalHeaderOptional.isPresent() ? new NetconfHelloMessage(doc, additionalHeaderOptional.get())
: new NetconfHelloMessage(doc);
return doc;
}
- public static NetconfHelloMessage createServerHello(Set<String> capabilities, long sessionId) {
+ public static NetconfHelloMessage createServerHello(Set<String> capabilities, long sessionId) throws NetconfDocumentedException {
Document doc = createHelloMessageDoc(capabilities);
Element sessionIdElement = doc.createElement(XmlNetconfConstants.SESSION_ID);
sessionIdElement.setTextContent(Long.toString(sessionId));
import com.google.common.base.Charsets;
-public class NetconfMessageConstants {
+public final class NetconfMessageConstants {
+
+ private NetconfMessageConstants(){}
/**
* The NETCONF 1.0 old-style message separator. This is framing mechanism
* is used by default.
public static final int MAX_HEADER_LENGTH = 13;
public static final byte[] END_OF_CHUNK = "\n##\n".getBytes(Charsets.UTF_8);
+
}
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import javax.annotation.Nullable;
public final class NetconfMessageUtil {
+ private static final Logger logger = LoggerFactory.getLogger(NetconfMessageUtil.class);
+
private NetconfMessageUtil() {}
- public static boolean isOKMessage(NetconfMessage message) {
+ public static boolean isOKMessage(NetconfMessage message) throws NetconfDocumentedException {
return isOKMessage(message.getDocument());
}
- public static boolean isOKMessage(Document document) {
+ public static boolean isOKMessage(Document document) throws NetconfDocumentedException {
return isOKMessage(XmlElement.fromDomDocument(document));
}
- public static boolean isOKMessage(XmlElement xmlElement) {
+ public static boolean isOKMessage(XmlElement xmlElement) throws NetconfDocumentedException {
if(xmlElement.getChildElements().size() != 1) {
return false;
}
return xmlElement.getOnlyChildElement().getName().equals(XmlNetconfConstants.OK);
}
- public static boolean isErrorMessage(NetconfMessage message) {
+ public static boolean isErrorMessage(NetconfMessage message) throws NetconfDocumentedException {
return isErrorMessage(message.getDocument());
}
- public static boolean isErrorMessage(Document document) {
+ public static boolean isErrorMessage(Document document) throws NetconfDocumentedException {
return isErrorMessage(XmlElement.fromDomDocument(document));
}
- public static boolean isErrorMessage(XmlElement xmlElement) {
+ public static boolean isErrorMessage(XmlElement xmlElement) throws NetconfDocumentedException {
if(xmlElement.getChildElements().size() != 1) {
return false;
}
return xmlElement.getOnlyChildElement().getName().equals(XmlNetconfConstants.RPC_ERROR);
}
- public static Collection<String> extractCapabilitiesFromHello(Document doc) {
+ public static Collection<String> extractCapabilitiesFromHello(Document doc) throws NetconfDocumentedException {
XmlElement responseElement = XmlElement.fromDomDocument(doc);
XmlElement capabilitiesElement = responseElement
.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.CAPABILITIES);
@Override
public String apply(@Nullable XmlElement input) {
// Trim possible leading/tailing whitespace
- return input.getTextContent().trim();
+ try {
+ return input.getTextContent().trim();
+ } catch (NetconfDocumentedException e) {
+ logger.trace("Error fetching inpit text content becauese {}",e);
+ return null;
+ }
}
});
XPathConstants.NODE);
errorSeverityNode.setTextContent(sendErrorException.getErrorSeverity().getTagValue());
- if (sendErrorException.getErrorInfo() != null && sendErrorException.getErrorInfo().isEmpty() == false) {
+ if (sendErrorException.getErrorInfo() != null && !sendErrorException.getErrorInfo().isEmpty()) {
/*
* <error-info> <bad-attribute>message-id</bad-attribute>
* <bad-element>rpc</bad-element> </error-info>
Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound, forClient);
- if (inetSocketAddressOptional.isPresent() == false) {
+ if (!inetSocketAddressOptional.isPresent()) {
throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound);
}
InetSocketAddress inetSocketAddress = inetSocketAddressOptional.get();
package org.opendaylight.controller.netconf.util.xml;
import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
+import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
+import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public final class XmlElement {
private final Element element;
+ private static final Logger logger = LoggerFactory.getLogger(XmlElement.class);
private XmlElement(Element element) {
this.element = element;
return new XmlElement(xml.getDocumentElement());
}
- public static XmlElement fromString(String s) {
+ public static XmlElement fromString(String s) throws NetconfDocumentedException {
try {
return new XmlElement(XmlUtil.readXmlToElement(s));
} catch (IOException | SAXException e) {
- throw new IllegalArgumentException("Unable to create from " + s, e);
+ throw NetconfDocumentedException.wrap(e);
}
}
- public static XmlElement fromDomElementWithExpected(Element element, String expectedName) {
+ public static XmlElement fromDomElementWithExpected(Element element, String expectedName) throws NetconfDocumentedException {
XmlElement xmlElement = XmlElement.fromDomElement(element);
xmlElement.checkName(expectedName);
return xmlElement;
}
- public static XmlElement fromDomElementWithExpected(Element element, String expectedName, String expectedNamespace) {
+ public static XmlElement fromDomElementWithExpected(Element element, String expectedName, String expectedNamespace) throws NetconfDocumentedException {
XmlElement xmlElement = XmlElement.fromDomElementWithExpected(element, expectedName);
xmlElement.checkNamespace(expectedNamespace);
return xmlElement;
}
- private static Map<String, String> extractNamespaces(Element typeElement) {
+ private static Map<String, String> extractNamespaces(Element typeElement) throws NetconfDocumentedException {
Map<String, String> namespaces = new HashMap<>();
NamedNodeMap attributes = typeElement.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
if (attribKey.equals(XmlUtil.XMLNS_ATTRIBUTE_KEY)) {
prefix = "";
} else {
- Preconditions.checkState(attribKey.startsWith(XmlUtil.XMLNS_ATTRIBUTE_KEY + ":"));
+ if (!attribKey.startsWith(XmlUtil.XMLNS_ATTRIBUTE_KEY + ":")){
+ throw new NetconfDocumentedException("Attribute doesn't start with :",
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
prefix = attribKey.substring(XmlUtil.XMLNS_ATTRIBUTE_KEY.length() + 1);
}
namespaces.put(prefix, attribute.getNodeValue());
return namespaces;
}
- public void checkName(String expectedName) {
- Preconditions.checkArgument(getName().equals(expectedName), "Expected %s xml element but was %s", expectedName,
- getName());
+ public void checkName(String expectedName) throws UnexpectedElementException {
+ if (!getName().equals(expectedName)){
+ throw new UnexpectedElementException(String.format("Expected %s xml element but was %s", expectedName,
+ getName()),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
}
- public void checkNamespaceAttribute(String expectedNamespace) {
- Preconditions.checkArgument(getNamespaceAttribute().equals(expectedNamespace),
- "Unexpected namespace %s for element %s, should be %s", getNamespaceAttribute(), expectedNamespace);
+ public void checkNamespaceAttribute(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException {
+ if (!getNamespaceAttribute().equals(expectedNamespace))
+ {
+ throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s",
+ getNamespaceAttribute(),
+ expectedNamespace),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
}
- public void checkNamespace(String expectedNamespace) {
- Preconditions.checkArgument(getNamespace().equals(expectedNamespace),
- "Unexpected namespace %s for element %s, should be %s", getNamespace(), expectedNamespace);
+ public void checkNamespace(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException {
+ if (!getNamespace().equals(expectedNamespace))
+ {
+ throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s",
+ getNamespace(),
+ expectedNamespace),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
}
public String getName() {
final List<XmlElement> result = new ArrayList<>();
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
- if (item instanceof Element == false) {
+ if (!(item instanceof Element)) {
continue;
}
if (strat.accept((Element) item)) {
return getChildElementsInternal(new ElementFilteringStrategy() {
@Override
public boolean accept(Element e) {
- return XmlElement.fromDomElement(e).getNamespace().equals(namespace);
+ try {
+ return XmlElement.fromDomElement(e).getNamespace().equals(namespace);
+ } catch (MissingNameSpaceException e1) {
+ return false;
+ }
}
});
});
}
- public XmlElement getOnlyChildElement(String childName) {
+ public XmlElement getOnlyChildElement(String childName) throws NetconfDocumentedException {
List<XmlElement> nameElements = getChildElements(childName);
- Preconditions.checkState(nameElements.size() == 1, "One element " + childName + " expected in " + toString());
+ if (nameElements.size() != 1){
+ throw new NetconfDocumentedException("One element " + childName + " expected in " + toString(),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
return nameElements.get(0);
}
}
}
- public XmlElement getOnlyChildElementWithSameNamespace(String childName) {
+ public XmlElement getOnlyChildElementWithSameNamespace(String childName) throws NetconfDocumentedException {
return getOnlyChildElement(childName, getNamespace());
}
}
}
- public XmlElement getOnlyChildElementWithSameNamespace() {
+ public XmlElement getOnlyChildElementWithSameNamespace() throws NetconfDocumentedException {
XmlElement childElement = getOnlyChildElement();
childElement.checkNamespace(getNamespace());
return childElement;
}
}
- public XmlElement getOnlyChildElement(final String childName, String namespace) {
+ public XmlElement getOnlyChildElement(final String childName, String namespace) throws NetconfDocumentedException {
List<XmlElement> children = getChildElementsWithinNamespace(namespace);
children = Lists.newArrayList(Collections2.filter(children, new Predicate<XmlElement>() {
@Override
return xmlElement.getName().equals(childName);
}
}));
- Preconditions.checkState(children.size() == 1, "One element %s:%s expected in %s but was %s", namespace,
- childName, toString(), children.size());
+ if (children.size() != 1){
+ throw new NetconfDocumentedException(String.format("One element %s:%s expected in %s but was %s", namespace,
+ childName, toString(), children.size()),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
+
return children.get(0);
}
- public XmlElement getOnlyChildElement() {
+ public XmlElement getOnlyChildElement() throws NetconfDocumentedException {
List<XmlElement> children = getChildElements();
- Preconditions.checkState(children.size() == 1, "One element expected in %s but was %s", toString(),
- children.size());
+ if (children.size() != 1){
+ throw new NetconfDocumentedException(String.format( "One element expected in %s but was %s", toString(),
+ children.size()),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
return children.get(0);
}
- public String getTextContent() {
+ public String getTextContent() throws NetconfDocumentedException {
Node textChild = element.getFirstChild();
- Preconditions.checkNotNull(textChild, "Child node expected, got null for " + getName() + " : " + element);
- Preconditions.checkState(textChild instanceof Text, getName() + " should contain text." +
- Text.class.getName() + " expected, got " + textChild);
+ if (null == textChild){
+ throw new NetconfDocumentedException(String.format( "Child node expected, got null for " + getName() + " : " + element),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
+ if (!(textChild instanceof Text)){
+ throw new NetconfDocumentedException(String.format(getName() + " should contain text." +
+ Text.class.getName() + " expected, got " + textChild),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
String content = textChild.getTextContent();
// Trim needed
return content.trim();
}
- public String getNamespaceAttribute() {
+ public String getNamespaceAttribute() throws MissingNameSpaceException {
String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY);
- Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify namespace",
- toString());
+ if (attribute == null || attribute.equals("")){
+ throw new MissingNameSpaceException(String.format("Element %s must specify namespace",
+ toString()),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
return attribute;
}
- public String getNamespace() {
+ public String getNamespace() throws MissingNameSpaceException {
String namespaceURI = element.getNamespaceURI();
- Preconditions.checkState(namespaceURI != null, "No namespace defined for %s", this);
+ if (namespaceURI == null || namespaceURI.equals("")){
+ throw new MissingNameSpaceException(String.format("No namespace defined for %s", this),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
return namespaceURI;
}
final StringBuilder sb = new StringBuilder("XmlElement{");
sb.append("name='").append(getName()).append('\'');
if (element.getNamespaceURI() != null) {
- sb.append(", namespace='").append(getNamespace()).append('\'');
+ try {
+ sb.append(", namespace='").append(getNamespace()).append('\'');
+ } catch (MissingNameSpaceException e) {
+ logger.trace("Missing namespace for element.");
+ }
}
sb.append('}');
return sb.toString();
* namespace is returned with empty string as key. If no default namespace
* is found value will be null.
*/
- public Map.Entry<String/* prefix */, String/* namespace */> findNamespaceOfTextContent() {
+ public Map.Entry<String/* prefix */, String/* namespace */> findNamespaceOfTextContent() throws NetconfDocumentedException {
Map<String, String> namespaces = extractNamespaces(element);
String textContent = getTextContent();
int indexOfColon = textContent.indexOf(':');
} else {
prefix = "";
}
- if (namespaces.containsKey(prefix) == false) {
+ if (!namespaces.containsKey(prefix)) {
throw new IllegalArgumentException("Cannot find namespace for " + XmlUtil.toString(element) + ". Prefix from content is "
+ prefix + ". Found namespaces " + namespaces);
}
return Maps.immutableEntry(prefix, namespaces.get(prefix));
}
- public List<XmlElement> getChildElementsWithSameNamespace(final String childName) {
+ public List<XmlElement> getChildElementsWithSameNamespace(final String childName) throws MissingNameSpaceException {
List<XmlElement> children = getChildElementsWithinNamespace(getNamespace());
return Lists.newArrayList(Collections2.filter(children, new Predicate<XmlElement>() {
@Override
}
public void checkUnrecognisedElements(List<XmlElement> recognisedElements,
- XmlElement... additionalRecognisedElements) {
+ XmlElement... additionalRecognisedElements) throws NetconfDocumentedException {
List<XmlElement> childElements = getChildElements();
childElements.removeAll(recognisedElements);
for (XmlElement additionalRecognisedElement : additionalRecognisedElements) {
childElements.remove(additionalRecognisedElement);
}
- Preconditions.checkState(childElements.isEmpty(), "Unrecognised elements %s in %s", childElements, this);
+ if (!childElements.isEmpty()){
+ throw new NetconfDocumentedException(String.format("Unrecognised elements %s in %s", childElements, this),
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error);
+ }
}
- public void checkUnrecognisedElements(XmlElement... additionalRecognisedElements) {
- checkUnrecognisedElements(Collections.<XmlElement> emptyList(), additionalRecognisedElements);
+ public void checkUnrecognisedElements(XmlElement... additionalRecognisedElements) throws NetconfDocumentedException {
+ checkUnrecognisedElements(Collections.<XmlElement>emptyList(), additionalRecognisedElements);
}
@Override
public boolean hasNamespace() {
try {
getNamespaceAttribute();
- } catch (IllegalStateException e) {
+ } catch (MissingNameSpaceException e) {
try {
getNamespace();
- } catch (IllegalStateException e1) {
+ } catch (MissingNameSpaceException e1) {
return false;
}
return true;
public static final String SESSION_ID = "session-id";
//
+ // 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";
- public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_1 = "urn:ietf:params:xml:ns:netconf:base:1.1";
+// public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_1 = "urn:ietf:params:xml:ns:netconf:base:1.1";
+ public static final String URN_IETF_PARAMS_NETCONF_BASE_1_0 = "urn:ietf:params:netconf:base:1.0";
+ public static final String URN_IETF_PARAMS_NETCONF_BASE_1_1 = "urn:ietf:params:netconf:base:1.1";
public static final String URN_IETF_PARAMS_XML_NS_NETCONF_EXI_1_0 = "urn:ietf:params:xml:ns:netconf:exi:1.0";
public static final String URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0 = "urn:ietf:params:netconf:capability:exi:1.0";
package org.opendaylight.controller.netconf.util.xml;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.SchemaFactory;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
public final class XmlUtil {
try {
dBuilder = BUILDERFACTORY.newDocumentBuilder();
} catch (ParserConfigurationException e) {
- throw new RuntimeException("Failed to parse XML document", e);
+ throw new IllegalStateException("Failed to parse XML document", e);
}
Document doc = dBuilder.parse(xmlContent);
public static Document newDocument() {
try {
DocumentBuilder builder = BUILDERFACTORY.newDocumentBuilder();
- Document document = builder.newDocument();
- return document;
+ return builder.newDocument();
} catch (ParserConfigurationException e) {
- throw new RuntimeException("Failed to create document", e);
+ throw new IllegalStateException("Failed to create document", e);
}
}
transformer.transform(source, result);
return result.getWriter().toString();
- } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
- throw new RuntimeException("Unable to serialize xml element " + xml, e);
+ } catch (Exception | TransformerFactoryConfigurationError e) {
+ throw new IllegalStateException("Unable to serialize xml element " + xml, e);
}
}
+++ /dev/null
-/*
- * Copyright (c) 2014 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;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.StringWriter;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.dom.DOMResult;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.openexi.proc.common.AlignmentType;
-import org.openexi.proc.common.GrammarOptions;
-import org.openexi.proc.grammars.GrammarCache;
-import org.openexi.sax.EXIReader;
-import org.openexi.sax.Transmogrifier;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.InputSource;
-
-/**
- * This test case tests nagasena library used for exi encode/decode.
- *
- * This library does not work correctly, since it is impossible to encode and then decode DOM xml.
- * Encoding DOM using sax Transformer produces invalid xml, that cannot be decoded (Problem seems to be the namespace handling).
- *
- */
-@Ignore
-public class EXILibTest {
-
- public static final AlignmentType ALIGNMENT_TYPE = AlignmentType.preCompress;
-
- @Test
- public void testExiLibWithSaxTransformer() throws Exception {
- final byte[] encode = encodeEXI(getDom2());
- final byte[] encodeWithTransformer = encodeEXITransformer(getDom2());
-
- // System.err.println(Arrays.toString(encode));
- // System.err.println(Arrays.toString(encodeWithTransformer));
-
- // This works fine (encoded from string)
- decodeEXI(encode);
- // Error, encoded from Dom with Transformer cannot be decoded, Exception is thrown
- //
- // either:
- // org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
- //
- // or:
- // java.lang.NullPointerException
- //
- // depends on GrammarOptions.addNS(go); option set
- decodeEXI(encodeWithTransformer);
- }
-
- private static final SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
-
- public static byte[] encodeEXITransformer(final Element xml) throws Exception {
- final Transmogrifier transmogrifier = new Transmogrifier();
-
- transmogrifier.setAlignmentType(ALIGNMENT_TYPE);
-
- final ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- transmogrifier.setGrammarCache(getGrammarCache());
-
- transmogrifier.setOutputStream(out);
-
- final Transformer transformer = saxTransformerFactory.newTransformer();
- transformer.transform(new DOMSource(xml), new SAXResult(transmogrifier.getSAXTransmogrifier()));
-
- return out.toByteArray();
- }
-
- public static byte[] encodeEXI(final Element xml) throws Exception {
- final Transmogrifier transmogrifier = new Transmogrifier();
-
- transmogrifier.setAlignmentType(ALIGNMENT_TYPE);
-
- final ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- transmogrifier.setGrammarCache(getGrammarCache());
-
- transmogrifier.setOutputStream(out);
-
- transmogrifier.encode(new InputSource(new ByteArrayInputStream(toString(xml, false).getBytes())));
-
- out.flush();
-
- return out.toByteArray();
- }
-
- private static GrammarCache getGrammarCache() {
- short go = GrammarOptions.DEFAULT_OPTIONS;
-
- // This option on or off, nagasena still fails
-// go = GrammarOptions.addNS(go);
-
- return new GrammarCache(null, go);
- }
-
- public static Document decodeEXI(final byte[] input) throws Exception {
-
- final GrammarCache grammarCache;
- final DOMResult domResult = new DOMResult();
-
- try(ByteArrayInputStream in = new ByteArrayInputStream(input)) {
-
- final EXIReader reader = new EXIReader();
-
- reader.setAlignmentType(ALIGNMENT_TYPE);
- grammarCache = getGrammarCache();
-
- reader.setGrammarCache(grammarCache);
-
- final SAXTransformerFactory transformerFactory
- = (SAXTransformerFactory) TransformerFactory.newInstance();
- final TransformerHandler handler = transformerFactory.newTransformerHandler();
- handler.setResult(domResult);
-
- reader.setContentHandler(handler);
-
- reader.parse(new InputSource(in));
- }
-
- return (Document) domResult.getNode();
- }
-
- public static Element getDom() {
- final Element dom;
-
- final Document d = newDocument();
-
- dom = d.createElement("rpc");
- dom.setAttribute("xmlns", "a.b.c");
- dom.setAttribute("message-id", "id");
- dom.appendChild(d.createElement("inner"));
-
- return dom;
- }
-
- public static Element getDom2() {
- final Element dom;
-
- final Document d = newDocument();
-
- dom = d.createElementNS("a.b.c", "rpc");
- dom.setAttribute("message-id", "id");
- dom.appendChild(d.createElement("inner"));
-
- return dom;
- }
-
- private static final DocumentBuilderFactory BUILDERFACTORY;
-
- static {
- final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setNamespaceAware(true);
- factory.setCoalescing(true);
- factory.setIgnoringElementContentWhitespace(true);
- factory.setIgnoringComments(true);
- BUILDERFACTORY = factory;
- }
-
- private static Document newDocument() {
- try {
- final DocumentBuilder builder = BUILDERFACTORY.newDocumentBuilder();
- return builder.newDocument();
- } catch (final ParserConfigurationException e) {
- throw new RuntimeException("Failed to create document", e);
- }
- }
-
- private static String toString(final Element xml, final boolean addXmlDeclaration) {
- try {
- final Transformer transformer = TransformerFactory.newInstance().newTransformer();
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, addXmlDeclaration ? "no" : "yes");
-
- final StreamResult result = new StreamResult(new StringWriter());
- final DOMSource source = new DOMSource(xml);
- transformer.transform(source, result);
-
- return result.getWriter().toString();
- } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
- throw new RuntimeException("Unable to serialize xml element " + xml, e);
- }
- }
-}
package org.opendaylight.controller.netconf.util;
import org.junit.Test;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
public void testConflictingVersionDetection() throws Exception {
Document document = XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/netconfMessages/conflictingversion/conflictingVersionResponse.xml"));
try{
- NetconfUtil.checkIsMessageOk(new NetconfMessage(document));
+ NetconfUtil.checkIsMessageOk(document);
fail();
}catch(IllegalStateException e){
assertThat(e.getMessage(), containsString("Optimistic lock failed. Expected parent version 21, was 18"));
Thread.sleep(10);
}
} catch (InterruptedException e1) {
- logger.warn("DiscoveryTransmit interupted", e1.getMessage());
+ logger.trace("DiscoveryTransmit interupted", e1.getMessage());
if (shuttingDown) {
return;
}
Thread.sleep(100);
} catch (InterruptedException e1) {
- logger.warn("TopologyNotify interrupted {}",
+ logger.trace("TopologyNotify interrupted {}",
e1.getMessage());
if (shuttingDown) {
return;
}
}
} catch (InterruptedException e1) {
- logger.warn(
+ logger.trace(
"Edge Bandwidth Utilization Notify Thread interrupted {}",
e1.getMessage());
if (shuttingDown) {
logger.debug("Bulk Notify container:{}", containerName);
TopologyBulkUpdate(containerName);
} catch (InterruptedException e) {
- logger.warn("Topology Bulk update thread interrupted");
+ logger.trace("Topology Bulk update thread interrupted");
if (shuttingDown) {
- return;
- }
+ return; }
}
}
}
protected void pollTxBitRates() {
Map<NodeConnector, Pair<Edge, Set<Property>>> globalContainerEdges = edgeMap
.get(GlobalConstants.DEFAULT.toString());
+ if (shuttingDown) {
+ logger.trace("Getting out the pollTxBitRates because bundle going down");
+ return;
+ }
if (globalContainerEdges == null) {
return;
}
logger.trace("STOP called!");
shuttingDown = true;
notifyThread.interrupt();
+ bwUtilNotifyThread.interrupt();
+ ofPluginTopoBulkUpdate.interrupt();
+ pollTimer.cancel();
}
void setTopologyServiceShimListener(Map<?, ?> props,
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.2-SNAPSHOT</version>
+ <relativePath>../../commons/opendaylight</relativePath>
+ </parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustersession</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>javax.servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.catalina</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.catalina.ha</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.coyote</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.juli.extras</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.tomcat.api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.tomcat.util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.9.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>1.5.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>1.5.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Fragment-Host>org.eclipse.gemini.web.tomcat</Fragment-Host>
+ <Export-Package>org.opendaylight.controller.clustersession</Export-Package>
+ <Import-Package>org.apache.catalina,
+ org.apache.catalina.session,
+ org.apache.catalina.util,
+ org.apache.catalina.ha.session,
+ javax.servlet,
+ javax.servlet.http,
+ org.slf4j,
+ org.osgi.framework,
+ org.eclipse.osgi.framework.console,
+ org.opendaylight.controller.clustering.services</Import-Package>
+ </instructions>
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+package org.opendaylight.controller.clustersession;
+
+import java.beans.PropertyChangeSupport;
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.catalina.Manager;
+import org.apache.catalina.SessionListener;
+import org.apache.catalina.session.StandardSession;
+import org.opendaylight.controller.clustersession.service.ClusterSessionService;
+
+public class ClusterSession extends StandardSession implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private transient ClusterSessionService sessionService;
+
+ public ClusterSession(Manager manager, ClusterSessionService sessionService) {
+ super(manager);
+ this.sessionService = sessionService;
+ }
+
+ public void setSessionService(ClusterSessionService sessionService){
+ this.sessionService = sessionService;
+ }
+
+ @Override
+ public void setAuthType(String authType) {
+ super.setAuthType(authType);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void setCreationTime(long time) {
+ super.setCreationTime(time);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void setMaxInactiveInterval(int interval) {
+ super.setMaxInactiveInterval(interval);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void setNew(boolean isNew) {
+ super.setNew(isNew);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void setPrincipal(Principal principal) {
+ super.setPrincipal(principal);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void setValid(boolean isValid) {
+ super.setValid(isValid);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void access() {
+ super.access();
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void endAccess() {
+ super.endAccess();
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void removeAttribute(String name, boolean notify) {
+ super.removeAttribute(name, notify);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void setAttribute(String name, Object value, boolean notify) {
+ super.setAttribute(name, value, notify);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void recycle() {
+ super.recycle();
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void removeNote(String name) {
+ super.removeNote(name);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void addSessionListener(SessionListener listener) {
+ super.addSessionListener(listener);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void removeSessionListener(SessionListener listener) {
+ super.removeSessionListener(listener);
+ sessionService.updateSession(this);
+ }
+
+ @Override
+ public void setNote(String name, Object value) {
+ super.setNote(name, value);
+ sessionService.updateSession(this);
+ }
+
+ /*
+ * Certain fields inside Standard session are not serialized, We need to process them here
+ */
+ public void afterDeserialization(){
+ if (listeners == null){
+ listeners = new ArrayList<SessionListener>();
+ }
+ if (notes == null){
+ notes = new ConcurrentHashMap<String, Object>();
+ }
+ if(support == null){
+ support = new PropertyChangeSupport(this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("ClusterSession[");
+ sb.append(id);
+ sb.append(", isNew : ");
+ sb.append(isNew);
+ sb.append(", isValid : ");
+ sb.append(isValid);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ /*
+ * These methods are added for deserialization purpose
+ */
+
+ public void setAuthTypeInternal(String authType){
+ this.authType = authType;
+ }
+
+ public void setPrincipalInternal(Principal principal){
+ this.principal = principal;
+ }
+
+ public void setNoteInternal(String name, Object value) {
+ notes.put(name, value);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.clustersession;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+public class ClusterSessionData implements Serializable{
+
+ private static final long serialVersionUID = 1L;
+
+ private ClusterSession session;
+
+ private byte[] principalData;
+
+ private byte[] savedRequestData;
+
+ private byte[] savedPrincipalData;
+
+ private String authType;
+
+ private String userName;
+
+ private String password;
+
+ public ClusterSession getSession() {
+ return session;
+ }
+
+ public void setSession(final ClusterSession session) {
+ this.session = session;
+ }
+
+ public byte[] getPrincipalData() {
+ return principalData;
+ }
+
+ public void setPrincipalData(final byte[] principalData) {
+ this.principalData = Arrays.copyOf(principalData, principalData.length);
+ }
+
+ public String getAuthType() {
+ return authType;
+ }
+
+ public void setAuthType(String authType) {
+ this.authType = authType;
+ }
+
+ public byte[] getSavedRequestData() {
+ return savedRequestData;
+ }
+
+ public void setSavedRequestData(byte[] savedRequestData) {
+ this.savedRequestData = Arrays.copyOf(savedRequestData, savedRequestData.length);
+ }
+
+ public byte[] getSavedPrincipalData() {
+ return savedPrincipalData;
+ }
+
+ public void setSavedPrincipalData(byte[] savedPrincipalData) {
+ this.savedPrincipalData = Arrays.copyOf(savedPrincipalData, savedPrincipalData.length);
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ */
+package org.opendaylight.controller.clustersession;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleState;
+import org.apache.catalina.Session;
+import org.apache.catalina.session.ManagerBase;
+import org.apache.catalina.util.SessionIdGenerator;
+import org.opendaylight.controller.clustersession.impl.ClusterSessionServiceImpl;
+import org.opendaylight.controller.clustersession.service.ClusterSessionService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+/**
+ * ClusterSession Manager is a custom session manager, that is used to persist session data
+ * across cluster of a storage such as infinispan or memcache
+ * @author harman singh
+ *
+ */
+public class ClusterSessionManager extends ManagerBase{
+ /**
+ * Has this component been _started yet?
+ */
+ protected boolean started = false;
+
+ protected ClusterSessionService sessionService;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ClusterSessionManager.class);
+ /**
+ * The descriptive information about this implementation.
+ */
+ protected static final String INFO = "ClusterSessionManager/1.0";
+
+ /**
+ * The descriptive name of this Manager implementation (for logging).
+ */
+ protected static final String NAME = "ClusterSessionManager";
+
+ public ClusterSessionManager(){
+ sessionService = new ClusterSessionServiceImpl(this);
+ }
+
+ /**
+ * Return descriptive information about this Manager implementation and
+ * the corresponding version number, in the format
+ * <code><description>/<version></code>.
+ */
+ @Override
+ public String getInfo(){
+ return INFO;
+ }
+
+ /**
+ * Return the descriptive short name of this Manager implementation.
+ */
+ @Override
+ public String getName(){
+ return NAME;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void load() throws ClassNotFoundException, IOException {
+ // We are not persisting any session in database, infinispan does not persist data.
+ // loading of persisted session is not required.
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void unload() throws IOException {
+ // We are not persisting any session in database, infinispan does not persist data.
+ // unloading of session to persistence layer is not required.
+ }
+
+ /**
+ * Start this component and implement the requirements
+ * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
+ *
+ * @exception LifecycleException if this component detects a fatal error
+ * that prevents this component from being used
+ */
+ @Override
+ protected synchronized void startInternal() throws LifecycleException {
+ sessionIdGenerator = new SessionIdGenerator();
+ sessionIdGenerator.setJvmRoute(getJvmRoute());
+ sessionIdGenerator.setSecureRandomAlgorithm(getSecureRandomAlgorithm());
+ sessionIdGenerator.setSecureRandomClass(getSecureRandomClass());
+ sessionIdGenerator.setSecureRandomProvider(getSecureRandomProvider());
+ sessionIdGenerator.setSessionIdLength(getSessionIdLength());
+ sessionService.startInternal(sessionIdGenerator);
+ setState(LifecycleState.STARTING);
+ }
+
+ /**
+ * Stop this component and implement the requirements
+ * of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
+ *
+ * @exception LifecycleException if this component detects a fatal error
+ * that prevents this component from being used
+ */
+ @Override
+ protected synchronized void stopInternal() throws LifecycleException {
+ setState(LifecycleState.STOPPING);
+
+ // Expire all active sessions
+ Session sessions[] = findSessions();
+ for (int i = 0; i < sessions.length; i++) {
+ Session session = sessions[i];
+ try {
+ if (session.isValid()) {
+ session.expire();
+ }
+ } catch (Exception e) {
+ LOGGER.warn(e.toString());
+ } finally {
+ // Measure against memory leaking if references to the session
+ // object are kept in a shared field somewhere
+ session.recycle();
+ }
+ }
+ // Require a new random number generator if we are restarted
+ super.stopInternal();
+ sessionService.stopInternal();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void expireSession(final String sessionId){
+ LOGGER.debug("SESSION EXPIRE : ", sessionId);
+ sessionService.expireSession(sessionId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void remove(final Session session){
+ LOGGER.debug("SESSION REMOVE : ", session.getId());
+ sessionService.removeSession(session.getId());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void remove(Session session, boolean update) {
+ sessionService.removeSession(session.getId());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Session findSession(final String id) throws IOException{
+ return sessionService.findSession(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Session createSession(final String sessionId){
+ LOGGER.debug("SESSION CREATE : ", sessionId);
+ if(sessionId != null){
+ Session session = sessionService.findSession(sessionId);
+ if(session != null){
+ return session;
+ }
+ }
+ return sessionService.createSession(sessionId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Session createEmptySession(){
+ return sessionService.createEmptySession();
+ }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void add(Session session){
+ LOGGER.debug("SESSION ADD : ", session.getId());
+ sessionService.addSession((ClusterSession)session);
+ }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public HashMap<String, String> getSession(String sessionId){
+ return sessionService.getSession(sessionId);
+ }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Session[] findSessions() {
+ return sessionService.findSessions();
+ }
+
+ public ClusterSessionService getSessionService() {
+ return sessionService;
+ }
+
+ public void setSessionService(ClusterSessionService sessionService) {
+ this.sessionService = sessionService;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ */
+package org.opendaylight.controller.clustersession;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.catalina.authenticator.Constants;
+import org.apache.catalina.authenticator.SavedRequest;
+import org.apache.catalina.ha.session.SerializablePrincipal;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.opendaylight.controller.clustersession.service.ClusterSessionService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ClusterSessionUtil will be used to convert ClusterSession object into ClusterSessionData object,
+ * which is serializable and can be passed for storage. This class also perform deserialization to
+ * create ClusterSession object
+ * @author harman singh
+ *
+ */
+
+public class ClusterSessionUtil {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ClusterSessionUtil.class);
+
+ private ClusterSessionUtil() {
+
+ }
+
+ /**
+ * Serialize the ClusterSession object to provide ClusterSessionData object,
+ * that will be used for storage like in inifinispan or memcache etc.
+ * @param session an instance of ClusterSession
+ * @return an instance of ClusterSessionData
+ */
+ public static ClusterSessionData getSerializableSession(ClusterSession session) {
+ if(session == null){
+ return null;
+ }
+ ClusterSessionData sessionData = new ClusterSessionData();
+ sessionData.setSession(session);
+ sessionData.setAuthType(session.getAuthType());
+ sessionData.setPrincipalData(serializePrincipal(session.getPrincipal()));
+ sessionData.setSavedRequestData(serializeSavedRequest(session.getNote(Constants.FORM_REQUEST_NOTE)));
+ Principal notePrincipal = (Principal) session.getNote(Constants.FORM_PRINCIPAL_NOTE);
+ byte[] principalBytes = serializePrincipal(notePrincipal);
+ sessionData.setSavedPrincipalData(principalBytes);
+ if(session.getPrincipal() == null && notePrincipal != null){
+ sessionData.setPrincipalData(principalBytes);
+ }
+ sessionData.setUserName((String) session.getNote(Constants.FORM_USERNAME));
+ sessionData.setPassword((String) session.getNote(Constants.FORM_PASSWORD));
+ return sessionData;
+ }
+
+ /**
+ * Deserialize the ClusterSessionData object that usually comes from storage
+ * to provide ClusterSession object,
+ * that will be used by Session Manager
+ * @param sessionData an instance of ClusterSessionData
+ * @param sessionService an instance of ClusterSessionService
+ * @param manager an instance of ClusterSessionManager
+ * @return an instance of ClusterSession
+ */
+
+ public static ClusterSession getDeserializedSession(ClusterSessionData sessionData, ClusterSessionService sessionService,
+ ClusterSessionManager manager) {
+ if(sessionData == null){
+ return null;
+ }
+ ClusterSession session = sessionData.getSession();
+ session.afterDeserialization();
+ session.setManager(manager);
+ session.setSessionService(sessionService);
+ if(sessionData.getAuthType() != null) {
+ session.setAuthTypeInternal(sessionData.getAuthType());
+ }
+ if(sessionData.getPrincipalData() != null && sessionData.getPrincipalData().length > 0){
+ session.setPrincipalInternal(deserializePrincipal(sessionData.getPrincipalData()));
+ }
+ if(sessionData.getSavedPrincipalData() != null && sessionData.getSavedPrincipalData().length > 0){
+ session.setNoteInternal(Constants.FORM_PRINCIPAL_NOTE, deserializePrincipal(sessionData.getSavedPrincipalData()));
+ }
+ if(sessionData.getSavedRequestData() != null && sessionData.getSavedRequestData().length > 0){
+ session.setNoteInternal(Constants.FORM_REQUEST_NOTE, deserializeSavedRequest(sessionData.getSavedRequestData()));
+ }
+ if(sessionData.getUserName() != null){
+ session.setNoteInternal(Constants.FORM_USERNAME, sessionData.getUserName());
+ }
+ if(sessionData.getPassword() != null){
+ session.setNoteInternal(Constants.FORM_PASSWORD, sessionData.getPassword());
+ }
+ return session;
+ }
+
+ private static byte[] serializePrincipal(final Principal principal){
+ if(principal == null) {
+ return new byte[0];
+ }
+ ByteArrayOutputStream bos = null;
+ ObjectOutputStream oos = null;
+ try {
+ bos = new ByteArrayOutputStream();
+ oos = new ObjectOutputStream(bos);
+ SerializablePrincipal.writePrincipal((GenericPrincipal) principal, oos );
+ oos.flush();
+ return bos.toByteArray();
+ } catch (IOException e) {
+ throw new IllegalArgumentException( "Non-serializable object", e);
+ } finally {
+ closeSilently(bos);
+ closeSilently(oos);
+ }
+ }
+
+ private static byte[] serializeSavedRequest(final Object obj) {
+ if(obj == null) {
+ return new byte[0];
+ }
+ final SavedRequest savedRequest = (SavedRequest) obj;
+ ByteArrayOutputStream bos = null;
+ ObjectOutputStream oos = null;
+ try {
+ bos = new ByteArrayOutputStream();
+ oos = new ObjectOutputStream(bos);
+ oos.writeObject(savedRequest.getContentType());
+ oos.writeObject(getHeaders(savedRequest));
+ oos.writeObject(newArrayList(savedRequest.getLocales()));
+ oos.writeObject(savedRequest.getMethod());
+ oos.writeObject(savedRequest.getQueryString());
+ oos.writeObject(savedRequest.getRequestURI());
+ oos.writeObject(savedRequest.getDecodedRequestURI());
+ oos.flush();
+ return bos.toByteArray();
+ } catch (IOException e) {
+ throw new IllegalArgumentException( "Non-serializable object", e);
+ } finally {
+ closeSilently(bos);
+ closeSilently(oos);
+ }
+ }
+
+ private static Principal deserializePrincipal(final byte[] data) {
+ ByteArrayInputStream bis = null;
+ ObjectInputStream ois = null;
+ try {
+ bis = new ByteArrayInputStream(data);
+ ois = new ObjectInputStream(bis);
+ return SerializablePrincipal.readPrincipal(ois);
+ } catch (IOException e) {
+ throw new IllegalArgumentException( "Could not deserialize principal", e);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException( "Could not deserialize principal", e);
+ } finally {
+ closeSilently(bis);
+ closeSilently(ois);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static SavedRequest deserializeSavedRequest(final byte[] data) {
+ ByteArrayInputStream bis = null;
+ ObjectInputStream ois = null;
+ try {
+ bis = new ByteArrayInputStream(data);
+ ois = new ObjectInputStream(bis);
+ final SavedRequest savedRequest = new SavedRequest();
+ savedRequest.setContentType((String) ois.readObject());
+ setHeaders(savedRequest, (Map<String, List<String>>) ois.readObject());
+ setLocales(savedRequest, (List<Locale>) ois.readObject());
+ savedRequest.setMethod((String) ois.readObject());
+ savedRequest.setQueryString((String) ois.readObject());
+ savedRequest.setRequestURI((String) ois.readObject());
+ savedRequest.setDecodedRequestURI((String) ois.readObject());
+ return savedRequest;
+ } catch (final IOException e) {
+ throw new IllegalArgumentException( "Could not deserialize SavedRequest", e );
+ } catch (final ClassNotFoundException e) {
+ throw new IllegalArgumentException( "Could not deserialize SavedRequest", e );
+ } finally {
+ closeSilently(bis);
+ closeSilently(ois);
+ }
+ }
+
+ private static void setLocales(final SavedRequest savedRequest, final List<Locale> locales) {
+ if(locales != null && !locales.isEmpty()) {
+ for (final Locale locale : locales) {
+ savedRequest.addLocale(locale);
+ }
+ }
+ }
+
+ private static <T> List<T> newArrayList(final Iterator<T> iter) {
+ if(!iter.hasNext()) {
+ return Collections.emptyList();
+ }
+ final List<T> result = new ArrayList<T>();
+ while (iter.hasNext()) {
+ result.add(iter.next());
+ }
+ return result;
+ }
+
+ private static Map<String, List<String>> getHeaders(final SavedRequest obj) {
+ final Map<String, List<String>> result = new HashMap<String, List<String>>();
+ final Iterator<String> namesIter = obj.getHeaderNames();
+ while (namesIter.hasNext()) {
+ final String name = namesIter.next();
+ final List<String> values = new ArrayList<String>();
+ result.put(name, values);
+ final Iterator<String> valuesIter = obj.getHeaderValues(name);
+ while (valuesIter.hasNext()) {
+ final String value = valuesIter.next();
+ values.add(value);
+ }
+ }
+ return result;
+ }
+
+ private static void setHeaders(final SavedRequest obj, final Map<String, List<String>> headers) {
+ if(headers != null) {
+ for (final Entry<String, List<String>> entry : headers.entrySet()) {
+ final List<String> values = entry.getValue();
+ for (final String value : values) {
+ obj.addHeader(entry.getKey(), value);
+ }
+ }
+ }
+ }
+
+ private static void closeSilently(final OutputStream os) {
+ if (os != null) {
+ try {
+ os.close();
+ } catch (final IOException f) {
+ LOGGER.debug("Exception occurred while closing output stream", f.toString());
+ }
+ }
+ }
+
+ private static void closeSilently(final InputStream is) {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (final IOException f) {
+ LOGGER.debug("Exception occurred while closing input stream", f.toString());
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ */
+package org.opendaylight.controller.clustersession.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.catalina.Session;
+import org.apache.catalina.util.SessionIdGenerator;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.clustersession.ClusterSession;
+import org.opendaylight.controller.clustersession.ClusterSessionData;
+import org.opendaylight.controller.clustersession.ClusterSessionManager;
+import org.opendaylight.controller.clustersession.ClusterSessionUtil;
+import org.opendaylight.controller.clustersession.service.ClusterSessionService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation to persist and retrieve session data from infinispan cache
+ * @author harman singh
+ *
+ */
+public class ClusterSessionServiceImpl implements ClusterSessionService,
+ ServiceTrackerCustomizer<IClusterGlobalServices, IClusterGlobalServices>{
+
+ private IClusterGlobalServices clusterGlobalServices = null;
+ private static final Logger LOGGER = LoggerFactory.getLogger(ClusterSessionServiceImpl.class);
+ private ConcurrentMap<String, ClusterSessionData> sessions = null;
+ private static final String SESSION_CACHE = "customSessionManager.sessionData";
+ private ClusterSessionManager manager = null;
+ private SessionIdGenerator sessionIdGenerator = null;
+ private BundleContext context = null;
+ private ServiceTracker<IClusterGlobalServices, IClusterGlobalServices> clusterTracker;
+ public ClusterSessionServiceImpl(ClusterSessionManager manager) {
+ this.manager = manager;
+ }
+ /**
+ * This method initialize the cluster service of opendaylight and
+ * create a cache map in infinispan
+ */
+
+ @Override
+ public void startInternal(SessionIdGenerator sessionIdGenerator){
+ this.sessionIdGenerator = sessionIdGenerator;
+ context = FrameworkUtil.getBundle(ClusterSessionManager.class).getBundleContext();
+ getClusterService();
+ createCache();
+ }
+
+ /**
+ * Removes the cluster service tracker while shut down
+ */
+ @Override
+ public void stopInternal(){
+ if(clusterTracker != null){
+ clusterTracker.close();
+ }
+ }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Session findSession(final String id){
+ if(id == null) {
+ return null;
+ }
+ if(sessions == null) {
+ LOGGER.debug("Session cache not present, try to create.");
+ createCache();
+ return null;
+ }
+ ClusterSessionData sessionData = sessions.get(id);
+ if(sessionData != null) {
+ LOGGER.debug("SESSION FOUND : ", id);
+ } else {
+ LOGGER.debug("SESSION NOTFOUND : ", id);
+ }
+ return ClusterSessionUtil.getDeserializedSession(sessionData, this, this.manager);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Session[] findSessions() {
+ if(sessions == null) {
+ LOGGER.debug("Session cache not present, try to create.");
+ createCache();
+ return new Session[0];
+ }
+ Collection<ClusterSessionData> sessionDataList = sessions.values();
+ ArrayList<ClusterSession> sessionList = new ArrayList<ClusterSession>();
+ for(ClusterSessionData sessionData : sessionDataList){
+ sessionList.add(ClusterSessionUtil.getDeserializedSession(sessionData, this, this.manager));
+ }
+ return sessionList.toArray(new Session[0]);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeSession(final String id){
+ if(sessions == null) {
+ LOGGER.debug("Session cache not present, try to create.");
+ createCache();
+ return;
+ }
+ sessions.remove(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void expireSession(final String id){
+ if(sessions == null) {
+ LOGGER.debug("Session cache not present, try to create.");
+ createCache();
+ return;
+ }
+ ClusterSessionData sessionData = sessions.get(id);
+ if(sessionData != null) {
+ sessionData.getSession().expire();
+ removeSession(id);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Session createSession(final String sessionId){
+ if(sessions == null) {
+ LOGGER.debug("Session cache not present, try to create.");
+ createCache();
+ return null;
+ }
+ Session session = createEmptySession();
+ session.setNew(true);
+ session.setValid(true);
+ session.setCreationTime(System.currentTimeMillis());
+ String id = sessionId;
+ if (id == null) {
+ id = generateSessionId();
+ }
+ session.setId(id);
+ return session;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addSession(final ClusterSession session){
+ if(sessions == null) {
+ LOGGER.debug("Session cache not present, try to create.");
+ createCache();
+ return;
+ }
+ ClusterSessionData sessionData = ClusterSessionUtil.getSerializableSession(session);
+ sessions.put(session.getId(), sessionData);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Session createEmptySession(){
+ return getNewSession();
+ }
+
+ /**
+ * Returns information about the session with the given session id.
+ *
+ * <p>The session information is organized as a HashMap, mapping
+ * session attribute names to the String representation of their values.
+ *
+ * @param sessionId Session id
+ *
+ * @return HashMap mapping session attribute names to the String
+ * representation of their values, or null if no session with the
+ * specified id exists, or if the session does not have any attributes
+ */
+ public HashMap<String, String> getSession(String sessionId) {
+ if(sessions == null) {
+ LOGGER.debug("Session cache not present, try to create.");
+ createCache();
+ return null;
+ }
+ ClusterSessionData sessionData = sessions.get(sessionId);
+ if (sessionData == null) {
+ return null;
+ }
+ ClusterSession s = ClusterSessionUtil.getDeserializedSession(sessionData, this, this.manager);
+ Enumeration<String> ee = s.getAttributeNames();
+ if (ee == null || !ee.hasMoreElements()) {
+ return null;
+ }
+ HashMap<String, String> map = new HashMap<String, String>();
+ while (ee.hasMoreElements()) {
+ String attrName = ee.nextElement();
+ map.put(attrName, s.getAttribute(attrName).toString());
+ }
+ return map;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void updateSession(ClusterSession session) {
+ if(sessions == null) {
+ LOGGER.debug("Session cache not present, try to create.");
+ createCache();
+ return;
+ }
+ if(session.getId() != null && sessions.get(session.getId()) != null){
+ ClusterSessionData sessionData = ClusterSessionUtil.getSerializableSession(session);
+ sessions.put(session.getId(), sessionData);
+ }
+ }
+
+ @Override
+ public IClusterGlobalServices addingService(ServiceReference<IClusterGlobalServices> reference) {
+ if (clusterGlobalServices == null) {
+ this.clusterGlobalServices = context.getService(reference);
+ createCache();
+ return clusterGlobalServices;
+ }
+ return null;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<IClusterGlobalServices> reference, IClusterGlobalServices service) {
+ // This method is added from ServiceTracker interface, We don't have to modify service.
+ }
+
+ @Override
+ public void removedService(ServiceReference<IClusterGlobalServices> reference, IClusterGlobalServices service) {
+ if (clusterGlobalServices == service) {
+ clusterGlobalServices = null;
+ }
+ }
+
+ /*
+ * Return an instance of Standard Session object with current session manager
+ */
+ private ClusterSession getNewSession() {
+ return new ClusterSession(this.manager, this);
+ }
+
+ /*
+ * Generate and return a new session identifier.
+ */
+ private String generateSessionId() {
+ String result = null;
+ do {
+ result = sessionIdGenerator.generateSessionId();
+ } while (sessions.containsKey(result));
+ return result;
+ }
+
+ private void createCache() {
+ allocateCache();
+ retrieveCache();
+ }
+
+ /*
+ * This is a fragment bundle, so We can't use Activator to set Service.
+ * This is the alternative to get registered clustered service
+ */
+ private void getClusterService(){
+ if (context != null) {
+ clusterTracker = new ServiceTracker<>(context, IClusterGlobalServices.class, this);
+ clusterTracker.open();
+ }
+ }
+
+ /*
+ * Allocate space in infinispan to persist session data
+ */
+ private void allocateCache() {
+ if (clusterGlobalServices == null) {
+ LOGGER.trace("un-initialized clusterGlobalService, can't create cache");
+ return;
+ }
+ try {
+ clusterGlobalServices.createCache(SESSION_CACHE,
+ EnumSet.of(IClusterServices.cacheMode.SYNC , IClusterServices.cacheMode.TRANSACTIONAL));
+
+ } catch (CacheConfigException cce) {
+ LOGGER.error("Cache configuration invalid - check cache mode", cce.toString());
+ } catch (CacheExistException ce) {
+ LOGGER.debug("Skipping cache creation as already present", ce.toString());
+ }
+ }
+
+ /*
+ * Fetch cached session data map object from infinispan
+ */
+ @SuppressWarnings("unchecked")
+ private void retrieveCache(){
+ if (clusterGlobalServices == null) {
+ LOGGER.trace("un-initialized clusterGlobalService, can't retrieve cache");
+ return;
+ }
+ sessions = (ConcurrentMap<String, ClusterSessionData>)clusterGlobalServices.getCache(SESSION_CACHE);
+ if(sessions == null){
+ LOGGER.warn("Failed to get session cache");
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.clustersession.service;
+
+import java.util.HashMap;
+
+import org.apache.catalina.Session;
+import org.apache.catalina.util.SessionIdGenerator;
+import org.opendaylight.controller.clustersession.ClusterSession;
+
+/**
+ * A service to handle session persistence and retrieval in any data store
+ *
+ * @author harman singh
+ *
+ */
+public interface ClusterSessionService {
+
+ /**
+ * This method performs all startup operations
+ */
+ void startInternal(SessionIdGenerator sessionIdGenerator);
+
+ /**
+ * Method to perform all clean up operations
+ */
+ void stopInternal();
+
+ /**
+ * Find Session object based on provided session id from persistance
+ * @param id
+ * @return an instance of Session
+ */
+ Session findSession(final String id);
+
+ /**
+ * Get an array of session objects available in storage
+ */
+ Session[] findSessions();
+
+ /**
+ * Remove a session object from persistence
+ * @param id of session object need to be removed
+ */
+ void removeSession(final String id);
+
+ /**
+ * Expire and remove a session object from persistence
+ * @param id of session object need to be expired
+ */
+ void expireSession(final String id);
+
+ /**
+ * Create a session object based on session id, if session is not present
+ * use random session id
+ * @param sessionId
+ * @return an instance of Session
+ */
+ Session createSession(final String sessionId);
+
+ /**
+ * Add a session object in persistence
+ * @param session an instance of ClusterSession
+ */
+ void addSession(final ClusterSession session);
+
+ /**
+ * Create an empty Session object
+ * @return session object
+ */
+ Session createEmptySession();
+
+ /**
+ * Fetch attributes of Session object fetched by supplied session id
+ * @param sessionId
+ * @return
+ */
+ HashMap<String, String> getSession(String sessionId);
+
+ /**
+ * update the session object in persistence
+ * @param session
+ */
+ void updateSession(final ClusterSession session);
+
+}
--- /dev/null
+package org.opendaylight.controller.clustersession;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.Session;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustersession.impl.ClusterSessionServiceImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({FrameworkUtil.class})
+public class ClusterSessionManagerTest {
+ static ClusterSessionManager manager = null;
+ static ClusterSessionServiceImpl sessionService = null;
+ private static final String SESSION_CACHE = "customSessionManager.sessionData";
+ static ConcurrentMap<String, ClusterSessionData> sessions = new ConcurrentHashMap<String, ClusterSessionData>();
+ private String sessionId = "1234567";
+ final String AUTH_TYPE = "FORM";
+ final String ATTRIBUTE_NAME = "AuthType";
+ final int SESSION_ID_LENGTH = 7;
+ @SuppressWarnings("unchecked")
+ @BeforeClass
+ public static void init(){
+ Bundle bundle = mock(Bundle.class);
+ BundleContext context = mock(BundleContext.class);
+ IClusterGlobalServices clusterGlobalService = mock(IClusterGlobalServices.class);
+ ServiceReference<IClusterGlobalServices> serviceReference = mock(ServiceReference.class);
+ PowerMockito.mockStatic(FrameworkUtil.class);
+ when(FrameworkUtil.getBundle(ClusterSessionManager.class)).thenReturn(bundle);
+ when(bundle.getBundleContext()).thenReturn(context);
+ when(context.getService(serviceReference)).thenReturn(clusterGlobalService);
+ when((ConcurrentMap<String, ClusterSessionData>)clusterGlobalService.getCache(SESSION_CACHE)).thenReturn(sessions);
+ Context containerContext = mock(Context.class);
+ manager = new ClusterSessionManager();
+ manager.setContainer(containerContext);
+ try {
+ manager.startInternal();
+ } catch (LifecycleException e) {
+ }
+ sessionService = (ClusterSessionServiceImpl) manager.getSessionService();
+ sessionService.addingService(serviceReference);
+ }
+
+ @Test
+ public void checkSessionManagerCreated(){
+ assertEquals("session manager info does not match", "ClusterSessionManager/1.0", manager.getInfo());
+ assertEquals("session manager name does not match", "ClusterSessionManager", manager.getName());
+ }
+
+ @Test
+ public void testCreateEmptySession(){
+ Session session = manager.createEmptySession();
+ assertEquals("session manager does not match", manager, session.getManager());
+ }
+
+ @Test
+ public void testCreateRandomSessionId(){
+ Session session = manager.createSession(null);
+ assertEquals("Session should be valid", true, session.isValid());
+ manager.remove(session);
+ }
+
+ @Test
+ public void testCreateSession(){
+ Session session = manager.createSession(sessionId);
+ assertEquals("Session should be valid", true, session.isValid());
+ assertEquals("Session id does not match", sessionId, session.getId());
+ manager.remove(session);
+ }
+
+ @Test
+ public void testReCreateSession(){
+ Session session = manager.createSession(sessionId);
+ assertEquals("Session should be valid", true, session.isValid());
+ assertEquals("Session id does not match", sessionId, session.getId());
+ manager.createSession(sessionId);
+ manager.remove(session);
+ }
+
+ @Test
+ public void testSessionCRUD() throws IOException{
+ Session foundSession = manager.findSession(sessionId);
+ assertNull("Session should not exist here", foundSession);
+ Session session = manager.createSession(sessionId);
+ manager.add(session);
+ foundSession = manager.findSession(sessionId);
+ assertEquals("Session was not found, id does not match", sessionId, foundSession.getId());
+ manager.remove(session);
+ foundSession = manager.findSession(sessionId);
+ assertEquals("Session was not removed", null, foundSession);
+ }
+
+ @Test
+ public void testExpireSession() throws IOException{
+ Session session = manager.createSession(sessionId);
+ session.setAuthType(AUTH_TYPE);
+ manager.add(session);
+ Session foundSession = manager.findSession(sessionId);
+ assertEquals("Session was not found", sessionId, foundSession.getId());
+ manager.expireSession(sessionId);
+ foundSession = manager.findSession(sessionId);
+ assertEquals("Session was not expired", null, foundSession);
+ }
+
+ @Test
+ public void testFindSessions(){
+ Session session = manager.createSession(sessionId);
+ session.setAuthType(AUTH_TYPE);
+ manager.add(session);
+ Session[] sessions = manager.findSessions();
+ assertEquals("Session array size does not match", 1, sessions.length);
+ assertEquals("Session array size does not match", sessionId, sessions[0].getId());
+ manager.remove(session);
+ }
+
+ @Test
+ public void testGetSession(){
+ ClusterSession session = (ClusterSession) manager.createSession(sessionId);
+ session.setAttribute(ATTRIBUTE_NAME, AUTH_TYPE);
+ manager.add(session);
+ HashMap<String, String> sessionAttributes = manager.getSession(sessionId);
+ assertNotNull("Session attribute should not be null", sessionAttributes);
+ assertEquals("Session attribute size does not match", 1, sessionAttributes.size());
+ assertEquals("Session attribute size does not match", AUTH_TYPE, sessionAttributes.get(ATTRIBUTE_NAME));
+ manager.remove(session);
+ }
+
+ @AfterClass
+ public static void cleanup(){
+ try {
+ manager.stopInternal();
+ } catch (LifecycleException e) {
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.clustersession;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Session;
+import org.apache.catalina.util.SessionIdGenerator;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustersession.impl.ClusterSessionServiceImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({FrameworkUtil.class})
+public class ClusterSessionServiceImplTest {
+ static ClusterSessionManager manager = null;
+ static ClusterSessionServiceImpl sessionService = null;
+ private static final String SESSION_CACHE = "customSessionManager.sessionData";
+ static ConcurrentMap<String, ClusterSessionData> sessions = new ConcurrentHashMap<String, ClusterSessionData>();
+ private String sessionId = "1234567";
+ final String AUTH_TYPE = "FORM";
+ final String ATTRIBUTE_NAME = "AuthType";
+
+ @SuppressWarnings("unchecked")
+ @BeforeClass
+ public static void init(){
+ Bundle bundle = mock(Bundle.class);
+ BundleContext context = mock(BundleContext.class);
+ IClusterGlobalServices clusterGlobalService = mock(IClusterGlobalServices.class);
+ ServiceReference<IClusterGlobalServices> serviceReference = mock(ServiceReference.class);
+ PowerMockito.mockStatic(FrameworkUtil.class);
+ when(FrameworkUtil.getBundle(ClusterSessionManager.class)).thenReturn(bundle);
+ when(bundle.getBundleContext()).thenReturn(context);
+ when(context.getService(serviceReference)).thenReturn(clusterGlobalService);
+ when((ConcurrentMap<String, ClusterSessionData>)clusterGlobalService.getCache(SESSION_CACHE)).thenReturn(sessions);
+ Context containerContext = mock(Context.class);
+ manager = new ClusterSessionManager();
+ sessionService = (ClusterSessionServiceImpl) manager.getSessionService();
+ manager.setContainer(containerContext);
+ sessionService.startInternal(new SessionIdGenerator());
+ sessionService.addingService(serviceReference);
+ }
+
+ @Test
+ public void testCreateEmptySession(){
+ Session session = sessionService.createEmptySession();
+ assertEquals("session manager does not match", manager, session.getManager());
+ }
+
+ @Test
+ public void testCreateSessionwithRandomId(){
+ Session session = sessionService.createSession(null);
+ assertEquals("Session should be valid", true, session.isValid());
+ sessionService.removeSession(session.getId());
+ }
+
+ @Test
+ public void testCreateSession(){
+ Session session = sessionService.createSession(sessionId);
+ assertEquals("Session should be valid", true, session.isValid());
+ assertEquals("Session id does not match", sessionId, session.getId());
+ sessionService.removeSession(sessionId);
+ }
+
+ @Test
+ public void testNullfindSession() {
+ Session session = sessionService.findSession(null);
+ assertNull("Session should be null", session);
+ }
+
+ @Test
+ public void testSessionCRUD(){
+ Session foundSession = sessionService.findSession(sessionId);
+ assertNull("Session should not exist here", foundSession);
+ Session session = sessionService.createSession(sessionId);
+ foundSession = sessionService.findSession(sessionId);
+ assertEquals("Session was not added", sessionId, foundSession.getId());
+ session.setAuthType(AUTH_TYPE);
+ sessionService.updateSession((ClusterSession)session);
+ foundSession = sessionService.findSession(sessionId);
+ assertEquals("Session was not found, id does not match", sessionId, foundSession.getId());
+ assertEquals("Session was not found, auth type does match", AUTH_TYPE, foundSession.getAuthType());
+ sessionService.removeSession(sessionId);
+ foundSession = sessionService.findSession(sessionId);
+ assertEquals("Session was not removed", null, foundSession);
+ }
+
+ @Test
+ public void testExpireSession(){
+ Session session = sessionService.createSession(sessionId);
+ session.setAuthType(AUTH_TYPE);
+ sessionService.addSession((ClusterSession)session);
+ Session foundSession = sessionService.findSession(sessionId);
+ assertEquals("Session was not found", sessionId, foundSession.getId());
+ sessionService.expireSession(sessionId);
+ foundSession = sessionService.findSession(sessionId);
+ assertEquals("Session was not expired", null, foundSession);
+ }
+
+ @Test
+ public void testFindSessions(){
+ Session session = sessionService.createSession(sessionId);
+ session.setAuthType(AUTH_TYPE);
+ sessionService.addSession((ClusterSession)session);
+ Session[] sessions = sessionService.findSessions();
+ assertEquals("Session array size does not match", 1, sessions.length);
+ assertEquals("Session array size does not match", sessionId, sessions[0].getId());
+ sessionService.removeSession(sessionId);
+ }
+
+ @Test
+ public void testGetSession(){
+ ClusterSession session = (ClusterSession) sessionService.createSession(sessionId);
+ session.setAttribute(ATTRIBUTE_NAME, AUTH_TYPE);
+ HashMap<String, String> sessionAttributes = sessionService.getSession(sessionId);
+ assertNotNull("Session attribute should not be null", sessionAttributes);
+ assertEquals("Session attribute size does not match", 1, sessionAttributes.size());
+ assertEquals("Session attribute size does not match", AUTH_TYPE, sessionAttributes.get(ATTRIBUTE_NAME));
+ sessionService.removeSession(sessionId);
+ }
+
+ @Test
+ public void testNullSessionCache(){
+ ClusterSessionManager clustermanager = new ClusterSessionManager();
+ ClusterSessionServiceImpl service = new ClusterSessionServiceImpl(clustermanager);
+ Session session = service.findSession(sessionId);
+ assertNull("Session should be null, as cache is null", session);
+ Session[] sessions = service.findSessions();
+ assertEquals("Session array should be empty", 0, sessions.length);
+ service.removeSession(sessionId);
+ service.expireSession(sessionId);
+ session = service.createSession(sessionId);
+ assertNull("Session should be null, as cache is null", session);
+ service.addSession(null);
+ Map<String,String> attributes = service.getSession(sessionId);
+ assertNull("Attributes should be null, as cache is null", attributes);
+ service.updateSession(null);
+ }
+
+ @AfterClass
+ public static void cleanup(){
+ sessionService.stopInternal();
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.clustersession;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.catalina.authenticator.Constants;
+import org.apache.catalina.authenticator.SavedRequest;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.junit.Test;
+import org.opendaylight.controller.clustersession.impl.ClusterSessionServiceImpl;
+import org.opendaylight.controller.clustersession.service.ClusterSessionService;
+
+
+public class ClusterSessionUtilTest {
+
+ final String AUTH_TYPE = "FORM";
+ final String ADMIN = "admin";
+ final String REQUEST_URI = "/test";
+ final String BLANK = "";
+ final String HEADER_NAME = "ContentType";
+ final String HEADER_VALUE = "JSON";
+ final long creationTime = 54545454L;
+ final int interval = 0;
+ ClusterSessionManager manager = new ClusterSessionManager();
+ ClusterSessionService sessionService = new ClusterSessionServiceImpl(manager);
+
+ @Test
+ public void testNullSerializableClusterSession() {
+ ClusterSessionData sessionData = ClusterSessionUtil.getSerializableSession(null);
+ assertEquals("Session data should be null for null session", null, sessionData);
+ }
+
+ @Test
+ public void testSerializableClusterSession() {
+ ClusterSession customSession = createClusterSesion();
+ ClusterSessionData sessionData = ClusterSessionUtil.getSerializableSession(customSession);
+ assertEquals("Session authentication type not valid", AUTH_TYPE, sessionData.getAuthType());
+ assertEquals("Session username does not match", ADMIN, sessionData.getUserName());
+ assertEquals("Session password does not match", ADMIN, sessionData.getPassword());
+ assertEquals("Session prinicpal does not match", ADMIN, sessionData.getSession().getPrincipal().getName());
+ }
+
+ @Test
+ public void testNullDeserialzableclusterSession() {
+ ClusterSession session = ClusterSessionUtil.getDeserializedSession(null, sessionService, manager);
+ assertEquals("Session should be null for null session data", null, session);
+ }
+
+ @Test
+ public void testDeserializableClusterSesion() {
+ ClusterSession customSession = createClusterSesion();
+ ClusterSessionData sessionData = ClusterSessionUtil.getSerializableSession(customSession);
+ customSession = sessionData.getSession();
+ customSession.setAuthType(AUTH_TYPE);
+ customSession.setNote(Constants.FORM_PRINCIPAL_NOTE, BLANK);
+ customSession.setNote(Constants.FORM_REQUEST_NOTE, BLANK);
+ ClusterSession session = ClusterSessionUtil.getDeserializedSession(sessionData, sessionService, manager);
+ assertEquals("Session authentication type not valid", AUTH_TYPE, session.getAuthType());
+ assertEquals("prinicpal name is not valid", ADMIN, session.getPrincipal().getName());
+ SavedRequest savedRequest = (SavedRequest)session.getNote(Constants.FORM_REQUEST_NOTE);
+ assertEquals("saved request uri does not match", REQUEST_URI, savedRequest.getRequestURI());
+ assertEquals("saved request header does not match", HEADER_VALUE, savedRequest.getHeaderValues(HEADER_NAME).next());
+ assertEquals("saved request header does not match", Locale.ENGLISH, savedRequest.getLocales().next());
+ String username = (String)session.getNote(Constants.FORM_USERNAME);
+ assertEquals("username does not match", ADMIN, username);
+ String password = (String)session.getNote(Constants.FORM_PASSWORD);
+ assertEquals("password does not match", ADMIN, password);
+ assertEquals("session manager does not match", manager, session.getManager());
+ assertEquals("session creation time does not match", creationTime, session.getCreationTime());
+ assertEquals("session man inactive interval does not match", interval, session.getMaxInactiveInterval());
+ assertEquals("is session new does not match", true, session.isNew());
+ assertEquals("is session valid does not match", true, session.isValid());
+ }
+
+ @Test
+ public void testSerializationtoFile(){
+ ClusterSession customSession = createClusterSesion();
+ ClusterSessionData sessionData = ClusterSessionUtil.getSerializableSession(customSession);
+ try(
+ OutputStream file = new FileOutputStream("sessionData.ser");
+ OutputStream buffer = new BufferedOutputStream(file);
+ ObjectOutput output = new ObjectOutputStream(buffer);
+ ){
+ output.writeObject(sessionData);
+ }
+ catch(IOException ex){
+ fail("IO exception while serializing object to a file.");
+ }
+ try(
+ InputStream file = new FileInputStream("sessionData.ser");
+ InputStream buffer = new BufferedInputStream(file);
+ ObjectInput input = new ObjectInputStream (buffer);
+ ){
+ //deserialize the session
+ ClusterSessionData recovedSession = (ClusterSessionData)input.readObject();
+ //display its data
+ ClusterSession session = ClusterSessionUtil.getDeserializedSession(recovedSession, sessionService, manager);
+ assertEquals("Session authentication type not valid", AUTH_TYPE, session.getAuthType());
+ assertEquals("prinicpal name is not valid", ADMIN, session.getPrincipal().getName());
+ SavedRequest savedRequest = (SavedRequest)session.getNote(Constants.FORM_REQUEST_NOTE);
+ assertEquals("saved request uri is not valid", REQUEST_URI, savedRequest.getRequestURI());
+ assertEquals("saved request header does not match", HEADER_VALUE, savedRequest.getHeaderValues(HEADER_NAME).next());
+ assertEquals("saved request header does not match", Locale.ENGLISH, savedRequest.getLocales().next());
+ String username = (String)session.getNote(Constants.FORM_USERNAME);
+ assertEquals("username does not match", ADMIN, username);
+ String password = (String)session.getNote(Constants.FORM_PASSWORD);
+ assertEquals("password does not match", ADMIN, password);
+ }
+ catch(ClassNotFoundException ex){
+ fail("Exception in object deserialization from file");
+ }
+ catch(IOException ex){
+ fail("Exception in object deserialization from file");
+ }
+ File serializedFile = new File("sessionData.ser");
+ serializedFile.delete();
+ }
+
+ private ClusterSession createClusterSesion(){
+ ClusterSession clusterSession = new ClusterSession(manager, sessionService);
+ clusterSession.setAuthType(AUTH_TYPE);
+ clusterSession.setCreationTime(creationTime);
+ clusterSession.setMaxInactiveInterval(interval);
+ clusterSession.setNew(true);
+ clusterSession.setValid(true);
+ List<String> roles = new ArrayList<String>();
+ roles.add(ADMIN);
+ GenericPrincipal principal = new GenericPrincipal(ADMIN, ADMIN, roles);
+ clusterSession.setPrincipal(principal);
+ clusterSession.setNote(Constants.FORM_PRINCIPAL_NOTE, principal);
+ SavedRequest savedRequest = new SavedRequest();
+ savedRequest.setRequestURI(REQUEST_URI);
+ savedRequest.addHeader(HEADER_NAME, HEADER_VALUE);
+ savedRequest.addLocale(Locale.ENGLISH);
+ clusterSession.setNote(Constants.FORM_REQUEST_NOTE, savedRequest);
+ clusterSession.setNote(Constants.FORM_USERNAME, ADMIN);
+ clusterSession.setNote(Constants.FORM_PASSWORD, ADMIN);
+ return clusterSession;
+ }
+}
lock.readLock().lock();
if (topoManager == null || dataPacketService == null
|| swMgr == null) {
+ lock.readLock().unlock();
return false;
}
log.error("Mode set to "
+ BroadcastMode.EXTERNAL_QUERY
+ ", but no external source of broadcast ports was provided.");
+ lock.readLock().unlock();
return false;
}
break;
return;
}
HostNodeConnector destHost = hostTracker.hostFind(dIP);
+ /*
+ * In cases when incoming and outgoing connectors are in the same node, there is no need
+ * to verify that there is a route. Because of that, we will only need routing.getRoute()
+ * if we know that src and dst nodes are different.
+ */
if (destHost != null
- && (routing == null ||
+ && (incomingNodeConnector.getNode().equals(destHost.getnodeconnectorNode()) ||
+ routing == null ||
routing.getRoute(incomingNodeConnector.getNode(), destHost.getnodeconnectorNode()) != null)) {
log.trace("Host {} is at {}", dIP, destHost.getnodeConnector());
- HostNodePair key = new HostNodePair(destHost, incomingNodeConnector.getNode());
// If SimpleForwarding is aware of this host, it will try to install
// a path. Forward packet until it's done.
- if (dataPacketService != null && this.rulesDB.containsKey(key)) {
-
+ if (dataPacketService != null) {
/*
* if we know where the host is and there's a path from where this
<parent>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>org.openexi</artifactId>
- <version>0000.0002.0035.0-SNAPSHOT</version>
+ <version>0000.0002.0038.0-SNAPSHOT</version>
</parent>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<packaging>bundle</packaging>
<properties>
- <archive>nagasena-rta-0000.0002.0035.0.jar</archive>
+ <archive>nagasena-rta-0000.0002.0038.0.jar</archive>
</properties>
<build>
<parent>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>org.openexi</artifactId>
- <version>0000.0002.0035.0-SNAPSHOT</version>
+ <version>0000.0002.0038.0-SNAPSHOT</version>
</parent>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<packaging>bundle</packaging>
<properties>
- <archive>nagasena-0000.0002.0035.0.jar</archive>
+ <archive>nagasena-0000.0002.0038.0.jar</archive>
</properties>
<build>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>org.openexi</artifactId>
- <version>0000.0002.0035.0-SNAPSHOT</version>
+ <version>0000.0002.0038.0-SNAPSHOT</version>
<packaging>pom</packaging>
<prerequisites>
<maven>3.0.4</maven>