<feature name="base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
<bundle start="true" start-level="35">mvn:eclipselink/javax.persistence/2.0.4.v201112161009</bundle>
<bundle start="true" start-level="35">mvn:eclipselink/javax.resource/1.5.0.v200906010428</bundle>
+ <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/2.5.0</bundle>
+ <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.core/2.5.0</bundle>
</feature>
<feature name="base-gemini-web" description="Gemini Web" version="${geminiweb.version}">
<feature>http</feature>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-subsystem</artifactId>
<version>0.2.5-SNAPSHOT</version>
+ <relativePath>../../opendaylight/config/</relativePath>
</parent>
<artifactId>config-features</artifactId>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<features name="odl-config-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+ <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/netconf-features/${netconf.version}/xml/features</repository>
+
+ <feature name='odl-config-startup' version='${project.version}'>
+ <feature version='${project.version}'>odl-config-netconf-connector</feature>
+ <feature version='${project.version}'>odl-config-persister</feature>
+ <feature version='${project.version}'>odl-netconf-impl</feature>
+ </feature>
+
+ <feature name='odl-config-core' version='${project.version}'>
+ <feature version='${yangtools.version}'>yangtools-concepts</feature>
+ <feature version='${yangtools.version}'>yangtools-binding</feature>
+ <feature version='${yangtools.version}'>yangtools-binding-generator</feature>
+ <feature version='${mdsal.version}'>odl-mdsal-commons</feature>
+ <feature version='${project.version}'>odl-config-api</feature>
+ <bundle>mvn:org.opendaylight.controller/config-util/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/yang-jmx-generator/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/shutdown-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/shutdown-impl/${project.version}</bundle>
+ <bundle>mvn:org.osgi/org.osgi.core/${osgi.core.version}</bundle>
+ <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
+ <bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
+ </feature>
+ <feature name='odl-config-manager' version='${project.version}'>
+ <feature version='${project.version}'>odl-config-core</feature>
+ <bundle>mvn:org.opendaylight.controller/config-manager/${project.version}</bundle>
+ </feature>
+ <feature name='odl-config-persister' version='${project.version}'>
+ <feature version='${netconf.version}'>odl-netconf-api</feature>
+ <feature version='${project.version}'>odl-config-api</feature>
+ <feature version='${yangtools.version}'>yangtools-binding-generator</feature>
+ <bundle>mvn:org.opendaylight.controller/config-persister-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/config-persister-file-xml-adapter/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/config-persister-directory-xml-adapter/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/config-persister-impl/${project.version}</bundle>
+
+ <bundle>mvn:org.opendaylight.controller/netconf-util/${netconf.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/netconf-mapping-api/${netconf.version}</bundle>
+
+ <bundle>mvn:com.google.guava/guava/${guava.version}</bundle>
+ <bundle>mvn:commons-io/commons-io/${commons.io.version}</bundle>
+ <bundle>mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
+ <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.core/${eclipse.persistence.version}</bundle>
+ <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/${eclipse.persistence.version}</bundle>
+ </feature>
+ <feature name='odl-config-api' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller/config-api/${project.version}</bundle>
+
+ <!-- yangtools features -->
+ <feature version='${yangtools.version}'>yangtools-concepts</feature>
+ <feature version='${yangtools.version}'>yangtools-binding</feature>
+ </feature>
+
+ <feature name='odl-config-netty-config-api' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller/netty-config-api/${project.version}</bundle>
+
+ <!-- netty bundles -->
+ <bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
+ <bundle>mvn:io.netty/netty-common/${netty.version}</bundle>
+ <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
+
+ <feature version='${project.version}'>odl-config-api</feature>
+ </feature>
+ <feature name='odl-config-netty' version='${project.version}'>
+ <feature version='${project.version}'>odl-config-netty-config-api</feature>
+ <bundle>mvn:org.opendaylight.controller/netty-event-executor-config/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/netty-threadgroup-config/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/netty-timer-config/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/threadpool-config-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/threadpool-config-impl/${project.version}</bundle>
+ <feature version='${project.version}'>odl-config-startup</feature>
+ </feature>
+ <feature name='odl-config-dispatcher' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller/netconf-config-dispatcher/${project.version}</bundle>
+ </feature>
+
+</features>
\ No newline at end of file
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-parent</artifactId>
<version>1.1-SNAPSHOT</version>
+ <relativePath>../../opendaylight/md-sal</relativePath>
</parent>
<artifactId>mdsal-features</artifactId>
<feature version='${project.version}'>odl-mdsal-restconf</feature>
</feature>
<feature name='odl-mdsal-commons' version='${project.version}'>
- <feature version='${yangtools.version}'>yangtools-concepts</feature>
- <feature version='${yangtools.version}'>yangtools-binding</feature>
+ <feature version='${yangtools.version}'>yangtools-data-binding</feature>
<bundle>mvn:org.opendaylight.controller/sal-common/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-common-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-common-impl/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-common-util/${project.version}</bundle>
- <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
- <bundle>wrap:mvn:org.eclipse.xtend/org.eclipse.xtend.lib/${xtend.version}</bundle>
</feature>
<feature name='odl-mdsal-broker' version='${project.version}'>
<feature version='${yangtools.version}'>yangtools-concepts</feature>
<feature version='${yangtools.version}'>yangtools-binding</feature>
<feature version='${mdsal.version}'>odl-mdsal-commons</feature>
- <feature version='${config.version}'>odl-config-subsystem</feature>
+ <feature version='${config.version}'>odl-config-core</feature>
+ <feature version='${config.version}'>odl-config-manager</feature>
+ <feature version='${config.version}'>odl-config-api</feature>
+ <feature version='${config.version}'>odl-config-persister</feature>
<bundle>mvn:org.opendaylight.controller/sal-core-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-core-spi/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-broker-impl/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-binding-broker-impl/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-binding-util/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/sal-connector-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/sal-inmemory-datastore/${project.version}</bundle>
</feature>
<feature name='odl-mdsal-restconf' version='${project.version}'>
<feature version='${mdsal.version}'>odl-mdsal-broker</feature>
<bundle>wrap:mvn:io.netty/netty-handler/${netty.version}</bundle>
<bundle>wrap:mvn:io.netty/netty-transport/${netty.version}</bundle>
</feature>
+ <feature name='odl-mdsal-model' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller.model/model-flow-base/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.model/model-flow-management/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.model/model-flow-service/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.model/model-flow-statistics/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.model/model-inventory/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.model/model-topology/${project.version}</bundle>
+ </feature>
+ <feature name='odl-mdsal-toaster' version='${project.version}'>
+ <feature version='${yangtools.version}'>yangtools-concepts</feature>
+ <feature version='${yangtools.version}'>yangtools-binding</feature>
+ <feature version='${project.version}'>odl-mdsal-broker</feature>
+ <feature version='${project.version}'>odl-mdsal-all</feature>
+ <bundle>mvn:org.opendaylight.controller.samples/sample-toaster/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.samples/sample-toaster-consumer/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.samples/sample-toaster-provider/${project.version}</bundle>
+ </feature>
+ <feature name='odl-mdsal-misc' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller/sal-netconf-connector/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/sal-restconf-broker/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/sal-remote/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.md/topology-manager/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.md/topology-lldp-discovery/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.md/statistics-manager/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.md/inventory-manager/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.md/forwardingrules-manager/${project.version}</bundle>
+ </feature>
+
</features>
--- /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>netconf-subsystem</artifactId>
+ <version>0.2.5-SNAPSHOT</version>
+ <relativePath>../../opendaylight/netconf</relativePath>
+ </parent>
+ <artifactId>netconf-features</artifactId>
+
+ <packaging>pom</packaging>
+
+ <properties>
+ <features.file>features.xml</features.file>
+ </properties>
+
+ <dependencies></dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>filter</id>
+ <goals>
+ <goal>resources</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/${features.file}</file>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<features name="odl-netconf-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+ <repository>mvn:org.opendaylight.controller/features-odl-protocol-framework/${protocol-framework.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/config-features/${config.version}/xml/features</repository>
+
+ <feature name='odl-netconf-api' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller/netconf-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring-extension/${project.version}</bundle>
+ <feature version='${protocol-framework.version}'>odl-protocol-framework</feature>
+ <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf-inet-types.version}</bundle>
+ <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf-yang-types.version}</bundle>
+ </feature>
+ <feature name='odl-netconf-mapping-api' version='${project.version}'>
+ <feature version='${project.version}'>odl-netconf-api</feature>
+ <bundle>mvn:org.opendaylight.controller/netconf-mapping-api/${project.version}</bundle>
+ </feature>
+ <feature name='odl-netconf-util' version='${project.version}'>
+ <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+ <bundle>mvn:org.opendaylight.controller/netconf-util/${project.version}</bundle>
+ </feature>
+ <feature name='odl-config-netconf-connector' version='${project.version}'>
+ <feature version='${config.version}'>odl-config-manager</feature>
+ <bundle>mvn:org.opendaylight.controller/config-netconf-connector/${project.version}</bundle>
+ <feature version='${project.version}'>odl-netconf-api</feature>
+ <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+ <feature version='${project.version}'>odl-netconf-util</feature>
+ </feature>
+
+ <feature name='odl-netconf-impl' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller/netconf-impl/${project.version}</bundle>
+ <feature version='${project.version}'>odl-netconf-api</feature>
+ <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+ <feature version='${project.version}'>odl-netconf-util</feature>
+ <feature version='${project.version}'>odl-netconf-netty-util</feature>
+ </feature>
+ <feature name='odl-netconf-netty-util' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller/netconf-netty-util/${project.version}</bundle>
+ <feature version='${project.version}'>odl-netconf-api</feature>
+ <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+ <feature version='${project.version}'>odl-netconf-util</feature>
+ <bundle>mvn:org.opendaylight.controller.thirdparty/ganymed/${ganymed.version}</bundle>
+ <bundle>mvn:org.openexi/nagasena/${exi.nagasena.version}</bundle>
+ <bundle>mvn:io.netty/netty-codec/${netty.version}</bundle>
+ <bundle>mvn:io.netty/netty-handler/${netty.version}</bundle>
+ <bundle>mvn:io.netty/netty-common/${netty.version}</bundle>
+ <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
+ <bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
+ </feature>
+ <feature name='odl-netconf-misc' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller/netconf-client/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/netconf-monitoring/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/netconf-tcp/${project.version}</bundle>
+ </feature>
+
+</features>
\ No newline at end of file
--- /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>../opendaylight/commons/opendaylight</relativePath>
+ </parent>
+ <artifactId>features-controller</artifactId>
+ <packaging>pom</packaging>
+ <prerequisites>
+ <maven>3.0</maven>
+ </prerequisites>
+ <modules>
+ <module>config</module>
+ <module>mdsal</module>
+ <module>netconf</module>
+ <module>protocol-framework</module>
+ </modules>
+</project>
--- /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>../../opendaylight/commons/opendaylight</relativePath>
+ </parent>
+ <artifactId>features-odl-protocol-framework</artifactId>
+ <version>${protocol-framework.version}</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <features.file>features.xml</features.file>
+ </properties>
+
+ <dependencies></dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>filter</id>
+ <goals>
+ <goal>resources</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/${features.file}</file>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<features name="odl-protocol-framework-${protocol-framework.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+ <repository>mvn:org.opendaylight.controller/config-features/${config.version}/xml/features</repository>
+ <feature name='odl-protocol-framework' version='${project.version}'>
+ <bundle>mvn:org.opendaylight.controller/protocol-framework/${protocol-framework.version}</bundle>
+ <feature version='${config.version}'>odl-config-api</feature> <!-- needed by netty-config-api -->
+ <feature version='${config.version}'>odl-config-netty-config-api</feature> <!-- needed by netty-config-api -->
+ </feature>
+</features>
\ No newline at end of file
<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>
+ <ganymed.version>1.1-SNAPSHOT</ganymed.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>
<dependency>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>ganymed</artifactId>
- <version>1.1-SNAPSHOT</version>
+ <version>${ganymed.version}</version>
</dependency>
<!-- Third parties from opendaylight released -->
<dependency>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<features name="config-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
- <feature name='config-all' version='${project.version}'>
- <feature version='${project.version}'>odl-config-subsystem</feature>
- </feature>
-
- <feature name='odl-config-subsystem' version='${project.version}'>
- <feature version='${yangtools.version}'>yangtools-concepts</feature>
- <feature version='${yangtools.version}'>yangtools-binding</feature>
- <feature version='${yangtools.version}'>yangtools-binding-generator</feature>
- <feature version='${mdsal.version}'>odl-mdsal-commons</feature>
- <bundle>mvn:org.opendaylight.controller/config-api/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.controller/config-util/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.controller/config-manager/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.controller/yang-jmx-generator/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.controller/config-persister-api/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.controller/config-persister-file-xml-adapter/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.controller/config-persister-directory-xml-adapter/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.controller/shutdown-api/${project.version}</bundle>
- <bundle>mvn:org.opendaylight.controller/shutdown-impl/${project.version}</bundle>
- <bundle>mvn:org.osgi/org.osgi.core/${osgi.core.version}</bundle>
- <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
- <bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
- </feature>
-</features>
\ No newline at end of file
<module>shutdown-impl</module>
<module>netconf-config-dispatcher</module>
<module>config-module-archetype</module>
- <module>feature</module>
</modules>
<dependencies>
<type>kar</type>
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-odl-protocol-framework</artifactId>
+ <version>${protocol-framework.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-features</artifactId>
+ <version>${netconf.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-features</artifactId>
<type>xml</type>
<scope>runtime</scope>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>features-yangtools</artifactId>
- <version>${yangtools.version}</version>
- <classifier>features</classifier>
- <type>xml</type>
- <scope>runtime</scope>
- </dependency>
</dependencies>
<build>
+++ /dev/null
-<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:remote:rpc">prefix:remote-zeromq-rpc-server</type>
- <name>remoter</name>
- <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">5666</port>
- <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
- <name>dom-broker</name>
- </dom-broker>
- </module>
- </modules>
- <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- </services>
- </data>
- </configuration>
-
- <required-capabilities>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc?module=odl-sal-dom-rpc-remote-cfg&revision=2013-10-28</capability>
- </required-capabilities>
-</snapshot>
-
*/
package org.opendaylight.controller.md.frm.compatibility;
-import java.util.Collections;
-
import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
import org.opendaylight.controller.sal.common.util.Arguments;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
this.manager.removeStaticFlow(flow.getName(), flow.getNode());
this.manager.addStaticFlow(flow);
}
- return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+ return RpcResultBuilder.<Void> success().build();
}
public RpcResult<Void> rollback(final FlowCommitTransaction transaction) {
import java.math.BigInteger;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.compatibility.InventoryMapping;
import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
AddFlowOutputBuilder builder = new AddFlowOutputBuilder();
builder.setTransactionId(new TransactionId(BigInteger.valueOf(status.getRequestId())));
AddFlowOutput rpcResultType = builder.build();
- return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
+ return Futures.immediateFuture(RpcResultBuilder.<AddFlowOutput>status(status.isSuccess())
+ .withResult(rpcResultType).build());
}
@Override
RemoveFlowOutputBuilder builder = new RemoveFlowOutputBuilder();
builder.setTransactionId(new TransactionId(BigInteger.valueOf(status.getRequestId())));
RemoveFlowOutput rpcResultType = builder.build();
- return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
+ return Futures.immediateFuture(RpcResultBuilder.<RemoveFlowOutput>status(status.isSuccess())
+ .withResult(rpcResultType).build());
}
import java.util.concurrent.Future;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.compatibility.FromSalConversionsUtils;
import org.opendaylight.controller.sal.compatibility.InventoryMapping;
import org.opendaylight.controller.sal.compatibility.NodeMapping;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMapBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
LOG.error(e.getMessage());
}
- return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null));
+ return Futures.immediateFuture(RpcResultBuilder.<GetAllFlowStatisticsFromFlowTableOutput>
+ status(rpcResultBool).withResult(rpcResultType).build());
}
/**
LOG.error(e.getMessage());
}
- return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null));
+ return Futures.immediateFuture(RpcResultBuilder.<GetAllFlowsStatisticsFromAllFlowTablesOutput>
+ status(rpcResultBool).withResult(rpcResultType).build());
}
@Override
LOG.error(e.getMessage());
}
- return Futures.immediateFuture(Rpcs.getRpcResult(rpcResultBool, rpcResultType, null));
+ return Futures.immediateFuture(RpcResultBuilder.<GetFlowStatisticsFromFlowTableOutput>
+ status(rpcResultBool).withResult(rpcResultType).build());
}
@Override
revision "2013-08-19" {
description "Initial revision of Inventory model";
}
-
-
+
+
typedef support-type {
type enumeration {
enum native;
typedef node-id {
type inet:uri;
+ description "Identifier for a particular node. For example:
+
+ myprotocol:<unique_node_id>
+
+ myprotocol:12
+
+ It is a good practice to always lead with a scoping identifier.
+ In the example above the scoping was 'myprotocol'. In your app you
+ could use 'myapp' etc.";
}
typedef node-connector-id {
type inet:uri;
+ description "Identifier for a particular node-connector. For example:
+
+ myprotocol:<unique_node_connector_id>
+ myprotocol:3
+
+ It is a good practice to always lead with a scoping identifier.
+ In the example above the scoping was 'myprotocol'. In your app you
+ could use 'myapp' etc.";
+
}
+ //YANG does not have a statement which limits the scope of an instance-identifier to a particular subtree,
+ //which is why we are using a type capture and not an instance-identifier to define a node-ref and a node-connector-ref.
typedef node-ref {
type instance-identifier;
+ description "A reference that points to an opendaylight-light:nodes/node in the data tree.";
}
typedef node-connector-ref {
type instance-identifier;
+ description "A reference that points to an opendaylight-list:nodes/node/{node-id}/node-connector in the data tree.";
}
identity node-context {
- description "Identity used to mark node context";
+ description "A node-context is a classifier for node elements which allows an RPC to provide a service on behalf of a particular element in the data tree.";
}
identity node-connector-context {
- description "Identity used to mark node connector context";
+ description "A node-connector-context is a classifier for node-connector elements which allows an RPC to provide a service on behalf of a particular element in the data tree.";
}
+ //We are defining a base identity here because there are limitations with yang enums. Yang doesn't allow you to extend enumeratations.
+ //Therefore by defining a base identity we allow other yang files to extend this identity to define additional "enumerations". By
+ //using node-type as their base they are able to pass their object to fields that accept "node-types" while uniquely describing their
+ //type of node, such as "router-node" or "switch-node" etc.
+ //See https://wiki.opendaylight.org/view/YANG_Tools:YANG_to_Java_Mapping#Identity for more information.
identity node-type {
- description "Base identity for node types";
+ description "A base identity definition which represents a generic node type and can be extended in other yang files.";
}
identity node-connector-type {
- description "Base identity for node connectors type";
+ description "A base identity definition which represents a generic node connector type and can be extended in other yang files.";
}
grouping node {
+
+ description "Describes the contents of a generic node -
+ essentially an ID and a list of node-connectors.
+ Acts as an augmentation point where other yang files
+ can add additional information.";
+
leaf id {
type node-id;
+ description "The unique identifier for the node.";
}
list "node-connector" {
key "id";
+
+ description "A list of node connectors that belong this node.";
ext:context-instance "node-connector-context";
uses node-connector;
}
grouping node-connector {
+
+ description "Describes a generic node connector which consists of an ID.
+ Acts as an augmentation point where other yang files can
+ add additional information.";
+
leaf id {
type node-connector-id;
+ description "The unique identifier for the node-connector.";
}
}
grouping node-context-ref {
- description
- "Helper grouping which contains a reference to node context.";
+ description
+ "A helper grouping which contains a reference to a node classified with a node-context. This allows RPCs in other yang files to refine their input to a particular node instance.";
+
leaf node {
ext:context-reference "node-context";
type node-ref;
+ description "A reference to a particular node.";
}
}
/** Base structure **/
container nodes {
+
+ description "The root container of all nodes.";
+
list node {
key "id";
ext:context-instance "node-context";
-
- uses node;
+ description "A list of nodes (as defined by the 'grouping node').";
+ uses node; //this refers to the 'grouping node' defined above.
}
}
+ //The following notifications should really be replaced by direct writes to the data tree with data change listeners listening to those changes.
+ //Notifications should be reserved for one time events which do not require persistence to the data tree.
notification node-updated {
+
+ status deprecated;
+
+ description "A notification sent by someone who realized there was a modification to a node, but did not modify the data tree.
+ Describes that something on the node has been updated (including addition of a new node), but is for
+ whatever reason is not modifying the data tree.
+
+ Deprecated: If a process determines that a node was updated, then that
+ logic should update the node using the DataBroker directly. Listeners interested
+ update changes should register a data change listener for notifications on removals.";
+
leaf node-ref {
ext:context-reference "node-context";
+ description "A reference to the node which changed.";
+
type node-ref;
}
uses node;
}
notification node-connector-updated {
+
+ status deprecated;
+
+ description "A notification sent by someone who realized there was a modification to a node-connector, but did not modify the data tree.
+ Describes that something on the node-connector has been updated (including addition of a new node-connector), but is for
+ whatever reason is not modifying the data tree.
+
+ Deprecated: If a process determines that a node-connector was updated, then that
+ logic should update the node-connector using the DataBroker directly. Listeners interested
+ update changes should register a data change listener for notifications on removals.";
+
leaf node-connector-ref {
ext:context-reference "node-connector-context";
type node-connector-ref;
+ description "A reference to the node-connector which changed.";
}
uses node-connector;
}
notification node-removed {
+
+ status deprecated;
+
+ description "A notification sent by someone who realized there was a node was removed, but did not modify the data tree.
+ Describes that a node has been removed but is for
+ whatever reason is not modifying the data tree.
+
+ Deprecated: If a process determines that a node was removed, then that
+ logic should remove the node from the DataBroker directly. Listeners interested
+ in changes should register a data change listener for notifications on removals.";
+
leaf node-ref {
+ description "A reference to the node that was removed.";
ext:context-reference "node-context";
type node-ref;
}
}
notification node-connector-removed {
+
+ status deprecated;
+
+ description "A notification sent by someone who realized there was a node-connector was removed, but did not modify the data tree.
+ Describes that a node-connector has been removed but is for
+ whatever reason is not modifying the data tree.
+
+ Deprecated: If a process determines that a node-connector was removed, then that
+ logic should remove the node-connector from the DataBroker directly. Listeners interested
+ in changes should register a data change listener for notifications on removals.";
+
leaf node-connector-ref {
+ description "A reference to the node-connector that was removed.";
ext:context-reference "node-connector-context";
type node-connector-ref;
}
<!--sal-protocolbuffer-encoding-->
<module>sal-protocolbuffer-encoding</module>
- <!-- Karaf feature -->
- <module>feature</module>
-
<!-- Yang Test Models for MD-SAL -->
<module>sal-test-model</module>
</modules>
import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
if(requestCommitSuccess) {
return tx.getDelegate().commit();
}
- return Futures.immediateFuture(Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.<RpcError>emptySet()));
+ return Futures.immediateFuture(RpcResultBuilder.<TransactionStatus>failed().withResult(TransactionStatus.FAILED).build());
}
});
private static final Logger LOG = LoggerFactory.getLogger(RpcRouterCodegenInstance.class);
- private T defaultService;
-
private final Class<T> serviceType;
private final T invocationProxy;
private final Map<Class<? extends BaseIdentity>, RpcRoutingTableImpl<? extends BaseIdentity, T>> routingTables;
- private final String name;
-
@SuppressWarnings("unchecked")
public RpcRouterCodegenInstance(final String name,final Class<T> type, final T routerImpl, final Iterable<Class<? extends BaseIdentity>> contexts) {
- this.name = name;
this.listeners = ListenerRegistry.create();
this.serviceType = type;
this.invocationProxy = routerImpl;
@Override
public T getDefaultService() {
- return defaultService;
+ return RuntimeCodeHelper.getDelegate(invocationProxy);
}
@Override
return new RoutedRpcRegistrationImpl(service);
}
+ public void removeDefaultImplementation(final T instance) {
+ RpcService current = RuntimeCodeHelper.getDelegate(invocationProxy);
+ if(instance == current) {
+ RuntimeCodeHelper.setDelegate(invocationProxy, null);
+ }
+ }
+
@Override
public RpcRegistration<T> registerDefaultService(final T service) {
- // TODO Auto-generated method stub
RuntimeCodeHelper.setDelegate(invocationProxy, service);
- return null;
+ return new DefaultRpcImplementationRegistration(service);
}
private class RoutedRpcRegistrationImpl extends AbstractObjectRegistration<T> implements RoutedRpcRegistration<T> {
}
}
+
+ private class DefaultRpcImplementationRegistration extends AbstractObjectRegistration<T> implements RpcRegistration<T> {
+
+
+ protected DefaultRpcImplementationRegistration(final T instance) {
+ super(instance);
+ }
+
+ @Override
+ protected void removeRegistration() {
+ removeDefaultImplementation(this.getInstance());
+ }
+
+ @Override
+ public Class<T> getServiceType() {
+ return serviceType;
+ }
+ }
+
+
}
*/
package org.opendaylight.controller.sal.binding.impl;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.WeakHashMap;
+
import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.EventListener;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-import static com.google.common.base.Preconditions.checkState;
-
public class RpcProviderRegistryImpl implements //
RpcProviderRegistry, //
RouteChangePublisher<RpcContextIdentifier, InstanceIdentifier<?>> {
return name;
}
- public RpcProviderRegistryImpl(String name) {
+ public RpcProviderRegistryImpl(final String name) {
super();
this.name = name;
}
@Override
- public final <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type,
- T implementation) throws IllegalStateException {
+ public final <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(final Class<T> type,
+ final T implementation) throws IllegalStateException {
return getRpcRouter(type).addRoutedRpcImplementation(implementation);
}
@Override
- public final <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> type, T implementation)
+ public final <T extends RpcService> RpcRegistration<T> addRpcImplementation(final Class<T> type, final T implementation)
throws IllegalStateException {
@SuppressWarnings("unchecked")
RpcRouter<T> potentialRouter = (RpcRouter<T>) rpcRouters.get(type);
@SuppressWarnings("unchecked")
@Override
- public final <T extends RpcService> T getRpcService(Class<T> type) {
+ public final <T extends RpcService> T getRpcService(final Class<T> type) {
T potentialProxy = (T) publicProxies.get(type);
if (potentialProxy != null) {
}
}
- @SuppressWarnings("unchecked")
- public <T extends RpcService> RpcRouter<T> getRpcRouter(Class<T> type) {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public <T extends RpcService> RpcRouter<T> getRpcRouter(final Class<T> type) {
RpcRouter<?> potentialRouter = rpcRouters.get(type);
if (potentialRouter != null) {
return (RpcRouter<T>) potentialRouter;
}
}
- private void notifyGlobalRpcAdded(Class<? extends RpcService> type) {
+ private void notifyGlobalRpcAdded(final Class<? extends RpcService> type) {
for(ListenerRegistration<GlobalRpcRegistrationListener> listener : globalRpcListeners) {
try {
listener.getInstance().onGlobalRpcRegistered(type);
}
- private void notifyListenersRoutedCreated(RpcRouter<?> router) {
+ private void notifyListenersRoutedCreated(final RpcRouter<?> router) {
for (ListenerRegistration<RouterInstantiationListener> listener : routerInstantiationListener) {
try {
}
public ListenerRegistration<RouterInstantiationListener> registerRouterInstantiationListener(
- RouterInstantiationListener listener) {
+ final RouterInstantiationListener listener) {
ListenerRegistration<RouterInstantiationListener> reg = routerInstantiationListener.register(listener);
try {
for (RpcRouter<?> router : rpcRouters.values()) {
return reg;
}
+ @SuppressWarnings("unchecked")
@Override
public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
- L listener) {
+ final L listener) {
return (ListenerRegistration<L>) routeChangeListeners.register(listener);
}
return rpcFactory;
}
- public void setRpcFactory(RuntimeCodeGenerator rpcFactory) {
+ public void setRpcFactory(final RuntimeCodeGenerator rpcFactory) {
this.rpcFactory = rpcFactory;
}
void onRpcRouterCreated(RpcRouter<?> router);
}
- public ListenerRegistration<GlobalRpcRegistrationListener> registerGlobalRpcRegistrationListener(GlobalRpcRegistrationListener listener) {
+ public ListenerRegistration<GlobalRpcRegistrationListener> registerGlobalRpcRegistrationListener(final GlobalRpcRegistrationListener listener) {
return globalRpcListeners.register(listener);
}
private final Class<T> type;
- public RouteChangeForwarder(Class<T> type) {
+ public RouteChangeForwarder(final Class<T> type) {
this.type = type;
}
@Override
- public void onRouteChange(RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
+ public void onRouteChange(final RouteChange<Class<? extends BaseIdentity>, InstanceIdentifier<?>> change) {
Map<RpcContextIdentifier, Set<InstanceIdentifier<?>>> announcements = new HashMap<>();
for (Entry<Class<? extends BaseIdentity>, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements()
.entrySet()) {
private final Class<T> serviceType;
private RpcProviderRegistryImpl registry;
- public RpcProxyRegistration(Class<T> type, T service, RpcProviderRegistryImpl registry) {
+ public RpcProxyRegistration(final Class<T> type, final T service, final RpcProviderRegistryImpl registry) {
super(service);
this.serviceType = type;
this.registry = registry;
*/
package org.opendaylight.controller.sal.binding.impl.connect.dom;
-import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
import java.util.Collection;
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 java.util.WeakHashMap;
-import java.util.concurrent.Callable;
+
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
-import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-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.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService.NotificationInterestListener;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
-import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
import org.opendaylight.controller.sal.binding.impl.MountPointManagerImpl.BindingMountPointImpl;
import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
-import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl.GlobalRpcRegistrationListener;
-import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl.RouterInstantiationListener;
-import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration.CompositeObjectRegistrationBuilder;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.BaseIdentity;
-import org.opendaylight.yangtools.yang.binding.BindingMapping;
-import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.Notification;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
-import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
-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.impl.codec.BindingIndependentMappingService;
import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-
public class BindingIndependentConnector implements //
RuntimeDataProvider, //
Provider, //
AutoCloseable {
- private final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
-
+ private static final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
.builder().toInstance();
- private final static Method EQUALS_METHOD;
-
private BindingIndependentMappingService mappingService;
-
private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
-
private DataProviderService baDataService;
- private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions = new ConcurrentHashMap<>();
- private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions = new ConcurrentHashMap<>();
-
- private final BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler();
- private final DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler();
-
- private Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> baCommitHandlerRegistration;
+ private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions;
+ private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
+ private final BindingToDomCommitHandler bindingToDomCommitHandler;
+ private final DomToBindingCommitHandler domToBindingCommitHandler;
private Registration<DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode>> biCommitHandlerRegistration;
-
private RpcProvisionRegistry biRpcRegistry;
private RpcProviderRegistry baRpcRegistry;
private ListenerRegistration<DomToBindingRpcForwardingManager> domToBindingRpcManager;
- // private ListenerRegistration<BindingToDomRpcForwardingManager>
- // bindingToDomRpcManager;
-
- private final Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
- @Override
- public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(final InstanceIdentifier<?> input) {
- return mappingService.toDataDom(input);
- }
-
- };
-
- private boolean rpcForwarding = false;
-
- private boolean dataForwarding = false;
-
- private boolean notificationForwarding = false;
+ private boolean rpcForwarding;
+ private boolean dataForwarding;
+ private boolean notificationForwarding;
private RpcProviderRegistryImpl baRpcRegistryImpl;
private NotificationPublishService domNotificationService;
- static {
- try {
- EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ public BindingIndependentConnector() {
+ domOpenedTransactions = new ConcurrentHashMap<>();
+ bindingOpenedTransactions = new ConcurrentHashMap<>();
+
+ bindingToDomCommitHandler = new BindingToDomCommitHandler(bindingOpenedTransactions, domOpenedTransactions);
+ domToBindingCommitHandler = new DomToBindingCommitHandler(bindingOpenedTransactions, domOpenedTransactions);
+ rpcForwarding = false;
+ dataForwarding = false;
+ notificationForwarding = false;
}
@Override
}
}
- private DataModificationTransaction createBindingToDomTransaction(
- final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
- DataModificationTransaction target = biDataService.beginTransaction();
- LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(), source.getIdentifier());
- for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
- target.removeConfigurationData(biEntry);
- LOG.debug("Delete of Binding Configuration Data {} is translated to {}", entry, biEntry);
- }
- for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
- target.removeOperationalData(biEntry);
- LOG.debug("Delete of Binding Operational Data {} is translated to {}", entry, biEntry);
- }
- for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
- .entrySet()) {
- Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
- .toDataDom(entry);
- target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
- LOG.debug("Update of Binding Configuration Data {} is translated to {}", entry, biEntry);
- }
- for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
- .entrySet()) {
- Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
- .toDataDom(entry);
- target.putOperationalData(biEntry.getKey(), biEntry.getValue());
- LOG.debug("Update of Binding Operational Data {} is translated to {}", entry, biEntry);
- }
-
- return target;
- }
-
- private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
- final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
- org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
- .beginTransaction();
- for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
- try {
-
- InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
- target.removeConfigurationData(baEntry);
- } catch (DeserializationException e) {
- LOG.error("Ommiting from BA transaction: {}.", entry, e);
- }
- }
- for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
- try {
-
- InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
- target.removeOperationalData(baEntry);
- } catch (DeserializationException e) {
- LOG.error("Ommiting from BA transaction: {}.", entry, e);
- }
- }
- for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
- .getUpdatedConfigurationData().entrySet()) {
- try {
- InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
- DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
- target.putConfigurationData(baKey, baData);
- } catch (DeserializationException e) {
- LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
- }
- }
- for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
- .getUpdatedOperationalData().entrySet()) {
- try {
-
- InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
- DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
- target.putOperationalData(baKey, baData);
- } catch (DeserializationException e) {
- LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
- }
- }
- return target;
- }
-
public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() {
return biDataService;
}
protected void setDomDataService(
final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
this.biDataService = biDataService;
+ bindingToDomCommitHandler.setBindingIndependentDataService(this.biDataService);
}
public DataProviderService getBaDataService() {
protected void setBindingDataService(final DataProviderService baDataService) {
this.baDataService = baDataService;
+ domToBindingCommitHandler.setBindingAwareDataService(this.baDataService);
}
public RpcProviderRegistry getRpcRegistry() {
dataForwarding = true;
}
+ //WTF? - cycle references to biFwdManager - need to solve :-/
public void startRpcForwarding() {
+ checkNotNull(mappingService, "Unable to start Rpc forwarding. Reason: Mapping Service is not initialized properly!");
if (biRpcRegistry != null && baRpcRegistry instanceof RouteChangePublisher<?, ?>) {
checkState(!rpcForwarding, "Connector is already forwarding RPCs");
- final DomToBindingRpcForwardingManager biFwdManager = new DomToBindingRpcForwardingManager();
+ final DomToBindingRpcForwardingManager biFwdManager = new DomToBindingRpcForwardingManager(mappingService, biRpcRegistry, baRpcRegistry);
domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(biFwdManager);
biRpcRegistry.addRpcRegistrationListener(biFwdManager);
baRpcRegistryImpl = (RpcProviderRegistryImpl) baRpcRegistry;
baRpcRegistryImpl.registerRouterInstantiationListener(domToBindingRpcManager.getInstance());
baRpcRegistryImpl.registerGlobalRpcRegistrationListener(domToBindingRpcManager.getInstance());
+ biFwdManager.setRegistryImpl(baRpcRegistryImpl);
}
rpcForwarding = true;
}
public void startNotificationForwarding() {
checkState(!notificationForwarding, "Connector is already forwarding notifications.");
- if (baNotifyService != null && domNotificationService != null) {
- baNotifyService.registerInterestListener(new DomToBindingNotificationForwarder());
-
+ if (mappingService == null) {
+ LOG.warn("Unable to start Notification forwarding. Reason: Mapping Service is not initialized properly!");
+ } else if (baNotifyService == null) {
+ LOG.warn("Unable to start Notification forwarding. Reason: Binding Aware Notify Service is not initialized properly!");
+ } else if (domNotificationService == null) {
+ LOG.warn("Unable to start Notification forwarding. Reason: DOM Notification Service is not initialized properly!");
+ } else {
+ baNotifyService.registerInterestListener(
+ new DomToBindingNotificationForwarder(mappingService, baNotifyService, domNotificationService));
notificationForwarding = true;
}
}
protected void setMappingService(final BindingIndependentMappingService mappingService) {
this.mappingService = mappingService;
+ bindingToDomCommitHandler.setMappingService(this.mappingService);
+ domToBindingCommitHandler.setMappingService(this.mappingService);
}
@Override
}
- public <T extends RpcService> void onRpcRouterCreated(final Class<T> serviceType, final RpcRouter<T> router) {
-
- }
-
public void setDomRpcRegistry(final RpcProvisionRegistry registry) {
biRpcRegistry = registry;
}
@Override
public void close() throws Exception {
- if (baCommitHandlerRegistration != null) {
- baCommitHandlerRegistration.close();
- }
if (biCommitHandlerRegistration != null) {
biCommitHandlerRegistration.close();
}
-
- }
-
- private class DomToBindingTransaction implements
- DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
-
- private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
- private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
-
- public DomToBindingTransaction(
- final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
- final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
- super();
- this.backing = backing;
- this.modification = modification;
- bindingOpenedTransactions.put(backing.getIdentifier(), this);
- }
-
- @Override
- public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
- return modification;
- }
-
- @Override
- public RpcResult<Void> rollback() throws IllegalStateException {
- // backing.cancel();
- return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
- }
-
- @Override
- public RpcResult<Void> finish() throws IllegalStateException {
- Future<RpcResult<TransactionStatus>> result = backing.commit();
- try {
- RpcResult<TransactionStatus> baResult = result.get();
- return Rpcs.<Void> getRpcResult(baResult.isSuccessful(), null, baResult.getErrors());
- } catch (InterruptedException e) {
- throw new IllegalStateException("", e);
- } catch (ExecutionException e) {
- throw new IllegalStateException("", e);
- }
- }
- }
-
- private class BindingToDomTransaction implements
- DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- private final DataModificationTransaction backing;
- private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
-
- public BindingToDomTransaction(final DataModificationTransaction backing,
- final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- this.backing = backing;
- this.modification = modification;
- domOpenedTransactions.put(backing.getIdentifier(), this);
- }
-
- @Override
- public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
- return modification;
- }
-
- @Override
- public RpcResult<Void> finish() throws IllegalStateException {
- Future<RpcResult<TransactionStatus>> result = backing.commit();
- try {
- RpcResult<TransactionStatus> biResult = result.get();
- return Rpcs.<Void> getRpcResult(biResult.isSuccessful(), null, biResult.getErrors());
- } catch (InterruptedException e) {
- throw new IllegalStateException("", e);
- } catch (ExecutionException e) {
- throw new IllegalStateException("", e);
- } finally {
- domOpenedTransactions.remove(backing.getIdentifier());
- }
- }
-
- @Override
- public RpcResult<Void> rollback() throws IllegalStateException {
- domOpenedTransactions.remove(backing.getIdentifier());
- return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
- }
- }
-
- private class BindingToDomCommitHandler implements
- DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- @Override
- public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
- final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
-
- /**
- * Transaction was created as DOM transaction, in that case we do
- * not need to forward it back.
- */
- if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
-
- return CommitHandlerTransactions.allwaysSuccessfulTransaction(bindingTransaction);
- }
- DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
- BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
- LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .",
- bindingTransaction.getIdentifier(), domTransaction.getIdentifier());
- return wrapped;
- }
- }
-
- private class DomToBindingCommitHandler implements //
- RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject>>, //
- DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
-
- @Override
- public void onRegister(
- final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
-
- mappingService.toDataDom(registration
- .getPath());
-
- }
-
- @Override
- public void onUnregister(
- final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
- // NOOP for now
- // FIXME: do registration based on only active commit handlers.
- }
-
- @Override
- public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
- final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
- Object identifier = domTransaction.getIdentifier();
-
- /**
- * We checks if the transcation was originated in this mapper. If it
- * was originated in this mapper we are returing allways success
- * commit hanlder to prevent creating loop in two-phase commit and
- * duplicating data.
- */
- if (domOpenedTransactions.containsKey(identifier)) {
- return CommitHandlerTransactions.allwaysSuccessfulTransaction(domTransaction);
- }
-
- org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
- DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction);
- LOG.trace("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
- baTransaction.getIdentifier());
- return forwardedTransaction;
- }
- }
-
- /**
- * Manager responsible for instantiating forwarders responsible for
- * forwarding of RPC invocations from DOM Broker to Binding Aware Broker
- *
- */
- private class DomToBindingRpcForwardingManager implements
- RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>, RouterInstantiationListener,
- GlobalRpcRegistrationListener, RpcRegistrationListener {
-
- private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
- private RpcProviderRegistryImpl registryImpl;
-
- public RpcProviderRegistryImpl getRegistryImpl() {
- return registryImpl;
- }
-
- public void setRegistryImpl(final RpcProviderRegistryImpl registryImpl) {
- this.registryImpl = registryImpl;
- }
-
- @Override
- public void onGlobalRpcRegistered(final Class<? extends RpcService> cls) {
- getRpcForwarder(cls, null).registerToDOMBroker();
- }
-
- @Override
- public void onGlobalRpcUnregistered(final Class<? extends RpcService> cls) {
- // NOOP
- }
-
- @Override
- public void onRpcRouterCreated(final RpcRouter<?> router) {
- Class<? extends BaseIdentity> ctx = router.getContexts().iterator().next();
- getRpcForwarder(router.getServiceType(), ctx);
- }
-
- @Override
- public void onRouteChange(final RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
- for (Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
- bindingRoutesAdded(entry);
- }
- }
-
- private void bindingRoutesAdded(final Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
- Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
- Class<? extends RpcService> service = entry.getKey().getRpcService();
- if (context != null) {
- getRpcForwarder(service, context).registerPaths(context, service, entry.getValue());
- }
- }
-
- private DomToBindingRpcForwarder getRpcForwarder(final Class<? extends RpcService> service,
- final Class<? extends BaseIdentity> context) {
- DomToBindingRpcForwarder potential = forwarders.get(service);
- if (potential != null) {
- return potential;
- }
- if (context == null) {
- potential = new DomToBindingRpcForwarder(service);
- } else {
- potential = new DomToBindingRpcForwarder(service, context);
- }
-
- forwarders.put(service, potential);
- return potential;
- }
-
- @Override
- public void onRpcImplementationAdded(final QName name) {
-
- final Optional<Class<? extends RpcService>> rpcInterface = mappingService.getRpcServiceClassFor(
- name.getNamespace().toString(), name.getFormattedRevision());
- if (rpcInterface.isPresent()) {
- getRpcForwarder(rpcInterface.get(), null).registerToBindingBroker();
- }
- }
-
- @Override
- public void onRpcImplementationRemoved(final QName name) {
-
- }
- }
-
- private class DomToBindingRpcForwarder implements RpcImplementation, InvocationHandler {
-
- private final Set<QName> supportedRpcs;
- private final WeakReference<Class<? extends RpcService>> rpcServiceType;
- private Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
- private final Map<QName, RpcInvocationStrategy> strategiesByQName = new HashMap<>();
- private final WeakHashMap<Method, RpcInvocationStrategy> strategiesByMethod = new WeakHashMap<>();
- private final RpcService proxy;
- private ObjectRegistration<?> forwarderRegistration;
- private boolean registrationInProgress = false;
-
- public DomToBindingRpcForwarder(final Class<? extends RpcService> service) {
- this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
- this.supportedRpcs = mappingService.getRpcQNamesFor(service);
-
- Class<?> cls = rpcServiceType.get();
- ClassLoader clsLoader = cls.getClassLoader();
- proxy =(RpcService) Proxy.newProxyInstance(clsLoader, new Class<?>[] { cls }, this);
- createStrategies();
- }
-
- /**
- * Constructor for Routed RPC Forwareder.
- *
- * @param service
- * @param context
- */
- public DomToBindingRpcForwarder(final Class<? extends RpcService> service,
- final Class<? extends BaseIdentity> context) {
- this(service);
- Builder<RoutedRpcRegistration> registrationsBuilder = ImmutableSet
- .<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> builder();
- try {
- for (QName rpc : supportedRpcs) {
- registrationsBuilder.add(biRpcRegistry.addRoutedRpcImplementation(rpc, this));
- }
- createDefaultDomForwarder();
- } catch (Exception e) {
- LOG.error("Could not forward Rpcs of type {}", service.getName(), e);
- }
- registrations = registrationsBuilder.build();
- }
-
-
-
- private void createStrategies() {
- try {
- for (QName rpc : supportedRpcs) {
- RpcInvocationStrategy strategy = createInvocationStrategy(rpc, rpcServiceType.get());
- strategiesByMethod.put(strategy.targetMethod, strategy);
- strategiesByQName.put(rpc, strategy);
- }
- } catch (Exception e) {
- LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
- }
-
- }
-
- /**
- * Registers RPC Forwarder to DOM Broker,
- * this means Binding Aware Broker has implementation of RPC
- * which is registered to it.
- *
- * If RPC Forwarder was previously registered to DOM Broker
- * or to Bidning Broker this method is noop to prevent
- * creating forwarding loop.
- *
- */
- public void registerToDOMBroker() {
- if(!registrationInProgress && forwarderRegistration == null) {
- registrationInProgress = true;
- CompositeObjectRegistrationBuilder<DomToBindingRpcForwarder> builder = CompositeObjectRegistration.builderFor(this);
- try {
- for (QName rpc : supportedRpcs) {
- builder.add(biRpcRegistry.addRpcImplementation(rpc, this));
- }
- } catch (Exception e) {
- LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
- }
- this.forwarderRegistration = builder.toInstance();
- registrationInProgress = false;
- }
- }
-
-
- public void registerPaths(final Class<? extends BaseIdentity> context,
- final Class<? extends RpcService> service, final Set<InstanceIdentifier<?>> set) {
- QName ctx = BindingReflections.findQName(context);
- for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
- toDOMInstanceIdentifier)) {
- for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
- reg.registerPath(ctx, path);
- }
- }
- }
-
- @Override
- public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
- if (EQUALS_METHOD.equals(method)) {
- return false;
- }
- RpcInvocationStrategy strategy = strategiesByMethod.get(method);
- checkState(strategy != null);
- checkArgument(args.length <= 2);
- if (args.length == 1) {
- checkArgument(args[0] instanceof DataObject);
- return strategy.forwardToDomBroker((DataObject) args[0]);
- }
- return strategy.forwardToDomBroker(null);
- }
-
- public void removePaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
- final Set<InstanceIdentifier<?>> set) {
- QName ctx = BindingReflections.findQName(context);
- for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
- toDOMInstanceIdentifier)) {
- for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
- reg.unregisterPath(ctx, path);
- }
- }
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return supportedRpcs;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public void createDefaultDomForwarder() {
- if (baRpcRegistryImpl != null) {
- Class<?> cls = rpcServiceType.get();
- ClassLoader clsLoader = cls.getClassLoader();
- RpcService proxy = (RpcService) Proxy.newProxyInstance(clsLoader, new Class<?>[] { cls }, this);
-
- RpcRouter rpcRouter = baRpcRegistryImpl.getRpcRouter(rpcServiceType.get());
- rpcRouter.registerDefaultService(proxy);
- }
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode domInput) {
- checkArgument(rpc != null);
- checkArgument(domInput != null);
-
- Class<? extends RpcService> rpcType = rpcServiceType.get();
- checkState(rpcType != null);
- RpcService rpcService = baRpcRegistry.getRpcService(rpcType);
- checkState(rpcService != null);
- CompositeNode domUnwrappedInput = domInput.getFirstCompositeByName(QName.create(rpc, "input"));
-
- try {
- return Futures.immediateFuture(resolveInvocationStrategy(rpc).invokeOn(rpcService, domUnwrappedInput));
- } catch (Exception e) {
- return Futures.immediateFailedFuture(e);
- }
- }
-
- private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc) {
- return strategiesByQName.get(rpc);
- }
-
- private RpcInvocationStrategy createInvocationStrategy(final QName rpc,
- final Class<? extends RpcService> rpcType) throws Exception {
- return ClassLoaderUtils.withClassLoader(rpcType.getClassLoader(), new Callable<RpcInvocationStrategy>() {
- @Override
- public RpcInvocationStrategy call() throws Exception {
- String methodName = BindingMapping.getMethodName(rpc);
- Method targetMethod = null;
- for (Method possibleMethod : rpcType.getMethods()) {
- if (possibleMethod.getName().equals(methodName)
- && BindingReflections.isRpcMethod(possibleMethod)) {
- targetMethod = possibleMethod;
- break;
- }
- }
- checkState(targetMethod != null, "Rpc method not found");
- return new RpcInvocationStrategy(rpc,targetMethod, mappingService, biRpcRegistry);
- }
-
- });
- }
-
- /**
- * Registers RPC Forwarder to Binding Broker,
- * this means DOM Broekr has implementation of RPC
- * which is registered to it.
- *
- * If RPC Forwarder was previously registered to DOM Broker
- * or to Bidning Broker this method is noop to prevent
- * creating forwarding loop.
- *
- */
- public void registerToBindingBroker() {
- if(!registrationInProgress && forwarderRegistration == null) {
- try {
- registrationInProgress = true;
- this.forwarderRegistration = baRpcRegistry.addRpcImplementation((Class)rpcServiceType.get(), proxy);
- } catch (Exception e) {
- LOG.error("Unable to forward RPCs for {}",rpcServiceType.get(),e);
- } finally {
- registrationInProgress = false;
- }
- }
- }
}
public boolean isRpcForwarding() {
public void setDomNotificationService(final NotificationPublishService domService) {
this.domNotificationService = domService;
}
-
- private class DomToBindingNotificationForwarder implements NotificationInterestListener, NotificationListener {
-
- private final ConcurrentMap<QName, WeakReference<Class<? extends Notification>>> notifications = new ConcurrentHashMap<>();
- private final Set<QName> supportedNotifications = new HashSet<>();
-
- @Override
- public Set<QName> getSupportedNotifications() {
- return Collections.unmodifiableSet(supportedNotifications);
- }
-
- @Override
- public void onNotification(final CompositeNode notification) {
- QName qname = notification.getNodeType();
- WeakReference<Class<? extends Notification>> potential = notifications.get(qname);
- if (potential != null) {
- Class<? extends Notification> potentialClass = potential.get();
- if (potentialClass != null) {
- final DataContainer baNotification = mappingService.dataObjectFromDataDom(potentialClass,
- notification);
-
- if (baNotification instanceof Notification) {
- baNotifyService.publish((Notification) baNotification);
- }
- }
- }
- }
-
- @Override
- public void onNotificationSubscribtion(final Class<? extends Notification> notificationType) {
- QName qname = BindingReflections.findQName(notificationType);
- if (qname != null) {
- WeakReference<Class<? extends Notification>> already = notifications.putIfAbsent(qname,
- new WeakReference<Class<? extends Notification>>(notificationType));
- if (already == null) {
- domNotificationService.addNotificationListener(qname, this);
- supportedNotifications.add(qname);
- }
- }
- }
- }
}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class BindingToDomCommitHandler implements
+ DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ private final Logger LOG = LoggerFactory.getLogger(BindingToDomCommitHandler.class);
+
+ private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
+ private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions;
+ private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
+ private BindingIndependentMappingService mappingService;
+
+ BindingToDomCommitHandler(final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions,
+ final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions) {
+ this.bindingOpenedTransactions = bindingOpenedTransactions;
+ this.domOpenedTransactions = domOpenedTransactions;
+ }
+
+ public void setBindingIndependentDataService(final DataProviderService biDataService) {
+ this.biDataService = biDataService;
+ }
+
+ public void setMappingService(BindingIndependentMappingService mappingService) {
+ this.mappingService = mappingService;
+ }
+
+ @Override
+ public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
+ final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
+
+ /**
+ * Transaction was created as DOM transaction, in that case we do
+ * not need to forward it back.
+ */
+ if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
+ return CommitHandlerTransactions.allwaysSuccessfulTransaction(bindingTransaction);
+ }
+ DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
+ BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction, domOpenedTransactions);
+ LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .",
+ bindingTransaction.getIdentifier(), domTransaction.getIdentifier());
+ return wrapped;
+ }
+
+ private DataModificationTransaction createBindingToDomTransaction(
+ final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
+ if (biDataService == null) {
+ final String msg = "Binding Independent Service is not initialized correctly! Binding to DOM Transaction cannot be created for ";
+ LOG.error(msg + "{}", source);
+ throw new IllegalStateException(msg + source);
+ }
+ if (mappingService == null) {
+ final String msg = "Mapping Service is not initialized correctly! Binding to DOM Transaction cannot be created for ";
+ LOG.error(msg + "{}", source);
+ throw new IllegalStateException(msg + source);
+ }
+ DataModificationTransaction target = biDataService.beginTransaction();
+ LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(), source.getIdentifier());
+ for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+ target.removeConfigurationData(biEntry);
+ LOG.debug("Delete of Binding Configuration Data {} is translated to {}", entry, biEntry);
+ }
+ for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+ target.removeOperationalData(biEntry);
+ LOG.debug("Delete of Binding Operational Data {} is translated to {}", entry, biEntry);
+ }
+ for (Map.Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
+ .entrySet()) {
+ Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+ .toDataDom(entry);
+ target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
+ LOG.debug("Update of Binding Configuration Data {} is translated to {}", entry, biEntry);
+ }
+ for (Map.Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
+ .entrySet()) {
+ Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+ .toDataDom(entry);
+ target.putOperationalData(biEntry.getKey(), biEntry.getValue());
+ LOG.debug("Update of Binding Operational Data {} is translated to {}", entry, biEntry);
+ }
+ return target;
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+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.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+class BindingToDomTransaction implements
+ DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ private final DataModificationTransaction backing;
+ private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+ private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions;
+
+ public BindingToDomTransaction(final DataModificationTransaction backing,
+ final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification,
+ ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions) {
+ this.backing = backing;
+ this.modification = modification;
+ this.domOpenedTransactions = domOpenedTransactions;
+ this.domOpenedTransactions.put(backing.getIdentifier(), this);
+ }
+
+ @Override
+ public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
+ return modification;
+ }
+
+ @Override
+ public RpcResult<Void> finish() throws IllegalStateException {
+ Future<RpcResult<TransactionStatus>> result = backing.commit();
+ try {
+ RpcResult<TransactionStatus> biResult = result.get();
+ domOpenedTransactions.remove(backing.getIdentifier());
+ return RpcResultBuilder.<Void> status(biResult.isSuccessful())
+ .withRpcErrors(biResult.getErrors()).build();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("", e);
+ } catch (ExecutionException e) {
+ throw new IllegalStateException("", e);
+ } finally {
+ domOpenedTransactions.remove(backing.getIdentifier());
+ }
+ }
+
+ @Override
+ public RpcResult<Void> rollback() throws IllegalStateException {
+ domOpenedTransactions.remove(backing.getIdentifier());
+ return RpcResultBuilder.<Void> success().build();
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.common.util.CommitHandlerTransactions;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class DomToBindingCommitHandler implements //
+ RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject>>, //
+ DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
+
+ private final Logger LOG = LoggerFactory.getLogger(DomToBindingCommitHandler.class);
+
+ private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
+ private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions;
+
+ DomToBindingCommitHandler(final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions,
+ final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions) {
+ this.bindingOpenedTransactions = bindingOpenedTransactions;
+ this.domOpenedTransactions = domOpenedTransactions;
+ }
+
+ private DataProviderService baDataService;
+ private BindingIndependentMappingService mappingService;
+
+ public void setBindingAwareDataService(DataProviderService baDataService) {
+ this.baDataService = baDataService;
+ }
+
+ public void setMappingService(BindingIndependentMappingService mappingService) {
+ this.mappingService = mappingService;
+ }
+
+ @Override
+ public void onRegister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+ mappingService.toDataDom(registration.getPath());
+ }
+
+ @Override
+ public void onUnregister(
+ final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+ // NOOP for now
+ // FIXME: do registration based on only active commit handlers.
+ }
+
+ @Override
+ public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
+ final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
+ Object identifier = domTransaction.getIdentifier();
+
+ /**
+ * We checks if the transcation was originated in this mapper. If it
+ * was originated in this mapper we are returing allways success
+ * commit hanlder to prevent creating loop in two-phase commit and
+ * duplicating data.
+ */
+ if (domOpenedTransactions.containsKey(identifier)) {
+ return CommitHandlerTransactions.allwaysSuccessfulTransaction(domTransaction);
+ }
+
+ org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
+ DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction, bindingOpenedTransactions);
+ LOG.trace("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
+ baTransaction.getIdentifier());
+ return forwardedTransaction;
+ }
+
+ private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
+ final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
+ if (baDataService == null) {
+ final String msg = "Binding Aware Service is not initialized correctly! DOM to Binding Transaction cannot be created for ";
+ LOG.error(msg + "{}", source);
+ throw new IllegalStateException(msg + source);
+ }
+ if (mappingService == null) {
+ final String msg = "Mapping Service is not initialized correctly! DOM to Binding Transaction cannot be created for ";
+ LOG.error(msg + "{}", source);
+ throw new IllegalStateException(msg + source);
+ }
+
+ org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
+ .beginTransaction();
+ for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
+ try {
+
+ InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+ target.removeConfigurationData(baEntry);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}.", entry, e);
+ }
+ }
+ for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
+ try {
+
+ InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+ target.removeOperationalData(baEntry);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}.", entry, e);
+ }
+ }
+ for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
+ .getUpdatedConfigurationData().entrySet()) {
+ try {
+ InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+ DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+ target.putConfigurationData(baKey, baData);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
+ }
+ }
+ for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
+ .getUpdatedOperationalData().entrySet()) {
+ try {
+
+ InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
+ DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
+ target.putOperationalData(baKey, baData);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
+ }
+ }
+ return target;
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+class DomToBindingNotificationForwarder implements NotificationProviderService.NotificationInterestListener,
+ NotificationListener {
+
+ private final ConcurrentMap<QName, WeakReference<Class<? extends Notification>>> notifications = new ConcurrentHashMap<>();
+ private final Set<QName> supportedNotifications = new HashSet<>();
+
+ private final BindingIndependentMappingService mappingService;
+ private final NotificationProviderService baNotifyService;
+ private final NotificationPublishService domNotificationService;
+
+ DomToBindingNotificationForwarder(final BindingIndependentMappingService mappingService, final NotificationProviderService baNotifyService,
+ final NotificationPublishService domNotificationService) {
+ this.mappingService = mappingService;
+ this.baNotifyService = baNotifyService;
+ this.domNotificationService = domNotificationService;
+ }
+
+ @Override
+ public Set<QName> getSupportedNotifications() {
+ return Collections.unmodifiableSet(supportedNotifications);
+ }
+
+ @Override
+ public void onNotification(final CompositeNode notification) {
+ QName qname = notification.getNodeType();
+ WeakReference<Class<? extends Notification>> potential = notifications.get(qname);
+ if (potential != null) {
+ Class<? extends Notification> potentialClass = potential.get();
+ if (potentialClass != null) {
+ final DataContainer baNotification = mappingService.dataObjectFromDataDom(potentialClass,
+ notification);
+
+ if (baNotification instanceof Notification) {
+ baNotifyService.publish((Notification) baNotification);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onNotificationSubscribtion(final Class<? extends Notification> notificationType) {
+ QName qname = BindingReflections.findQName(notificationType);
+ if (qname != null) {
+ WeakReference<Class<? extends Notification>> already = notifications.putIfAbsent(qname,
+ new WeakReference<Class<? extends Notification>>(notificationType));
+ if (already == null) {
+ domNotificationService.addNotificationListener(qname, this);
+ supportedNotifications.add(qname);
+ }
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
+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.impl.codec.BindingIndependentMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+class DomToBindingRpcForwarder implements RpcImplementation, InvocationHandler {
+
+ private final Logger LOG = LoggerFactory.getLogger(DomToBindingRpcForwarder.class);
+
+ private final Set<QName> supportedRpcs;
+ private final WeakReference<Class<? extends RpcService>> rpcServiceType;
+ private Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
+ private final Map<QName, RpcInvocationStrategy> strategiesByQName = new HashMap<>();
+ private final WeakHashMap<Method, RpcInvocationStrategy> strategiesByMethod = new WeakHashMap<>();
+ private final RpcService proxy;
+ private ObjectRegistration<?> forwarderRegistration;
+ private boolean registrationInProgress = false;
+
+ private final RpcProvisionRegistry biRpcRegistry;
+ private final RpcProviderRegistry baRpcRegistry;
+ private final RpcProviderRegistryImpl baRpcRegistryImpl;
+
+ private final Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier;
+
+ private final static Method EQUALS_METHOD;
+
+ static {
+ try {
+ EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public DomToBindingRpcForwarder(final Class<? extends RpcService> service, final BindingIndependentMappingService mappingService,
+ final RpcProvisionRegistry biRpcRegistry, final RpcProviderRegistry baRpcRegistry, final RpcProviderRegistryImpl registryImpl) {
+ this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
+ this.supportedRpcs = mappingService.getRpcQNamesFor(service);
+
+ toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
+
+ @Override
+ public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(final InstanceIdentifier<?> input) {
+ return mappingService.toDataDom(input);
+ }
+ };
+
+ this.biRpcRegistry = biRpcRegistry;
+ this.baRpcRegistry = baRpcRegistry;
+ this.baRpcRegistryImpl = registryImpl;
+
+ Class<?> cls = rpcServiceType.get();
+ ClassLoader clsLoader = cls.getClassLoader();
+ proxy =(RpcService) Proxy.newProxyInstance(clsLoader, new Class<?>[] { cls }, this);
+ createStrategies(mappingService);
+ }
+
+ /**
+ * Constructor for Routed RPC Forwareder.
+ *
+ * @param service
+ * @param context
+ * @param registryImpl
+ */
+ public DomToBindingRpcForwarder(final Class<? extends RpcService> service,
+ final Class<? extends BaseIdentity> context, final BindingIndependentMappingService mappingService,
+ final RpcProvisionRegistry biRpcRegistry, final RpcProviderRegistry baRpcRegistry, final RpcProviderRegistryImpl registryImpl) {
+ this(service, mappingService, biRpcRegistry, baRpcRegistry,registryImpl);
+
+ final ImmutableSet.Builder<Broker.RoutedRpcRegistration> registrationsBuilder = ImmutableSet.builder();
+ try {
+ for (QName rpc : supportedRpcs) {
+ registrationsBuilder.add(biRpcRegistry.addRoutedRpcImplementation(rpc, this));
+ }
+ createDefaultDomForwarder();
+ } catch (Exception e) {
+ LOG.error("Could not forward Rpcs of type {}", service.getName(), e);
+ }
+ registrations = registrationsBuilder.build();
+ }
+
+
+
+ private void createStrategies(final BindingIndependentMappingService mappingService) {
+ try {
+ for (QName rpc : supportedRpcs) {
+ RpcInvocationStrategy strategy = createInvocationStrategy(rpc, rpcServiceType.get(), mappingService);
+ strategiesByMethod.put(strategy.targetMethod, strategy);
+ strategiesByQName.put(rpc, strategy);
+ }
+ } catch (Exception e) {
+ LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
+ }
+
+ }
+
+ /**
+ * Registers RPC Forwarder to DOM Broker,
+ * this means Binding Aware Broker has implementation of RPC
+ * which is registered to it.
+ *
+ * If RPC Forwarder was previously registered to DOM Broker
+ * or to Bidning Broker this method is noop to prevent
+ * creating forwarding loop.
+ *
+ */
+ public void registerToDOMBroker() {
+ if(!registrationInProgress && forwarderRegistration == null) {
+ registrationInProgress = true;
+ CompositeObjectRegistration.CompositeObjectRegistrationBuilder<DomToBindingRpcForwarder> builder = CompositeObjectRegistration.builderFor(this);
+ try {
+ for (QName rpc : supportedRpcs) {
+ builder.add(biRpcRegistry.addRpcImplementation(rpc, this));
+ }
+ } catch (Exception e) {
+ LOG.error("Could not forward Rpcs of type {}", rpcServiceType.get(), e);
+ }
+ this.forwarderRegistration = builder.toInstance();
+ registrationInProgress = false;
+ }
+ }
+
+
+ public void registerPaths(final Class<? extends BaseIdentity> context,
+ final Class<? extends RpcService> service, final Set<InstanceIdentifier<?>> set) {
+ QName ctx = BindingReflections.findQName(context);
+ for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
+ toDOMInstanceIdentifier)) {
+ for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
+ reg.registerPath(ctx, path);
+ }
+ }
+ }
+
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ if (EQUALS_METHOD.equals(method)) {
+ return false;
+ }
+ RpcInvocationStrategy strategy = strategiesByMethod.get(method);
+ checkState(strategy != null);
+ checkArgument(args.length <= 2);
+ if (args.length == 1) {
+ checkArgument(args[0] instanceof DataObject);
+ return strategy.forwardToDomBroker((DataObject) args[0]);
+ }
+ return strategy.forwardToDomBroker(null);
+ }
+
+ public void removePaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
+ final Set<InstanceIdentifier<?>> set) {
+ QName ctx = BindingReflections.findQName(context);
+ for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
+ toDOMInstanceIdentifier)) {
+ for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
+ reg.unregisterPath(ctx, path);
+ }
+ }
+ }
+
+ @Override
+ public Set<QName> getSupportedRpcs() {
+ return supportedRpcs;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public void createDefaultDomForwarder() {
+ if (baRpcRegistryImpl != null) {
+ Class<?> cls = rpcServiceType.get();
+ ClassLoader clsLoader = cls.getClassLoader();
+ RpcService proxy = (RpcService) Proxy.newProxyInstance(clsLoader, new Class<?>[] { cls }, this);
+
+ RpcRouter rpcRouter = baRpcRegistryImpl.getRpcRouter(rpcServiceType.get());
+ rpcRouter.registerDefaultService(proxy);
+ }
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode domInput) {
+ checkArgument(rpc != null);
+ checkArgument(domInput != null);
+
+ Class<? extends RpcService> rpcType = rpcServiceType.get();
+ checkState(rpcType != null);
+ RpcService rpcService = baRpcRegistry.getRpcService(rpcType);
+ checkState(rpcService != null);
+ CompositeNode domUnwrappedInput = domInput.getFirstCompositeByName(QName.create(rpc, "input"));
+
+ try {
+ return Futures.immediateFuture(resolveInvocationStrategy(rpc).invokeOn(rpcService, domUnwrappedInput));
+ } catch (Exception e) {
+ return Futures.immediateFailedFuture(e);
+ }
+ }
+
+ private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc) {
+ return strategiesByQName.get(rpc);
+ }
+
+ private RpcInvocationStrategy createInvocationStrategy(final QName rpc,
+ final Class<? extends RpcService> rpcType, final BindingIndependentMappingService mappingService) throws Exception {
+ return ClassLoaderUtils.withClassLoader(rpcType.getClassLoader(), new Callable<RpcInvocationStrategy>() {
+ @Override
+ public RpcInvocationStrategy call() throws Exception {
+ String methodName = BindingMapping.getMethodName(rpc);
+ Method targetMethod = null;
+ for (Method possibleMethod : rpcType.getMethods()) {
+ if (possibleMethod.getName().equals(methodName)
+ && BindingReflections.isRpcMethod(possibleMethod)) {
+ targetMethod = possibleMethod;
+ break;
+ }
+ }
+ checkState(targetMethod != null, "Rpc method not found");
+ return new RpcInvocationStrategy(rpc, targetMethod, mappingService, biRpcRegistry);
+ }
+
+ });
+ }
+
+ /**
+ * Registers RPC Forwarder to Binding Broker,
+ * this means DOM Broekr has implementation of RPC
+ * which is registered to it.
+ *
+ * If RPC Forwarder was previously registered to DOM Broker
+ * or to Bidning Broker this method is noop to prevent
+ * creating forwarding loop.
+ *
+ */
+ public void registerToBindingBroker() {
+ if(!registrationInProgress && forwarderRegistration == null) {
+ try {
+ registrationInProgress = true;
+ this.forwarderRegistration = baRpcRegistry.addRpcImplementation((Class)rpcServiceType.get(), proxy);
+ } catch (Exception e) {
+ LOG.error("Unable to forward RPCs for {}",rpcServiceType.get(),e);
+ } finally {
+ registrationInProgress = false;
+ }
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.base.Optional;
+
+/**
+ * Manager responsible for instantiating forwarders responsible for
+ * forwarding of RPC invocations from DOM Broker to Binding Aware Broker
+ *
+ */
+class DomToBindingRpcForwardingManager implements
+ RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>,
+ RpcProviderRegistryImpl.RouterInstantiationListener,
+ RpcProviderRegistryImpl.GlobalRpcRegistrationListener, RpcRegistrationListener {
+
+ private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
+ private final BindingIndependentMappingService mappingService;
+ private final RpcProvisionRegistry biRpcRegistry;
+ private final RpcProviderRegistry baRpcRegistry;
+ private RpcProviderRegistryImpl registryImpl;
+
+ DomToBindingRpcForwardingManager(final BindingIndependentMappingService mappingService, final RpcProvisionRegistry biRpcRegistry,
+ final RpcProviderRegistry baRpcRegistry) {
+ this.mappingService = mappingService;
+ this.biRpcRegistry = biRpcRegistry;
+ this.baRpcRegistry = baRpcRegistry;
+ }
+
+ public RpcProviderRegistryImpl getRegistryImpl() {
+ return registryImpl;
+ }
+
+ public void setRegistryImpl(final RpcProviderRegistryImpl registryImpl) {
+ this.registryImpl = registryImpl;
+ }
+
+ @Override
+ public void onGlobalRpcRegistered(final Class<? extends RpcService> cls) {
+ getRpcForwarder(cls, null).registerToDOMBroker();
+ }
+
+ @Override
+ public void onGlobalRpcUnregistered(final Class<? extends RpcService> cls) {
+ // NOOP
+ }
+
+ @Override
+ public void onRpcRouterCreated(final RpcRouter<?> router) {
+ Class<? extends BaseIdentity> ctx = router.getContexts().iterator().next();
+ getRpcForwarder(router.getServiceType(), ctx);
+ }
+
+ @Override
+ public void onRouteChange(final RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
+ for (Map.Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
+ bindingRoutesAdded(entry);
+ }
+ }
+
+ private void bindingRoutesAdded(final Map.Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
+ Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
+ Class<? extends RpcService> service = entry.getKey().getRpcService();
+ if (context != null) {
+ getRpcForwarder(service, context).registerPaths(context, service, entry.getValue());
+ }
+ }
+
+ private DomToBindingRpcForwarder getRpcForwarder(final Class<? extends RpcService> service,
+ final Class<? extends BaseIdentity> context) {
+ DomToBindingRpcForwarder potential = forwarders.get(service);
+ if (potential != null) {
+ return potential;
+ }
+ if (context == null) {
+ potential = new DomToBindingRpcForwarder(service, mappingService, biRpcRegistry, baRpcRegistry,registryImpl);
+ } else {
+ potential = new DomToBindingRpcForwarder(service, context, mappingService, biRpcRegistry, baRpcRegistry,registryImpl);
+ }
+
+ forwarders.put(service, potential);
+ return potential;
+ }
+
+ @Override
+ public void onRpcImplementationAdded(final QName name) {
+
+ final Optional<Class<? extends RpcService>> rpcInterface = mappingService.getRpcServiceClassFor(
+ name.getNamespace().toString(), name.getFormattedRevision());
+ if (rpcInterface.isPresent()) {
+ getRpcForwarder(rpcInterface.get(), null).registerToBindingBroker();
+ }
+ }
+
+ @Override
+ public void onRpcImplementationRemoved(final QName name) {
+
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+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.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+class DomToBindingTransaction implements
+ DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> {
+
+ private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
+ private final DataModification<InstanceIdentifier, CompositeNode> modification;
+ private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
+
+ public DomToBindingTransaction(
+ final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
+ final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification,
+ ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions) {
+ super();
+ this.backing = backing;
+ this.modification = modification;
+ this.bindingOpenedTransactions = bindingOpenedTransactions;
+ this.bindingOpenedTransactions.put(backing.getIdentifier(), this);
+ }
+
+ @Override
+ public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
+ return modification;
+ }
+
+ @Override
+ public RpcResult<Void> rollback() throws IllegalStateException {
+ bindingOpenedTransactions.remove(backing.getIdentifier());
+ return RpcResultBuilder.<Void> success().build();
+ }
+
+ @Override
+ public RpcResult<Void> finish() throws IllegalStateException {
+ Future<RpcResult<TransactionStatus>> result = backing.commit();
+ try {
+ RpcResult<TransactionStatus> baResult = result.get();
+ bindingOpenedTransactions.remove(backing.getIdentifier());
+ return RpcResultBuilder.<Void> status(baResult.isSuccessful())
+ .withRpcErrors(baResult.getErrors()).build();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("", e);
+ } catch (ExecutionException e) {
+ throw new IllegalStateException("", e);
+ } finally {
+ bindingOpenedTransactions.remove(backing.getIdentifier());
+ }
+ }
+}
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
-import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Future;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
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.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
if(biRpcRegistry == null) {
- return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
+ return Futures.<RpcResult<?>> immediateFuture(RpcResultBuilder.failed().build());
}
CompositeNode inputXml = null;
Function<RpcResult<CompositeNode>, RpcResult<?>> transformationFunction =
new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
+ @SuppressWarnings("rawtypes")
@Override
public RpcResult<?> apply(RpcResult<CompositeNode> result) {
}
}
- return Rpcs.getRpcResult(result.isSuccessful(), output, result.getErrors());
+ return RpcResultBuilder.from( (RpcResult)result ).withResult( output ).build();
}
};
}
if (futureResult == null) {
- return Rpcs.getRpcResult(false);
+ return RpcResultBuilder.<CompositeNode>failed().build();
}
- RpcResult<?> bindingResult = futureResult.get();
-
- Collection<RpcError> errors = bindingResult.getErrors();
- if( errors == null ) {
- errors = Collections.<RpcError>emptySet();
- }
+ @SuppressWarnings("rawtypes")
+ RpcResult bindingResult = futureResult.get();
final Object resultObj = bindingResult.getResult();
- CompositeNode output = null;
+ Object output = null;
if (resultObj instanceof DataObject) {
output = mappingService.toDataDom((DataObject)resultObj);
}
- return Rpcs.getRpcResult( bindingResult.isSuccessful(), output, errors);
+ return RpcResultBuilder.from( bindingResult ).withResult( output ).build();
}
public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+++ /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.binding.impl.util;
-
-import com.google.common.collect.Multimap;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map.Entry;
-import org.opendaylight.yangtools.concepts.Path;
-
-@SuppressWarnings("all")
-public class MapUtils {
- public static <P extends Path<P>, V extends Object> Collection<Entry<? extends P,? extends V>> getAllChildren(final Multimap<? extends P,? extends V> map, final P path) {
- HashSet<Entry<? extends P,? extends V>> _hashSet = new HashSet<Entry<? extends P, ? extends V>>();
- final HashSet<Entry<? extends P,? extends V>> ret = _hashSet;
- final Collection<? extends Entry<? extends P,? extends V>> entries = map.entries();
- for (final Entry<? extends P,? extends V> entry : entries) {
- {
- final P currentPath = entry.getKey();
- if (path.contains(currentPath)) {
- ret.add(entry);
- } else if (currentPath.contains(path)){
- ret.add(entry);
- }
- }
- }
- return ret;
- }
-}
-
--- /dev/null
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.path;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Regression test suite for Bug 1125 - Can't detect switch disconnection
+ * https://bugs.opendaylight.org/show_bug.cgi?id=1125
+ */
+public class Bug1125RegressionTest extends AbstractDataChangeListenerTest {
+
+ private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier
+ .create(Top.class);
+ private static final InstanceIdentifier<TopLevelList> TOP_FOO_PATH = TOP_PATH
+ .child(TopLevelList.class, TOP_FOO_KEY);
+
+ private static final InstanceIdentifier<TreeComplexUsesAugment> FOO_AUGMENT_PATH = TOP_FOO_PATH
+ .augmentation(TreeComplexUsesAugment.class);
+
+ private static final InstanceIdentifier<TreeComplexUsesAugment> WILDCARDED_AUGMENT_PATH = TOP_PATH
+ .child(TopLevelList.class).augmentation(
+ TreeComplexUsesAugment.class);
+
+ private void writeInitialState() {
+ WriteTransaction initialTx = getDataBroker().newWriteOnlyTransaction();
+ initialTx.put(LogicalDatastoreType.OPERATIONAL, TOP_PATH,
+ new TopBuilder().build());
+ TreeComplexUsesAugment fooAugment = new TreeComplexUsesAugmentBuilder()
+ .setContainerWithUses(
+ new ContainerWithUsesBuilder().setLeafFromGrouping(
+ "foo").build()).build();
+ initialTx.put(LogicalDatastoreType.OPERATIONAL, path(TOP_FOO_KEY),
+ topLevelList(TOP_FOO_KEY, fooAugment));
+ assertCommit(initialTx.commit());
+ }
+
+ private void delete(final InstanceIdentifier<?> path) {
+ WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
+ tx.delete(LogicalDatastoreType.OPERATIONAL, path);
+ assertCommit(tx.commit());
+ }
+
+ private void verifyRemoved(
+ final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event) {
+ assertEmpty(event.getCreatedData());
+ assertEmpty(event.getUpdatedData());
+ assertContains(event.getRemovedPaths(), FOO_AUGMENT_PATH);
+ }
+
+ private void deleteAndListenAugment(final DataChangeScope scope,
+ final InstanceIdentifier<?> path) {
+ writeInitialState();
+ TestListener listener = createListener(
+ LogicalDatastoreType.OPERATIONAL, WILDCARDED_AUGMENT_PATH,
+ scope);
+ delete(path);
+ verifyRemoved(listener.event());
+ }
+
+ @Test
+ public void deleteAndListenAugment() {
+
+ deleteAndListenAugment(DataChangeScope.ONE, TOP_PATH);
+
+ deleteAndListenAugment(DataChangeScope.BASE, TOP_PATH);
+
+ deleteAndListenAugment(DataChangeScope.SUBTREE, TOP_PATH);
+
+ deleteAndListenAugment(DataChangeScope.BASE, TOP_FOO_PATH);
+
+ deleteAndListenAugment(DataChangeScope.ONE, TOP_FOO_PATH);
+
+ deleteAndListenAugment(DataChangeScope.SUBTREE, TOP_FOO_PATH);
+
+ deleteAndListenAugment(DataChangeScope.BASE, FOO_AUGMENT_PATH);
+
+ deleteAndListenAugment(DataChangeScope.ONE, FOO_AUGMENT_PATH);
+
+ deleteAndListenAugment(DataChangeScope.SUBTREE, FOO_AUGMENT_PATH);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_BAR_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.path;
+
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.test.AssertCollections;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
+import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.rpcservice.rev140701.OpendaylightTestRpcServiceService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.rpc.routing.rev140701.OpendaylightTestRoutedRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.rpc.routing.rev140701.TestContext;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+
+public class RpcProviderRegistryTest {
+
+ private static InstanceIdentifier<TopLevelList> FOO_PATH = path(TOP_FOO_KEY);
+ private static InstanceIdentifier<TopLevelList> BAR_PATH = path(TOP_BAR_KEY);
+ private static RpcContextIdentifier ROUTING_CONTEXT = RpcContextIdentifier.contextFor(OpendaylightTestRoutedRpcService.class, TestContext.class);
+
+ private RpcProviderRegistryImpl rpcRegistry;
+
+ @Before
+ public void setup() {
+ rpcRegistry = new RpcProviderRegistryImpl("test");
+ }
+
+ private static class TestListener implements RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>> {
+
+ final SettableFuture<RouteChange<RpcContextIdentifier, InstanceIdentifier<?>>> event = SettableFuture.create();
+ @Override
+ public void onRouteChange(
+ final RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
+ event.set(change);
+ }
+ }
+
+ @Test
+ public void testGlobalRpcRegistrations() throws Exception {
+ OpendaylightTestRpcServiceService one = Mockito.mock(OpendaylightTestRpcServiceService.class);
+ OpendaylightTestRpcServiceService two = Mockito.mock(OpendaylightTestRpcServiceService.class);
+
+ RpcRegistration<OpendaylightTestRpcServiceService> regOne = rpcRegistry.addRpcImplementation(OpendaylightTestRpcServiceService.class, one);
+ assertNotNull(regOne);
+
+ try {
+ rpcRegistry.addRpcImplementation(OpendaylightTestRpcServiceService.class, two);
+ fail("Second call for registration of same RPC must throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ assertNotNull(e.getMessage());
+ }
+
+ regOne.close();
+
+ RpcRegistration<OpendaylightTestRpcServiceService> regTwo = rpcRegistry.addRpcImplementation(OpendaylightTestRpcServiceService.class, two);
+ assertNotNull(regTwo);
+ }
+
+ @Test
+ public void testRpcRouterInstance() throws Exception {
+ OpendaylightTestRoutedRpcService def = Mockito.mock(OpendaylightTestRoutedRpcService.class);
+
+ RpcRouter<OpendaylightTestRoutedRpcService> router = rpcRegistry.getRpcRouter(OpendaylightTestRoutedRpcService.class);
+
+ assertEquals(OpendaylightTestRoutedRpcService.class, router.getServiceType());
+ assertNotNull(router.getInvocationProxy());
+ assertNull(router.getDefaultService());
+
+ AssertCollections.assertContains(router.getContexts(), TestContext.class);
+
+ RpcRegistration<OpendaylightTestRoutedRpcService> regDef = router.registerDefaultService(def);
+ assertNotNull(regDef);
+ assertEquals(OpendaylightTestRoutedRpcService.class,regDef.getServiceType());
+ assertEquals(def,regDef.getInstance());
+ assertEquals(def, router.getDefaultService());
+
+ regDef.close();
+ assertNull("Default instance should be null after closing registration", router.getDefaultService());
+ }
+
+ @Test
+ public void testRoutedRpcPathChangeEvents() throws InterruptedException, TimeoutException, ExecutionException {
+ OpendaylightTestRoutedRpcService one = Mockito.mock(OpendaylightTestRoutedRpcService.class);
+ OpendaylightTestRoutedRpcService two = Mockito.mock(OpendaylightTestRoutedRpcService.class);
+ RoutedRpcRegistration<OpendaylightTestRoutedRpcService> regOne = rpcRegistry.addRoutedRpcImplementation(OpendaylightTestRoutedRpcService.class, one);
+ RoutedRpcRegistration<OpendaylightTestRoutedRpcService> regTwo = rpcRegistry.addRoutedRpcImplementation(OpendaylightTestRoutedRpcService.class, two);
+ assertNotNull(regOne);
+ assertNotNull(regTwo);
+
+ final TestListener addListener = new TestListener();
+ rpcRegistry.registerRouteChangeListener(addListener);
+ regOne.registerPath(TestContext.class, FOO_PATH);
+
+ RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> fooAddEvent = addListener.event.get(500, TimeUnit.MILLISECONDS);
+ Set<InstanceIdentifier<?>> announce = fooAddEvent.getAnnouncements().get(ROUTING_CONTEXT);
+ assertNotNull(announce);
+ AssertCollections.assertContains(announce, FOO_PATH);
+ AssertCollections.assertNotContains(announce, BAR_PATH);
+
+
+
+ final TestListener removeListener = new TestListener();
+ rpcRegistry.registerRouteChangeListener(removeListener);
+
+ regOne.unregisterPath(TestContext.class, FOO_PATH);
+
+ RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> fooRemoveEvent = removeListener.event.get(500, TimeUnit.MILLISECONDS);
+ Set<InstanceIdentifier<?>> removal = fooRemoveEvent.getRemovals().get(ROUTING_CONTEXT);
+ assertNotNull(removal);
+ AssertCollections.assertContains(removal, FOO_PATH);
+ AssertCollections.assertNotContains(removal, BAR_PATH);
+
+
+ }
+
+}
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.RpcService;
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.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
private void setupForForwardToDom(boolean hasOutput, boolean hasInput, int expectedErrorSize) {
- if (expectedErrorSize > 0)
+ if (expectedErrorSize > 0) {
errors.add(rpcError);
- RpcResult<CompositeNode> result = Rpcs.getRpcResult(true, invokeRpcResult, errors);
+ }
+ RpcResult<CompositeNode> result = RpcResultBuilder.<CompositeNode>success(invokeRpcResult)
+ .withRpcErrors( errors ).build();
futureCompNode = Futures.immediateFuture(result);
if( hasInput )
{
* invokeOn Tests
*/
private void setupRpcResultsWithOutput(int expectedErrorSize) {
- if (expectedErrorSize > 0)
+ if (expectedErrorSize > 0) {
errors.add(rpcError);
- RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+ }
+ RpcResult<CompositeNode> resultCompNode = RpcResultBuilder.<CompositeNode>success(inputInvokeOn)
+ .withRpcErrors(errors).build();
futureCompNode = Futures.immediateFuture(resultCompNode);
- RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, toDataDomInput, errors);
+ RpcResult<DataObject> resultDataObj = RpcResultBuilder.<DataObject>success(toDataDomInput)
+ .withRpcErrors(errors).build();
futureDataObj = Futures.immediateFuture(resultDataObj);
when(mockMappingService.toDataDom(toDataDomInput)).thenReturn(outputInvokeOn);
}
private void setupRpcResultsNoOutput(int expectedErrorSize) {
- if (expectedErrorSize > 0)
+ if (expectedErrorSize > 0) {
errors.add(rpcError);
- RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+ }
+ RpcResult<CompositeNode> resultCompNode = RpcResultBuilder.<CompositeNode>success(inputInvokeOn)
+ .withRpcErrors(errors).build();
futureCompNode = Futures.immediateFuture(resultCompNode);
- RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, null, errors);
+ RpcResult<DataObject> resultDataObj = RpcResultBuilder.<DataObject>success()
+ .withRpcErrors(errors).build();
futureDataObj = Futures.immediateFuture(resultDataObj);
}
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
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.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@Override
public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
CompositeNode result = testContext.getBindingToDomMappingService().toDataDom(output);
- return Futures.immediateFuture(Rpcs.getRpcResult(true, result, ImmutableList.<RpcError>of()));
+ return Futures.immediateFuture(RpcResultBuilder.<CompositeNode>success(result).build());
}
});
registration.registerPath(NodeContext.QNAME, BI_NODE_C_ID);
private Future<RpcResult<AddFlowOutput>> addFlowResult(boolean success, long xid) {
AddFlowOutput output = new AddFlowOutputBuilder() //
.setTransactionId(new TransactionId(BigInteger.valueOf(xid))).build();
- RpcResult<AddFlowOutput> result = Rpcs.getRpcResult(success, output, ImmutableList.<RpcError> of());
+ RpcResult<AddFlowOutput> result = RpcResultBuilder.<AddFlowOutput>status(success).withResult(output).build();
return Futures.immediateFuture(result);
}
import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(
final QName rpc, final CompositeNode input) {
- return Futures.immediateFuture(Rpcs
- .<CompositeNode> getRpcResult(true));
+ return Futures.immediateFuture(RpcResultBuilder
+ .<CompositeNode> success().build());
}
@Override
package org.opendaylight.controller.md.sal.common.impl.service;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.yangtools.concepts.Path;
-import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
log.trace("Transaction: {} Finished successfully (no effects).", transactionId);
- return Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
- Collections.<RpcError> emptySet());
+ return RpcResultBuilder.<TransactionStatus> success( TransactionStatus.COMMITED ).build();
}
final ImmutableList.Builder<ListenerStateCapture<P, D, DCL>> listenersBuilder = ImmutableList.builder();
log.trace("Transaction: {} Notifying listeners.", transactionId);
publishDataChangeEvent(listeners);
- return Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
- Collections.<RpcError> emptySet());
+ return RpcResultBuilder.<TransactionStatus> success(TransactionStatus.COMMITED).build();
}
private void captureInitialState(ImmutableList<ListenerStateCapture<P, D, DCL>> listeners) {
for (final DataCommitTransaction<P, D> transaction : transactions) {
transaction.rollback();
}
- Set<RpcError> _emptySet = Collections.<RpcError> emptySet();
- return Rpcs.<TransactionStatus> getRpcResult(false, TransactionStatus.FAILED, _emptySet);
+ return RpcResultBuilder.<TransactionStatus> failed().withResult(TransactionStatus.FAILED).build();
}
}
*/
package org.opendaylight.controller.sal.common.util;
-import java.util.Collections;
-
import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
import org.opendaylight.yangtools.concepts.Path;
-import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
public class CommitHandlerTransactions {
}
@Override
public RpcResult<Void> rollback() throws IllegalStateException {
- return Rpcs.<Void>getRpcResult(true, null, Collections.<RpcError>emptyList());
+ return RpcResultBuilder.<Void>success().build();
}
@Override
public RpcResult<Void> finish() throws IllegalStateException {
- return Rpcs.<Void>getRpcResult(true, null, Collections.<RpcError>emptyList());
+ return RpcResultBuilder.<Void>success().build();
}
@Override
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
/**
- * @author mirehak
- *
+ * @deprecated Use {@link org.opendaylight.yangtools.yang.common.RpcResultBuilder}
*/
+@Deprecated
public class RpcErrors {
/**
import com.google.common.collect.ImmutableList;
+/**
+ * @deprecated Use {@link org.opendaylight.yangtools.yang.common.RpcResultBuilder}
+ */
+@Deprecated
public class Rpcs {
public static <T> RpcResult<T> getRpcResult(boolean successful) {
*/
package org.opendaylight.controller.md.sal.dom.broker.impl;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
-import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
private RpcResult<TransactionStatus> commitBlocking() throws TransactionCommitFailedException {
commitAll().checkedGet();
- return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.<RpcError> emptySet());
+ return RpcResultBuilder.<TransactionStatus>success(TransactionStatus.COMMITED).build();
}
/**
--- /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.dom.broker.impl;
+
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+
+class GlobalRpcRegistration extends AbstractObjectRegistration<RpcImplementation> implements
+ RpcRegistration {
+ private final QName type;
+ private SchemaAwareRpcBroker router;
+
+ public GlobalRpcRegistration(final QName type, final RpcImplementation instance, final SchemaAwareRpcBroker router) {
+ super(instance);
+ this.type = type;
+ this.router = router;
+ }
+
+ @Override
+ public QName getType() {
+ return type;
+ }
+
+ @Override
+ protected void removeRegistration() {
+ if (router != null) {
+ router.remove(this);
+ router = null;
+ }
+ }
+}
\ No newline at end of file
*/
package org.opendaylight.controller.sal.dom.broker.impl;
-import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.data.DataStore;
-import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.slf4j.Logger;
}
public RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
- return Rpcs.<Void> getRpcResult(true, null,
- Collections.<RpcError> emptySet());
+ return RpcResultBuilder.<Void> success().build();
}
public RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
configuration.putAll(modification.getUpdatedConfigurationData());
operational.putAll(modification.getUpdatedOperationalData());
- return Rpcs.<Void> getRpcResult(true, null,
- Collections.<RpcError> emptySet());
+ return RpcResultBuilder.<Void> success().build();
}
public void remove(final Map<InstanceIdentifier, CompositeNode> map,
--- /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.dom.broker.impl;
+
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+class RoutedRpcRegImpl extends AbstractObjectRegistration<RpcImplementation> implements
+ RoutedRpcRegistration {
+
+ private final QName type;
+ private final RoutedRpcSelector router;
+
+ public RoutedRpcRegImpl(final QName rpcType, final RpcImplementation implementation, final RoutedRpcSelector routedRpcSelector) {
+ super(implementation);
+ this.type = rpcType;
+ router = routedRpcSelector;
+ }
+
+ @Override
+ public void registerPath(final QName context, final InstanceIdentifier path) {
+ router.addPath(context, path, this);
+ }
+
+ @Override
+ public void unregisterPath(final QName context, final InstanceIdentifier path) {
+ router.removePath(context, path, this);
+ }
+
+ @Override
+ protected void removeRegistration() {
+
+ }
+
+ @Override
+ public QName getType() {
+ return type;
+ }
+
+}
\ 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.sal.dom.broker.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy;
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
+import org.opendaylight.yangtools.concepts.Identifiable;
+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.SimpleNode;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.ListenableFuture;
+
+class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiable<RpcRoutingContext> {
+
+ private final RpcRoutingStrategy strategy;
+ private final Set<QName> supportedRpcs;
+ private final RpcRoutingContext identifier;
+ final ConcurrentMap<InstanceIdentifier, RoutedRpcRegImpl> implementations = new ConcurrentHashMap<>();
+ private final SchemaAwareRpcBroker router;
+
+ public RoutedRpcSelector(final RpcRoutingStrategy strategy, final SchemaAwareRpcBroker router) {
+ super();
+ this.strategy = strategy;
+ supportedRpcs = ImmutableSet.of(strategy.getIdentifier());
+ identifier = RpcRoutingContext.create(strategy.getContext(), strategy.getIdentifier());
+ this.router = router;
+ }
+
+ @Override
+ public RpcRoutingContext getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public void close() throws Exception {
+
+ }
+
+ @Override
+ public Set<QName> getSupportedRpcs() {
+ return supportedRpcs;
+ }
+
+ public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
+ return new RoutedRpcRegImpl(rpcType, implementation, this);
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
+ CompositeNode inputContainer = input.getFirstCompositeByName(QName.create(rpc,"input"));
+ checkArgument(inputContainer != null, "Rpc payload must contain input element");
+ SimpleNode<?> routeContainer = inputContainer.getFirstSimpleByName(strategy.getLeaf());
+ checkArgument(routeContainer != null, "Leaf %s must be set with value", strategy.getLeaf());
+ Object route = routeContainer.getValue();
+ checkArgument(route instanceof InstanceIdentifier,
+ "The routed node %s is not an instance identifier", route);
+ RpcImplementation potential = null;
+ if (route != null) {
+ RoutedRpcRegImpl potentialReg = implementations.get(route);
+ if (potentialReg != null) {
+ potential = potentialReg.getInstance();
+ }
+ }
+ if (potential == null) {
+ return router.invokeRpc(rpc, (InstanceIdentifier) route, input);
+ }
+ checkState(potential != null, "No implementation is available for rpc:%s path:%s", rpc, route);
+ return potential.invokeRpc(rpc, input);
+ }
+
+ public void addPath(final QName context, final InstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) {
+ //checkArgument(strategy.getContext().equals(context),"Supplied context is not supported.");
+ RoutedRpcRegImpl previous = implementations.put(path, routedRpcRegImpl);
+ if (previous == null) {
+ router.notifyPathAnnouncement(context,strategy.getIdentifier(), path);
+ }
+
+ }
+
+ public void removePath(final QName context, final InstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) {
+ boolean removed = implementations.remove(path, routedRpcRegImpl);
+ if (removed) {
+ router.notifyPathWithdrawal(context, strategy.getIdentifier(), path);
+ }
+ }
+}
\ No newline at end of file
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import com.google.common.base.Preconditions;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
import org.opendaylight.controller.md.sal.common.impl.routing.RoutingUtils;
+import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy;
import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
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.SimpleNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
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.api.UnknownSchemaNode;
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.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareRpcBroker.class);
- private static final QName CONTEXT_REFERENCE = QName.create("urn:opendaylight:yang:extension:yang-ext",
- "2013-07-09", "context-reference");
+
private final ListenerRegistry<RpcRegistrationListener> rpcRegistrationListeners = new ListenerRegistry<>();
private final ListenerRegistry<RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> routeChangeListeners = new ListenerRegistry<>();
private SchemaContextProvider schemaProvider;
private RoutedRpcDefaultImplementation defaultDelegate;
- public SchemaAwareRpcBroker(String identifier, SchemaContextProvider schemaProvider) {
+ public SchemaAwareRpcBroker(final String identifier, final SchemaContextProvider schemaProvider) {
super();
this.identifier = identifier;
this.schemaProvider = schemaProvider;
return defaultImplementation;
}
- public void setDefaultImplementation(RpcImplementation defaultImplementation) {
+ public void setDefaultImplementation(final RpcImplementation defaultImplementation) {
this.defaultImplementation = defaultImplementation;
}
return schemaProvider;
}
- public void setSchemaProvider(SchemaContextProvider schemaProvider) {
+ public void setSchemaProvider(final SchemaContextProvider schemaProvider) {
this.schemaProvider = schemaProvider;
}
}
@Override
- public void setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultDelegate) {
+ public void setRoutedRpcDefaultDelegate(final RoutedRpcDefaultImplementation defaultDelegate) {
this.defaultDelegate = defaultDelegate;
}
@Override
- public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
+ public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
checkArgument(rpcType != null, "RPC Type should not be null");
checkArgument(implementation != null, "RPC Implementatoin should not be null");
return getOrCreateRoutedRpcRouter(rpcType).addRoutedRpcImplementation(rpcType, implementation);
}
- private RoutedRpcSelector getOrCreateRoutedRpcRouter(QName rpcType) {
+ private RoutedRpcSelector getOrCreateRoutedRpcRouter(final QName rpcType) {
RoutedRpcSelector potential = getRoutedRpcRouter(rpcType);
if (potential != null) {
return potential;
return potential;
}
RpcDefinition definition = findRpcDefinition(rpcType);
- RoutingStrategy strategy = getRoutingStrategy(definition);
- checkState(strategy instanceof RoutedRpcStrategy, "Rpc %s is not routed.", rpcType);
- potential = new RoutedRpcSelector((RoutedRpcStrategy) strategy, this);
+ RpcRoutingStrategy strategy = RpcRoutingStrategy.from(definition);
+ checkState(strategy.isContextBasedRouted(), "Rpc %s is not routed.", rpcType);
+ potential = new RoutedRpcSelector( strategy, this);
implementations.put(rpcType, potential);
return potential;
}
}
- private RoutedRpcSelector getRoutedRpcRouter(QName rpcType) {
+ private RoutedRpcSelector getRoutedRpcRouter(final QName rpcType) {
RpcImplementation potential = implementations.get(rpcType);
if (potential != null) {
checkState(potential instanceof RoutedRpcSelector, "Rpc %s is not routed.", rpcType);
}
@Override
- public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation)
+ public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
throws IllegalArgumentException {
checkArgument(rpcType != null, "RPC Type should not be null");
checkArgument(implementation != null, "RPC Implementatoin should not be null");
checkState(!hasRpcImplementation(rpcType), "Implementation already registered");
RpcDefinition definition = findRpcDefinition(rpcType);
- checkArgument(!isRoutedRpc(definition), "RPC Type must not be routed.");
+ checkArgument(!RpcRoutingStrategy.from(definition).isContextBasedRouted(), "RPC Type must not be content routed.");
GlobalRpcRegistration reg = new GlobalRpcRegistration(rpcType, implementation, this);
final RpcImplementation previous = implementations.putIfAbsent(rpcType, implementation);
Preconditions.checkState(previous == null, "Rpc %s is already registered.",rpcType);
return reg;
}
- private void notifyRpcAdded(QName rpcType) {
+ private void notifyRpcAdded(final QName rpcType) {
for (ListenerRegistration<RpcRegistrationListener> listener : rpcRegistrationListeners) {
try {
listener.getInstance().onRpcImplementationAdded(rpcType);
}
}
- private boolean isRoutedRpc(RpcDefinition definition) {
- return getRoutingStrategy(definition) instanceof RoutedRpcStrategy;
- }
-
@Override
- public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener) {
+ public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(final RpcRegistrationListener listener) {
ListenerRegistration<RpcRegistrationListener> reg = rpcRegistrationListeners.register(listener);
for (QName impl : implementations.keySet()) {
listener.onRpcImplementationAdded(impl);
}
@Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
+ public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
return findRpcImplemention(rpc).invokeRpc(rpc, input);
}
- private RpcImplementation findRpcImplemention(QName rpc) {
+ private RpcImplementation findRpcImplemention(final QName rpc) {
checkArgument(rpc != null, "Rpc name should not be null");
RpcImplementation potentialImpl = implementations.get(rpc);
if (potentialImpl != null) {
return potentialImpl;
}
- private boolean hasRpcImplementation(QName rpc) {
+ private boolean hasRpcImplementation(final QName rpc) {
return implementations.containsKey(rpc);
}
- private RpcDefinition findRpcDefinition(QName rpcType) {
+ private RpcDefinition findRpcDefinition(final QName rpcType) {
checkArgument(rpcType != null, "Rpc name must be supplied.");
checkState(schemaProvider != null, "Schema Provider is not available.");
SchemaContext ctx = schemaProvider.getSchemaContext();
return findRpcDefinition(rpcType, module.getRpcs());
}
- static private RpcDefinition findRpcDefinition(QName rpcType, Set<RpcDefinition> rpcs) {
+ static private RpcDefinition findRpcDefinition(final QName rpcType, final Set<RpcDefinition> rpcs) {
checkState(rpcs != null, "Rpc schema is not available.");
for (RpcDefinition rpc : rpcs) {
if (rpcType.equals(rpc.getQName())) {
throw new IllegalArgumentException("Supplied Rpc Type is not defined.");
}
- private RoutingStrategy getRoutingStrategy(RpcDefinition rpc) {
- ContainerSchemaNode input = rpc.getInput();
- if (input != null) {
- for (DataSchemaNode schemaNode : input.getChildNodes()) {
- Optional<QName> context = getRoutingContext(schemaNode);
- if (context.isPresent()) {
- return createRoutedStrategy(rpc, context.get(), schemaNode.getQName());
- }
- }
- }
- return createGlobalStrategy(rpc);
- }
-
- private static RoutingStrategy createRoutedStrategy(RpcDefinition rpc, QName context, QName leafNode) {
- return new RoutedRpcStrategy(rpc.getQName(), context, leafNode);
- }
-
- private Optional<QName> getRoutingContext(DataSchemaNode schemaNode) {
- for (UnknownSchemaNode extension : schemaNode.getUnknownSchemaNodes()) {
- if (CONTEXT_REFERENCE.equals(extension.getNodeType())) {
- return Optional.fromNullable(extension.getQName());
- }
- }
- return Optional.absent();
- }
-
- private static RoutingStrategy createGlobalStrategy(RpcDefinition rpc) {
- GlobalRpcStrategy ret = new GlobalRpcStrategy(rpc.getQName());
- return ret;
- }
-
@Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input) {
- checkState(defaultDelegate != null);
- return defaultDelegate.invokeRpc(rpc, identifier, input);
- }
-
- private static abstract class RoutingStrategy implements Identifiable<QName> {
-
- private final QName identifier;
-
- public RoutingStrategy(QName identifier) {
- super();
- this.identifier = identifier;
- }
-
- @Override
- public QName getIdentifier() {
- return identifier;
- }
- }
-
- private static class GlobalRpcStrategy extends RoutingStrategy {
-
- public GlobalRpcStrategy(QName identifier) {
- super(identifier);
- }
- }
-
- private static class RoutedRpcStrategy extends RoutingStrategy {
-
- private final QName context;
- private final QName leaf;
-
- public RoutedRpcStrategy(QName identifier, QName ctx, QName leaf) {
- super(identifier);
- this.context = ctx;
- this.leaf = leaf;
- }
-
- public QName getContext() {
- return context;
- }
-
- public QName getLeaf() {
- return leaf;
- }
+ public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final InstanceIdentifier route, final CompositeNode input) {
+ checkState(defaultDelegate != null, "No implementation is available for rpc:%s path:%s", rpc, route);
+ return defaultDelegate.invokeRpc(rpc, route, input);
}
- private static class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiable<RpcRoutingContext> {
-
- private final RoutedRpcStrategy strategy;
- private final Set<QName> supportedRpcs;
- private final RpcRoutingContext identifier;
- private RpcImplementation defaultDelegate;
- private final ConcurrentMap<InstanceIdentifier, RoutedRpcRegImpl> implementations = new ConcurrentHashMap<>();
- private final SchemaAwareRpcBroker router;
-
- public RoutedRpcSelector(RoutedRpcStrategy strategy, SchemaAwareRpcBroker router) {
- super();
- this.strategy = strategy;
- supportedRpcs = ImmutableSet.of(strategy.getIdentifier());
- identifier = RpcRoutingContext.create(strategy.context, strategy.getIdentifier());
- this.router = router;
- }
-
- @Override
- public RpcRoutingContext getIdentifier() {
- return identifier;
- }
-
- @Override
- public void close() throws Exception {
-
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return supportedRpcs;
- }
-
- public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
- return new RoutedRpcRegImpl(rpcType, implementation, this);
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
- CompositeNode inputContainer = input.getFirstCompositeByName(QName.create(rpc,"input"));
- checkArgument(inputContainer != null, "Rpc payload must contain input element");
- SimpleNode<?> routeContainer = inputContainer.getFirstSimpleByName(strategy.getLeaf());
- checkArgument(routeContainer != null, "Leaf %s must be set with value", strategy.getLeaf());
- Object route = routeContainer.getValue();
- checkArgument(route instanceof InstanceIdentifier,
- "The routed node %s is not an instance identifier", route);
- RpcImplementation potential = null;
- if (route != null) {
- RoutedRpcRegImpl potentialReg = implementations.get(route);
- if (potentialReg != null) {
- potential = potentialReg.getInstance();
- }
- }
- if (potential == null) {
- return router.invokeRpc(rpc, (InstanceIdentifier) route, input);
- }
- checkState(potential != null, "No implementation is available for rpc:%s path:%s", rpc, route);
- return potential.invokeRpc(rpc, input);
- }
-
- public void addPath(QName context, InstanceIdentifier path, RoutedRpcRegImpl routedRpcRegImpl) {
- //checkArgument(strategy.getContext().equals(context),"Supplied context is not supported.");
- RoutedRpcRegImpl previous = implementations.put(path, routedRpcRegImpl);
- if (previous == null) {
- router.notifyPathAnnouncement(context,strategy.getIdentifier(), path);
- }
-
- }
-
- public void removePath(QName context, InstanceIdentifier path, RoutedRpcRegImpl routedRpcRegImpl) {
- boolean removed = implementations.remove(path, routedRpcRegImpl);
- if (removed) {
- router.notifyPathWithdrawal(context, strategy.getIdentifier(), path);
- }
- }
- }
-
- private static class GlobalRpcRegistration extends AbstractObjectRegistration<RpcImplementation> implements
- RpcRegistration {
- private final QName type;
- private SchemaAwareRpcBroker router;
-
- public GlobalRpcRegistration(QName type, RpcImplementation instance, SchemaAwareRpcBroker router) {
- super(instance);
- this.type = type;
- this.router = router;
- }
-
- @Override
- public QName getType() {
- return type;
- }
-
- @Override
- protected void removeRegistration() {
- if (router != null) {
- router.remove(this);
- router = null;
- }
- }
- }
-
- private static class RoutedRpcRegImpl extends AbstractObjectRegistration<RpcImplementation> implements
- RoutedRpcRegistration {
-
- private final QName type;
- private final RoutedRpcSelector router;
-
- public RoutedRpcRegImpl(QName rpcType, RpcImplementation implementation, RoutedRpcSelector routedRpcSelector) {
- super(implementation);
- this.type = rpcType;
- router = routedRpcSelector;
- }
-
- @Override
- public void registerPath(QName context, InstanceIdentifier path) {
- router.addPath(context, path, this);
- }
-
- @Override
- public void unregisterPath(QName context, InstanceIdentifier path) {
- router.removePath(context, path, this);
- }
-
- @Override
- protected void removeRegistration() {
-
- }
-
- @Override
- public QName getType() {
- return type;
- }
-
- }
-
- private void remove(GlobalRpcRegistration registration) {
+ void remove(final GlobalRpcRegistration registration) {
implementations.remove(registration.getType(), registration);
}
- private void notifyPathAnnouncement(QName context, QName identifier, InstanceIdentifier path) {
+ void notifyPathAnnouncement(final QName context, final QName identifier, final InstanceIdentifier path) {
RpcRoutingContext contextWrapped = RpcRoutingContext.create(context, identifier);
RouteChange<RpcRoutingContext, InstanceIdentifier> change = RoutingUtils.announcementChange(contextWrapped , path);
for(ListenerRegistration<RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> routeListener : routeChangeListeners) {
routeListener.getInstance().onRouteChange(change);
} catch (Exception e) {
LOG.error("Unhandled exception during invoking onRouteChange for {}",routeListener.getInstance(),e);
-
}
}
}
-
-
- private void notifyPathWithdrawal(QName context,QName identifier, InstanceIdentifier path) {
+ void notifyPathWithdrawal(final QName context,final QName identifier, final InstanceIdentifier path) {
RpcRoutingContext contextWrapped = RpcRoutingContext.create(context, identifier);
RouteChange<RpcRoutingContext, InstanceIdentifier> change = RoutingUtils.removalChange(contextWrapped , path);
for(ListenerRegistration<RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> routeListener : routeChangeListeners) {
@Override
public <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(
- L listener) {
+ final L listener) {
ListenerRegistration<L> reg = routeChangeListeners.registerWithType(listener);
RouteChange<RpcRoutingContext, InstanceIdentifier> initial = createInitialRouteChange();
try {
--- /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.dom.broker.spi.rpc;
+
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+
+import com.google.common.base.Optional;
+
+public abstract class RpcRoutingStrategy implements Identifiable<QName> {
+
+ private final QName identifier;
+ private static final QName CONTEXT_REFERENCE = QName.create("urn:opendaylight:yang:extension:yang-ext",
+ "2013-07-09", "context-reference");
+
+ private RpcRoutingStrategy(final QName identifier) {
+ super();
+ this.identifier = identifier;
+ }
+
+ /**
+ * Returns leaf QName in which RPC Route is stored
+ *
+ *
+ * @return leaf QName in which RPC Route is stored
+ * @throws UnsupportedOperationException If RPC is not content routed.
+ * ({@link #isContextBasedRouted()} returned <code>false</code>)
+ */
+ public abstract QName getLeaf();
+
+ /**
+ * Returns identity QName which represents RPC Routing context
+ *
+ * @return identity QName which represents RPC Routing context
+ * @throws UnsupportedOperationException If RPC is not content routed.
+ * ({@link #isContextBasedRouted()} returned <code>false</code>)
+ */
+ public abstract QName getContext();
+
+ @Override
+ public QName getIdentifier() {
+ return identifier;
+ }
+
+ /**
+ * Returns true if RPC is routed by context.
+ *
+ * @return true if RPC is routed by content.
+ */
+ public abstract boolean isContextBasedRouted();
+
+ public static RpcRoutingStrategy from(final RpcDefinition rpc) {
+ ContainerSchemaNode input = rpc.getInput();
+ if (input != null) {
+ for (DataSchemaNode schemaNode : input.getChildNodes()) {
+ Optional<QName> context = getRoutingContext(schemaNode);
+ if (context.isPresent()) {
+ return createRoutedStrategy(rpc, context.get(), schemaNode.getQName());
+ }
+ }
+ }
+ return createGlobalStrategy(rpc);
+ }
+
+ public static Optional<QName> getRoutingContext(final DataSchemaNode schemaNode) {
+ for (UnknownSchemaNode extension : schemaNode.getUnknownSchemaNodes()) {
+ if (CONTEXT_REFERENCE.equals(extension.getNodeType())) {
+ return Optional.fromNullable(extension.getQName());
+ }
+ }
+ return Optional.absent();
+ }
+
+ private static RpcRoutingStrategy createRoutedStrategy(final RpcDefinition rpc, final QName context, final QName leafNode) {
+ return new RoutedRpcStrategy(rpc.getQName(), context, leafNode);
+ }
+
+
+
+ private static RpcRoutingStrategy createGlobalStrategy(final RpcDefinition rpc) {
+ GlobalRpcStrategy ret = new GlobalRpcStrategy(rpc.getQName());
+ return ret;
+ }
+
+ private static class RoutedRpcStrategy extends RpcRoutingStrategy {
+
+ final QName context;
+ private final QName leaf;
+
+ private RoutedRpcStrategy(final QName identifier, final QName ctx, final QName leaf) {
+ super(identifier);
+ this.context = ctx;
+ this.leaf = leaf;
+ }
+
+ @Override
+ public QName getContext() {
+ return context;
+ }
+
+ @Override
+ public QName getLeaf() {
+ return leaf;
+ }
+
+ @Override
+ public boolean isContextBasedRouted() {
+ return true;
+ }
+ }
+
+ private static class GlobalRpcStrategy extends RpcRoutingStrategy {
+
+ public GlobalRpcStrategy(final QName identifier) {
+ super(identifier);
+ }
+
+ @Override
+ public boolean isContextBasedRouted() {
+ return false;
+ }
+
+ @Override
+ public QName getContext() {
+ throw new UnsupportedOperationException("Not routed strategy does not have context.");
+ }
+
+ @Override
+ public QName getLeaf() {
+ throw new UnsupportedOperationException("Not routed strategy does not have context.");
+ }
+ }
+}
\ No newline at end of file
package org.opendaylight.controller.sal.connect.netconf.listener;
import java.util.ArrayDeque;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.connect.api.RemoteDevice;
import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
-import org.opendaylight.controller.sal.connect.util.FailedRpcResult;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
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.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final NetconfClientConfiguration config) {
if(config instanceof NetconfReconnectingClientConfiguration) {
dispatch.createReconnectingClient((NetconfReconnectingClientConfiguration) config);
+ } else {
+ dispatch.createClient(config);
}
-
- dispatch.createClient(config);
}
private void tearDown( String reason ) {
private RpcResult<NetconfMessage> createErrorRpcResult( RpcError.ErrorType errorType, String message )
{
- return new FailedRpcResult<NetconfMessage>( RpcErrors.getRpcError( null,
- NetconfDocumentedException.ErrorTag.operation_failed.getTagValue(),
- null, RpcError.ErrorSeverity.ERROR, message, errorType, null ) );
+ return RpcResultBuilder.<NetconfMessage>failed()
+ .withError( errorType, NetconfDocumentedException.ErrorTag.operation_failed.getTagValue(),
+ message )
+ .build();
}
@Override
logger.warn( "{}: Invalid request-reply match, reply message contains different message-id, request: {}, response: {}",
id, msgToS( request.request ), msgToS( message ), e );
- request.future.set( new FailedRpcResult<NetconfMessage>(
- NetconfMessageTransformUtil.toRpcError( e ) ) );
+ request.future.set( RpcResultBuilder.<NetconfMessage>failed()
+ .withRpcError( NetconfMessageTransformUtil.toRpcError( e ) ).build() );
return;
}
logger.warn( "{}: Error reply from remote device, request: {}, response: {}", id,
msgToS( request.request ), msgToS( message ), e );
- request.future.set( new FailedRpcResult<NetconfMessage>(
- NetconfMessageTransformUtil.toRpcError( e ) ) );
+ request.future.set( RpcResultBuilder.<NetconfMessage>failed()
+ .withRpcError( NetconfMessageTransformUtil.toRpcError( e ) ).build() );
return;
}
- request.future.set(Rpcs.getRpcResult( true, message, Collections.<RpcError>emptySet() ) );
+ request.future.set( RpcResultBuilder.<NetconfMessage>success( message ).build() );
}
}
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.connect.util.FailedRpcResult;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.slf4j.Logger;
@Override
public RpcResult<Void> finish() throws IllegalStateException {
- return new FailedRpcResult<>(RpcErrors.getRpcError(null, null, null, RpcError.ErrorSeverity.ERROR,
- id + ": Unexpected operation error during pre-commit operations", RpcError.ErrorType.APPLICATION, e));
+ return RpcResultBuilder.<Void>failed().withError( RpcError.ErrorType.APPLICATION,
+ id + ": Unexpected operation error during pre-commit operations", e ).build();
}
@Override
import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures;
+
import java.util.Collections;
import java.util.Set;
import javax.annotation.Nullable;
+
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.connect.api.MessageTransformer;
import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import com.google.common.util.concurrent.ListenableFuture;
if (netconfMessageRpcResult.isSuccessful()) {
return transformer.toRpcResult(netconfMessageRpcResult.getResult(), rpc);
} else {
- return Rpcs.getRpcResult(false, netconfMessageRpcResult.getErrors());
+ return RpcResultBuilder.<CompositeNode> failed()
+ .withRpcErrors(netconfMessageRpcResult.getErrors()).build();
}
}
*/
package org.opendaylight.controller.sal.connect.netconf.sal;
+import com.google.common.base.Preconditions;
import java.util.Collection;
import java.util.Collections;
-
import java.util.concurrent.ExecutorService;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-
final class NetconfDeviceSalProvider implements AutoCloseable, Provider, BindingAwareProvider {
private static final Logger logger = LoggerFactory.getLogger(NetconfDeviceSalProvider.class);
public MountProvisionInstance getMountInstance() {
Preconditions.checkState(mountInstance != null,
- "%s: Sal provider was not initialized by sal. Cannot publish notification", id);
+ "%s: Sal provider was not initialized by sal. Cannot get mount instance", id);
return mountInstance;
}
public NetconfDeviceDatastoreAdapter getDatastoreAdapter() {
Preconditions.checkState(datastoreAdapter != null,
- "%s: Sal provider %s was not initialized by sal. Cannot publish notification", id);
+ "%s: Sal provider %s was not initialized by sal. Cannot get datastore adapter", id);
return datastoreAdapter;
}
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
-import org.opendaylight.controller.sal.connect.util.FailedRpcResult;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
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.common.RpcResultBuilder;
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;
throw new RuntimeException(id + ": Interrupted while waiting for response", e);
} catch (final ExecutionException e) {
LOG.warn("{}: Failed to finish commit operation", id, e);
- return new FailedRpcResult<>(RpcErrors.getRpcError(null, null, null, RpcError.ErrorSeverity.ERROR,
- id + ": Unexpected operation error during commit operation", RpcError.ErrorType.APPLICATION, e));
+ return RpcResultBuilder.<Void>failed().withError( RpcError.ErrorType.APPLICATION,
+ id + ": Unexpected operation error during commit operation", e ).build();
}
}
package org.opendaylight.controller.sal.connect.netconf.schema.mapping;
import com.google.common.base.Optional;
-import java.util.Collections;
+
import java.util.List;
import java.util.Set;
+
import javax.activation.UnsupportedDataTypeException;
+
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.connect.api.MessageTransformer;
import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
import org.opendaylight.controller.sal.connect.util.MessageCounter;
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.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
return toRpcResult(message, rpc, schemaContext.get());
} else {
final CompositeNode node = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
- return Rpcs.getRpcResult(true, node, Collections.<RpcError>emptySet());
+ return RpcResultBuilder.success( node ).build();
}
}
compositeNode = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
}
- return Rpcs.getRpcResult(true, compositeNode, Collections.<RpcError> emptySet());
+ return RpcResultBuilder.success( compositeNode ).build();
}
@Override
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.sal.common.util.RpcErrors;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
}
}
- return RpcErrors.getRpcError( null, ex.getErrorTag().getTagValue(), infoBuilder.toString(),
- toRpcErrorSeverity( ex.getErrorSeverity() ), ex.getLocalizedMessage(),
- toRpcErrorType( ex.getErrorType() ), ex.getCause() );
+ ErrorSeverity severity = toRpcErrorSeverity( ex.getErrorSeverity() );
+ return severity == ErrorSeverity.ERROR ?
+ RpcResultBuilder.newError(
+ toRpcErrorType( ex.getErrorType() ), ex.getErrorTag().getTagValue(),
+ ex.getLocalizedMessage(), null, infoBuilder.toString(), ex.getCause() ) :
+ RpcResultBuilder.newWarning(
+ toRpcErrorType( ex.getErrorType() ), ex.getErrorTag().getTagValue(),
+ ex.getLocalizedMessage(), null, infoBuilder.toString(), ex.getCause() );
}
private static ErrorSeverity toRpcErrorSeverity( final NetconfDocumentedException.ErrorSeverity severity ) {
.addAll(Collections2.filter(node.getValue(), new Predicate<Node<?>>() {
@Override
public boolean apply(@Nullable final Node<?> input) {
- return input.getNodeType() != inputQName;
+ return !inputQName.equals(input.getNodeType());
}
})) //
.build();
+++ /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.util;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-public final class FailedRpcResult<T> implements RpcResult<T> {
-
- private final RpcError rpcError;
-
- public FailedRpcResult(final RpcError rpcError) {
- this.rpcError = rpcError;
- }
-
- @Override
- public boolean isSuccessful() {
- return false;
- }
-
- @Override
- public T getResult() {
- return null;
- }
-
- @Override
- public Collection<RpcError> getErrors() {
- return Collections.singletonList(rpcError);
- }
-}
import org.mockito.Mockito;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.connect.api.MessageTransformer;
import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
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.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
}
}
- private static final RpcResult<NetconfMessage> rpcResult = Rpcs.getRpcResult(true, netconfMessage, Collections.<RpcError>emptySet());
- private static final RpcResult<CompositeNode> rpcResultC = Rpcs.getRpcResult(true, compositeNode, Collections.<RpcError>emptySet());
+ private static final RpcResult<NetconfMessage> rpcResult = RpcResultBuilder.success(netconfMessage).build();
+ private static final RpcResult<CompositeNode> rpcResultC = RpcResultBuilder.success(compositeNode).build();
public static final String TEST_NAMESPACE = "test:namespace";
public static final String TEST_MODULE = "test-module";
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+/**
+ * Test case for reported bug 1355
+ *
+ * @author Lukas Sedlak
+ * @see <a
+ * https://bugs.opendaylight.org/show_bug.cgi?id=1355</a>
+ */
+public class NetconfToRpcRequestTest {
+
+ private String TEST_MODEL_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:rpc-test";
+ private String REVISION = "2014-07-14";
+ private QName INPUT_QNAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "input");
+ private QName STREAM_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "stream-name");
+ private QName RPC_NAME = QName.create(TEST_MODEL_NAMESPACE, REVISION, "subscribe");
+
+ NetconfMessageTransformer messageTransformer;
+
+ @SuppressWarnings("deprecation")
+ @Before
+ public void setup() throws Exception {
+ final List<InputStream> modelsToParse = Collections
+ .singletonList(getClass().getResourceAsStream("/schemas/rpc-notification-subscription.yang"));
+ final YangContextParser parser = new YangParserImpl();
+ final Set<Module> modules = parser.parseYangModelsFromStreams(modelsToParse);
+ assertTrue(!modules.isEmpty());
+ final SchemaContext schemaContext = parser.resolveSchemaContext(modules);
+ assertNotNull(schemaContext);
+
+ messageTransformer = new NetconfMessageTransformer();
+ messageTransformer.onGlobalContextUpdated(schemaContext);
+ }
+
+ @Test
+ public void test() throws Exception {
+ final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
+ rootBuilder.setQName(RPC_NAME);
+
+ final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
+ inputBuilder.setQName(INPUT_QNAME);
+ inputBuilder.addLeaf(STREAM_NAME, "NETCONF");
+
+ rootBuilder.add(inputBuilder.toInstance());
+ final ImmutableCompositeNode root = rootBuilder.toInstance();
+
+ final CompositeNode flattenedNode = NetconfMessageTransformUtil.flattenInput(root);
+ assertNotNull(flattenedNode);
+ assertEquals(1, flattenedNode.size());
+
+ final List<CompositeNode> inputNode = flattenedNode.getCompositesByName(INPUT_QNAME);
+ assertNotNull(inputNode);
+ assertTrue(inputNode.isEmpty());
+
+ final NetconfMessage message = messageTransformer.toRpcRequest(RPC_NAME, root);
+ assertNotNull(message);
+ }
+}
--- /dev/null
+module rpc-notification-subscription {
+
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:rpc-test";
+ prefix "rpc";
+
+ organization
+ "Cisco Systems, Inc.";
+
+ contact
+ "lsedlak@cisco.com";
+
+ description
+ "Test model for testing of rpc INPUT parameter during subscription call.";
+
+ revision 2014-07-14 {
+ description
+ "Initial revision.";
+ }
+
+ rpc subscribe {
+ description
+ "Test rpc to init subscription";
+
+ input {
+ leaf stream-name {
+ type string;
+ default "NETCONF";
+ description
+ "Optional stream name param.";
+ }
+
+ anyxml data {
+ description
+ "Optional additional data.";
+ }
+ }
+ }
+}
\ No newline at end of file
package org.opendaylight.controller.sal.restconf.impl;
import com.google.common.util.concurrent.Futures;
-import java.util.Collections;
+
import java.util.concurrent.Future;
+
import javax.ws.rs.core.Response.Status;
+
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
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.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.slf4j.Logger;
LOG.info("Delete Configuration via Restconf: {}", path);
CompositeNode redDataAtPath = transaction.readConfigurationData(path);
if (redDataAtPath == null) {
- return Futures.immediateFuture(Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
- Collections.<RpcError> emptyList()));
+ return Futures.immediateFuture(RpcResultBuilder.<TransactionStatus>
+ success(TransactionStatus.COMMITED).build());
}
transaction.removeConfigurationData(path);
return transaction.commit();
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
+
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.ModifyAction;
import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
CompositeNode payload = preparePayload();
when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenReturn(
- Futures.<RpcResult<CompositeNode>> immediateFuture(Rpcs.<CompositeNode> getRpcResult(true)));
+ Futures.<RpcResult<CompositeNode>> immediateFuture(RpcResultBuilder.<CompositeNode>success().build()));
StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", payload, uriInfo);
assertTrue(structData == null);
@Test
public void testInvokeRpcWithNoPayloadRpc_FailNoErrors() {
- RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(false);
+ RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>failed().build();
BrokerFacade brokerFacade = mock(BrokerFacade.class);
when(
@Test
public void testInvokeRpcWithNoPayloadRpc_FailWithRpcError() {
- List<RpcError> rpcErrors = Arrays.asList(RpcErrors.getRpcError(null, "bogusTag", null, ErrorSeverity.ERROR,
- "foo", RpcError.ErrorType.TRANSPORT, null), RpcErrors.getRpcError("app-tag", "in-use", null,
- ErrorSeverity.WARNING, "bar", RpcError.ErrorType.RPC, null));
+ List<RpcError> rpcErrors = Arrays.asList(
+ RpcResultBuilder.newError( RpcError.ErrorType.TRANSPORT, "bogusTag", "foo" ),
+ RpcResultBuilder.newWarning( RpcError.ErrorType.RPC, "in-use", "bar",
+ "app-tag", null, null ) );
- RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(false, rpcErrors);
+ RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>failed()
+ .withRpcErrors(rpcErrors).build();
BrokerFacade brokerFacade = mock(BrokerFacade.class);
when(
@Test
public void testInvokeRpcWithNoPayload_Success() {
- RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(true);
+ RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>success().build();
BrokerFacade brokerFacade = mock(BrokerFacade.class);
when(
@Test
public void testInvokeRpcMethodWithInput() {
- RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(true);
+ RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>success().build();
CompositeNode payload = mock(CompositeNode.class);
@Test
public void testInvokeRpcWithNoPayloadWithOutput_Success() {
CompositeNode compositeNode = mock(CompositeNode.class);
- RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(true, compositeNode,
- Collections.<RpcError> emptyList());
+ RpcResult<CompositeNode> rpcResult =
+ RpcResultBuilder.<CompositeNode>success(compositeNode).build();
BrokerFacade brokerFacade = mock(BrokerFacade.class);
when(
@Test
public void testMountedRpcCallNoPayload_Success() throws Exception {
- RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode> getRpcResult(true);
+ RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>success().build();
ListenableFuture<RpcResult<CompositeNode>> mockListener = mock(ListenableFuture.class);
when(mockListener.get()).thenReturn(rpcResult);
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.core.api.mount.MountService;
import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
List<RpcError> rpcErrors = new ArrayList<>();
- rpcErrors.add(RpcErrors.getRpcError("applicationTag1", "tag1", "info1", ErrorSeverity.ERROR, "message1",
- ErrorType.RPC, null));
- rpcErrors.add(RpcErrors.getRpcError("applicationTag2", "tag2", "info2", ErrorSeverity.WARNING, "message2",
- ErrorType.PROTOCOL, null));
+ rpcErrors.add( RpcResultBuilder.newError( ErrorType.RPC, "tag1", "message1",
+ "applicationTag1", "info1", null ) );
+ rpcErrors.add( RpcResultBuilder.newWarning( ErrorType.PROTOCOL, "tag2", "message2",
+ "applicationTag2", "info2", null ) );
mockInvokeRpc(null, false, rpcErrors);
assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
-import static org.opendaylight.controller.sal.common.util.RpcErrors.getRpcError;
import java.util.HashMap;
import java.util.Map;
import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
/**
* Unit tests for RestconfError.
public void testRestConfErrorWithRpcError() {
// All fields set
- RpcError rpcError = getRpcError("mock app-tag", ErrorTag.BAD_ATTRIBUTE.getTagValue(), "mock error-info",
- RpcError.ErrorSeverity.ERROR, "mock error-message", RpcError.ErrorType.PROTOCOL, new Exception(
- "mock cause"));
+ RpcError rpcError = RpcResultBuilder.newError(
+ RpcError.ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE.getTagValue(), "mock error-message",
+ "mock app-tag", "mock error-info", new Exception( "mock cause" ) );
validateRestConfError("mock error-message", ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE, "mock app-tag",
"mock error-info", new RestconfError(rpcError));
// All fields set except 'info' - expect error-info set to 'cause'
- rpcError = getRpcError("mock app-tag", ErrorTag.BAD_ATTRIBUTE.getTagValue(), null,
- RpcError.ErrorSeverity.ERROR, "mock error-message", RpcError.ErrorType.PROTOCOL, new Exception(
- "mock cause"));
+ rpcError = RpcResultBuilder.newError(
+ RpcError.ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE.getTagValue(), "mock error-message",
+ "mock app-tag", null, new Exception( "mock cause" ) );
validateRestConfError("mock error-message", ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE, "mock app-tag",
new Contains("mock cause"), new RestconfError(rpcError));
// Some fields set - expect error-info set to ErrorSeverity
- rpcError = getRpcError(null, ErrorTag.ACCESS_DENIED.getTagValue(), null, RpcError.ErrorSeverity.ERROR, null,
- RpcError.ErrorType.RPC, null);
+ rpcError = RpcResultBuilder.newError(
+ RpcError.ErrorType.RPC, ErrorTag.ACCESS_DENIED.getTagValue(), null, null, null, null );
validateRestConfError(null, ErrorType.RPC, ErrorTag.ACCESS_DENIED, null, "<severity>error</severity>",
new RestconfError(rpcError));
// 'tag' field not mapped to ErrorTag - expect error-tag set to
// OPERATION_FAILED
- rpcError = getRpcError(null, "not mapped", null, RpcError.ErrorSeverity.WARNING, null,
- RpcError.ErrorType.TRANSPORT, null);
+ rpcError = RpcResultBuilder.newWarning(
+ RpcError.ErrorType.TRANSPORT, "not mapped", null, null, null, null );
validateRestConfError(null, ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED, null,
"<severity>warning</severity>", new RestconfError(rpcError));
// No fields set - edge case
- rpcError = getRpcError(null, null, null, null, null, null, null);
+ rpcError = RpcResultBuilder.newError( null, null, null, null, null, null );
- validateRestConfError(null, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, null, (String) null,
- new RestconfError(rpcError));
+ validateRestConfError( null, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED,
+ null, "<severity>error</severity>", new RestconfError( rpcError ) );
}
private void validateRestConfError(String expectedMessage, ErrorType expectedErrorType, ErrorTag expectedErrorTag,
--- /dev/null
+module opendaylight-test-routed-rpc {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:rpc:routing";
+ prefix "rpc";
+ import yang-ext { prefix ext; }
+
+ description
+ "Test model for testing of registering rpc service on binding independent mount point
+ and retrieving rpc service via binding aware mount point.";
+
+ revision "2014-07-01" {
+ description
+ "Initial revision";
+ }
+
+ identity test-context {
+ description "Test Context";
+ }
+
+ typedef encapsulated-route {
+ type instance-identifier;
+ }
+
+ grouping route-in-grouping {
+ leaf route {
+ type instance-identifier;
+ ext:context-reference test-context;
+ }
+ }
+
+ grouping encapsulated-route-in-grouping {
+ leaf route {
+ type encapsulated-route;
+ ext:context-reference test-context;
+ }
+ }
+
+ rpc routed-simple-route {
+ input {
+ leaf route {
+ type instance-identifier;
+ ext:context-reference test-context;
+ }
+ }
+ }
+}
package org.opendaylight.controller.sample.kitchen.impl;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+
import org.opendaylight.controller.config.yang.config.kitchen_service.impl.KitchenServiceRuntimeMXBean;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sample.kitchen.api.EggsType;
import org.opendaylight.controller.sample.kitchen.api.KitchenService;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
return Futures.immediateFuture(
- Rpcs.<Void> getRpcResult( atLeastOneSucceeded, errorList.build() ) );
+ RpcResultBuilder.<Void> status( atLeastOneSucceeded )
+ .withRpcErrors( errorList.build() ).build() );
}
} );
}
public RpcResult<Void> call() throws Exception {
// We don't actually do anything here - just return a successful result.
- return Rpcs.<Void> getRpcResult( true, Collections.<RpcError>emptyList() );
+ return RpcResultBuilder.<Void> success().build();
}
} );
}
if( toasterOutOfBread )
{
log.info( "We're out of toast but we can make eggs" );
- return Futures.immediateFuture( Rpcs.<Void> getRpcResult( true,
- Arrays.asList( RpcErrors.getRpcError( "", "partial-operation", null,
- ErrorSeverity.WARNING,
- "Toaster is out of bread but we can make you eggs",
- ErrorType.APPLICATION, null ) ) ) );
+ return Futures.immediateFuture( RpcResultBuilder.<Void> success()
+ .withWarning( ErrorType.APPLICATION, "partial-operation",
+ "Toaster is out of bread but we can make you eggs" ).build() );
}
// Access the ToasterService to make the toast.
*/
package org.opendaylight.controller.sample.toaster.provider;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.DisplayString;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.RestockToasterInput;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
}
// Always return success from the cancel toast call.
- return Futures.immediateFuture( Rpcs.<Void> getRpcResult( true,
- Collections.<RpcError>emptyList() ) );
+ return Futures.immediateFuture( RpcResultBuilder.<Void> success().build() );
}
/**
return futureResult;
}
- private List<RpcError> makeToasterOutOfBreadError() {
- return Arrays.asList(
- RpcErrors.getRpcError( "out-of-stock", "resource-denied", null, null,
- "Toaster is out of bread",
- ErrorType.APPLICATION, null ) );
+ private RpcError makeToasterOutOfBreadError() {
+ return RpcResultBuilder.newError( ErrorType.APPLICATION, "resource-denied",
+ "Toaster is out of bread", "out-of-stock", null, null );
}
- private List<RpcError> makeToasterInUseError() {
- return Arrays.asList(
- RpcErrors.getRpcError( "", "in-use", null, ErrorSeverity.WARNING,
- "Toaster is busy", ErrorType.APPLICATION, null ) );
+ private RpcError makeToasterInUseError() {
+ return RpcResultBuilder.newWarning( ErrorType.APPLICATION, "in-use",
+ "Toaster is busy", null, null, null );
}
private void checkStatusAndMakeToast( final MakeToastInput input,
if( outOfBread() ) {
LOG.debug( "Toaster is out of bread" );
- return Futures.immediateFuture( Rpcs.<TransactionStatus>getRpcResult(
- false, null, makeToasterOutOfBreadError() ) );
+ return Futures.immediateFuture( RpcResultBuilder.<TransactionStatus>failed()
+ .withRpcError( makeToasterOutOfBreadError() ).build() );
}
LOG.debug( "Setting Toaster status to Down" );
// Return an error since we are already making toast. This will get
// propagated to the commitFuture below which will interpret the null
// TransactionStatus in the RpcResult as an error condition.
- return Futures.immediateFuture( Rpcs.<TransactionStatus>getRpcResult(
- false, null, makeToasterInUseError() ) );
+ return Futures.immediateFuture( RpcResultBuilder.<TransactionStatus>failed()
+ .withRpcError( makeToasterInUseError() ).build() );
}
} );
// the read above returned ToasterStatus.Down. Either way, fail the
// futureResult and copy the errors.
- futureResult.set( Rpcs.<Void>getRpcResult( false, null, result.getErrors() ) );
+ futureResult.set( RpcResultBuilder.<Void>failed().withRpcErrors(
+ result.getErrors() ).build() );
}
}
LOG.error( "Failed to commit Toaster status", ex );
// Got some unexpected error so fail.
- futureResult.set( Rpcs.<Void> getRpcResult( false, null, Arrays.asList(
- RpcErrors.getRpcError( null, null, null, ErrorSeverity.ERROR,
- ex.getMessage(),
- ErrorType.APPLICATION, ex ) ) ) );
+ futureResult.set( RpcResultBuilder.<Void> failed()
+ .withError( ErrorType.APPLICATION, ex.getMessage() ).build() );
}
}
} );
notificationProvider.publish( reStockedNotification );
}
- return Futures.immediateFuture(Rpcs.<Void> getRpcResult(true, Collections.<RpcError>emptyList()));
+ return Futures.immediateFuture( RpcResultBuilder.<Void> success().build() );
}
/**
LOG.debug("Toast done");
- futureResult.set( Rpcs.<Void>getRpcResult( true, null,
- Collections.<RpcError>emptyList() ) );
+ futureResult.set( RpcResultBuilder.<Void>success().build() );
return null;
}
}
private State state = State.IDLE;
+ private final Promise<S> promise;
private final Timer timer;
private final long connectionTimeoutMillis;
L sessionListener, long connectionTimeoutMillis) {
super(promise, channel);
this.sessionPreferences = sessionPreferences;
+ this.promise = promise;
this.timer = timer;
this.sessionListener = sessionListener;
this.connectionTimeoutMillis = connectionTimeoutMillis;
channel.pipeline().addLast(NAME_OF_EXCEPTION_HANDLER, new ExceptionHandlingInboundChannelHandler());
+ // FIXME, make sessionPreferences return HelloMessage, move NetconfHelloMessage to API
+ sendMessage((NetconfHelloMessage)helloMessage);
+
+ replaceHelloMessageOutboundHandler();
+ changeState(State.OPEN_WAIT);
+
timeout = this.timer.newTimeout(new TimerTask() {
@Override
public void run(final Timeout timeout) {
synchronized (this) {
if (state != State.ESTABLISHED) {
+
logger.debug("Connection timeout after {}, session is in state {}", timeout, state);
- final IllegalStateException cause = new IllegalStateException(
- "Session was not established after " + timeout);
- negotiationFailed(cause);
+
+ // Do not fail negotiation if promise is done or canceled
+ // It would result in setting result of the promise second time and that throws exception
+ if (isPromiseFinished() == false) {
+ // FIXME BUG-1365 calling "negotiation failed" closes the channel, but the channel does not get closed if data is still being transferred
+ // Loopback connection initiation might
+ negotiationFailed(new IllegalStateException("Session was not established after " + timeout));
+ }
+
changeState(State.FAILED);
} else if(channel.isOpen()) {
channel.pipeline().remove(NAME_OF_EXCEPTION_HANDLER);
}
}
}
- }, connectionTimeoutMillis, TimeUnit.MILLISECONDS);
- // FIXME, make sessionPreferences return HelloMessage, move NetconfHelloMessage to API
- sendMessage((NetconfHelloMessage)helloMessage);
+ private boolean isPromiseFinished() {
+ return promise.isDone() || promise.isCancelled();
+ }
- replaceHelloMessageOutboundHandler();
- changeState(State.OPEN_WAIT);
+ }, connectionTimeoutMillis, TimeUnit.MILLISECONDS);
}
private void cancelTimeout() {
<module>opendaylight/dummy-console</module>
<module>opendaylight/karaf-branding</module>
<module>opendaylight/distribution/opendaylight-karaf</module>
+ <module>features</module>
</modules>
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>