From: Tony Tkacik Date: Tue, 13 May 2014 13:52:24 +0000 (+0000) Subject: Merge "Bug 809: Enhancements to the toaster example" X-Git-Tag: autorelease-tag-v20140601202136_82eb3f9~96 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=e159106bc148e76fc1e3e3c780bdd740d99e74ed;hp=0453a062c587b03363c35e7989294b0933bb9895 Merge "Bug 809: Enhancements to the toaster example" --- diff --git a/opendaylight/appauth/pom.xml b/opendaylight/appauth/pom.xml index f07c855877..e74e3cb915 100644 --- a/opendaylight/appauth/pom.xml +++ b/opendaylight/appauth/pom.xml @@ -35,7 +35,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true @@ -48,7 +47,6 @@ org.apache.felix.dm, org.opendaylight.controller.appauth, org.opendaylight.controller.appauth.authorization - diff --git a/opendaylight/arphandler/pom.xml b/opendaylight/arphandler/pom.xml index 8d62c1da4b..064d04c25c 100644 --- a/opendaylight/arphandler/pom.xml +++ b/opendaylight/arphandler/pom.xml @@ -50,7 +50,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/clustering/services/pom.xml b/opendaylight/clustering/services/pom.xml index 3806421df8..3ff6bac21f 100644 --- a/opendaylight/clustering/services/pom.xml +++ b/opendaylight/clustering/services/pom.xml @@ -24,7 +24,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheConfigException.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheConfigException.java index 32c3d08c91..e030142016 100644 --- a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheConfigException.java +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheConfigException.java @@ -24,6 +24,7 @@ package org.opendaylight.controller.clustering.services; * passed and so on. */ public class CacheConfigException extends Exception { + private static final long serialVersionUID = 1L; /** * Instantiates a new cache config exception. diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheExistException.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheExistException.java index 583de7cb50..70165cce1f 100644 --- a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheExistException.java +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheExistException.java @@ -23,6 +23,7 @@ package org.opendaylight.controller.clustering.services; * allocated already exists */ public class CacheExistException extends Exception { + private static final long serialVersionUID = 1L; /** * Instantiates a new cache exist exception. diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheListenerAddException.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheListenerAddException.java index 34ba41c5d4..996e0a0767 100644 --- a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheListenerAddException.java +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/CacheListenerAddException.java @@ -21,6 +21,7 @@ package org.opendaylight.controller.clustering.services; * Listener being added fails for any reason */ public class CacheListenerAddException extends Exception { + private static final long serialVersionUID = 1L; /** * Instantiates a new cache listener add exception. diff --git a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ListenRoleChangeAddException.java b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ListenRoleChangeAddException.java index 523a1340c5..dd2585b17e 100644 --- a/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ListenRoleChangeAddException.java +++ b/opendaylight/clustering/services/src/main/java/org/opendaylight/controller/clustering/services/ListenRoleChangeAddException.java @@ -20,7 +20,9 @@ package org.opendaylight.controller.clustering.services; * @deprecated for internal use * The Class ListenRoleChangeAddException. */ +@Deprecated public class ListenRoleChangeAddException extends Exception { + private static final long serialVersionUID = 1L; /** * Instantiates a new listen role change add exception. diff --git a/opendaylight/clustering/services_implementation/pom.xml b/opendaylight/clustering/services_implementation/pom.xml index 4acfae0d29..8d3f53b6c4 100644 --- a/opendaylight/clustering/services_implementation/pom.xml +++ b/opendaylight/clustering/services_implementation/pom.xml @@ -63,7 +63,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true @@ -75,9 +74,8 @@ !org.hornetq.*, !org.jboss.*, javax.transaction, - *, org.opendaylight.controller.clustering.services, - org.opendaylight.controller.sal.core + org.opendaylight.controller.sal.core,* org.opendaylight.controller.clustering.services_implementation.internal.Activator diff --git a/opendaylight/clustering/stub/pom.xml b/opendaylight/clustering/stub/pom.xml index 7a0c1378b6..6a0b3082fb 100644 --- a/opendaylight/clustering/stub/pom.xml +++ b/opendaylight/clustering/stub/pom.xml @@ -31,7 +31,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/clustering/test/pom.xml b/opendaylight/clustering/test/pom.xml index 02a231b78c..9021c9419e 100644 --- a/opendaylight/clustering/test/pom.xml +++ b/opendaylight/clustering/test/pom.xml @@ -60,7 +60,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass.java index 076ec05e32..51f8128382 100644 --- a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass.java +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass.java @@ -12,6 +12,7 @@ package org.opendaylight.controller.clustering.test.internal; import java.io.Serializable; public class ComplexClass implements IComplex, Serializable { + private static final long serialVersionUID = 1L; private String identity; public ComplexClass(String i) { diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass1.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass1.java index fda2ff10aa..876fb656ac 100644 --- a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass1.java +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexClass1.java @@ -12,6 +12,7 @@ package org.opendaylight.controller.clustering.test.internal; import java.io.Serializable; public class ComplexClass1 implements IComplex, Serializable { + private static final long serialVersionUID = 1L; private String identity; public ComplexClass1(String i) { diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexContainer.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexContainer.java index adc062d4c4..d07c192241 100644 --- a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexContainer.java +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/ComplexContainer.java @@ -12,9 +12,10 @@ package org.opendaylight.controller.clustering.test.internal; import java.io.Serializable; public class ComplexContainer implements Serializable { - private IComplex f; - private IComplex f1; - private Integer state; + private static final long serialVersionUID = 1L; + private final IComplex f; + private final IComplex f1; + private final Integer state; public ComplexContainer(String i, Integer s) { this.state = s; diff --git a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/StringContainer.java b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/StringContainer.java index 39ef1b0e29..7cdb032988 100644 --- a/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/StringContainer.java +++ b/opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/StringContainer.java @@ -12,6 +12,7 @@ package org.opendaylight.controller.clustering.test.internal; import java.io.Serializable; public class StringContainer implements Serializable { + private static final long serialVersionUID = 1L; private String mystring; public StringContainer() { diff --git a/opendaylight/commons/concepts/pom.xml b/opendaylight/commons/concepts/pom.xml index de263cb41f..01dd61a1cb 100644 --- a/opendaylight/commons/concepts/pom.xml +++ b/opendaylight/commons/concepts/pom.xml @@ -23,7 +23,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/commons/httpclient/pom.xml b/opendaylight/commons/httpclient/pom.xml index f068fded4e..07d3cdda96 100644 --- a/opendaylight/commons/httpclient/pom.xml +++ b/opendaylight/commons/httpclient/pom.xml @@ -38,7 +38,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index 4a7a395693..aaab66d4b0 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -15,44 +15,71 @@ + 1.0.0 + 0.4.2-SNAPSHOT + 0.5.2-SNAPSHOT - 2.3.7 + 4.1 + + 1.50 + 2.4.0 0.4.2-SNAPSHOT 2.10 0.5.1-SNAPSHOT 0.4.3-SNAPSHOT 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT + + 1.7 + 1.2.2 0.1.2-SNAPSHOT 2.4 3.1 + 3.0.1 2.3.2 0.5.2-SNAPSHOT 0.2.5-SNAPSHOT + 0.4.3-SNAPSHOT 0.4.3-SNAPSHOT 0.1.2-SNAPSHOT 0.5.2-SNAPSHOT + 0.4.2-SNAPSHOT 0.5.2-SNAPSHOT - + 0.0.2-SNAPSHOT 7.0.42 + 0.4.2-SNAPSHOT + 2.5.0 1.3.1 - 1.26.2 + 1.28 3.0.0 - 0000.0002.0038.0-SNAPSHOT + 0000.0002.0038.0 2.15 + 1.0.1 + 3.0.1 + 3.1.0 + 3.1.6 + 4.2.0 + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT 0.5.2-SNAPSHOT + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT 0.6.0-SNAPSHOT 2.2.0.RELEASE + 2.2.4 14.0.1 0.5.2-SNAPSHOT 0.5.2-SNAPSHOT + 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT 2010.09.24.4-SNAPSHOT 2013.10.21.2-SNAPSHOT 2010.09.24.4-SNAPSHOT - 2.3.0 + 2.3.2 0.6.2.201302030002 2.4 1.7 @@ -61,9 +88,13 @@ 1.17 1.17 + 1.3.3 src/main/yang-gen-config 1.1.4 + 2.0.1 + 1.1.1 4.8.1 + 3.0.1 1.0.9 0.4.2-SNAPSHOT 2.5.1 @@ -75,24 +106,35 @@ 0.2.5-SNAPSHOT 4.0.17.Final 0.0.3-SNAPSHOT + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT http://nexus.opendaylight.org/content 2013.08.27.4-SNAPSHOT + 20080701 + 0.0.2-SNAPSHOT + 5.0.0 5.0.0 UTF-8 UTF-8 2.6 - 1.0-alpha-2 0.5.0-SNAPSHOT - 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT 2.3.2 + 0.4.2-SNAPSHOT 0.1.2-SNAPSHOT + 0.4.2-SNAPSHOT 0.0.3-SNAPSHOT 0.8.1-SNAPSHOT src/main/yang-gen-sal 0.5.2-SNAPSHOT + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT dav:http://nexus.opendaylight.org/content/sites/site 3.2 1.7.2 @@ -102,17 +144,30 @@ jacoco java org.openflow.openflowj,net.sf.jung2 + 1.0.0 1.2.1 + 3.1.4.RELEASE 3.1.3.RELEASE 3.1.3.RELEASE + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT 0.5.1-SNAPSHOT + 0.4.2-SNAPSHOT 2.15 0.7.1-SNAPSHOT + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT -Xmx1024m -XX:MaxPermSize=256m + 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT + 0.4.2-SNAPSHOT 1.5.0 + 0.4.2-SNAPSHOT + 0.0.2-SNAPSHOT 0.4.2-SNAPSHOT 3.6.0.RELEASE + 0.4.2-SNAPSHOT src/main/xtend-gen 2.4.3 2013.09.07.4-SNAPSHOT @@ -142,37 +197,37 @@ logback-core ${logback.version} - com.fasterxml.jackson.core jackson-annotations ${jackson.version} - com.fasterxml.jackson.core jackson-core ${jackson.version} - com.fasterxml.jackson.core jackson-databind ${jackson.version} + + com.fasterxml.jackson.datatype + jackson-datatype-json-org + ${jackson.version} + com.fasterxml.jackson.jaxrs jackson-jaxrs-base ${jackson.version} - com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider ${jackson.version} - com.fasterxml.jackson.module jackson-module-jaxb-annotations @@ -181,12 +236,12 @@ com.google.code.findbugs jsr305 - 2.0.1 + ${jsr305.api.version} com.google.code.gson gson - 2.2.4 + ${gson.version} com.google.guava @@ -212,12 +267,12 @@ commons-codec commons-codec - 1.7 + ${commons.codec.version} commons-fileupload commons-fileupload - 1.2.2 + ${commons.fileupload.version} commons-io @@ -227,7 +282,7 @@ commons-net commons-net - 3.0.1 + ${commons.net.version} eclipselink @@ -370,8 +425,7 @@ netty-common ${netty.version} - - + io.netty netty-handler @@ -382,6 +436,11 @@ netty-transport ${netty.version} + + javax.ws.rs + jsr311-api + ${jsr311.api.version} + orbit javax.activation @@ -470,7 +529,7 @@ org.aopalliance com.springsource.org.aopalliance - 1.0.0 + ${aopalliance.version} org.apache.commons @@ -480,46 +539,45 @@ org.apache.felix org.apache.felix.dependencymanager - 3.1.0 + ${felix.dependencymanager.version} org.apache.felix org.apache.felix.dependencymanager.shell - 3.0.1 + ${felix.dependencymanager.shell.version} org.apache.felix org.apache.felix.fileinstall - 3.1.6 + ${felix.fileinstall.version} org.apache.felix org.apache.felix.webconsole - 4.2.0 + ${felix.webconsole.version} all org.bouncycastle bcpkix-jdk15on - 1.50 + ${bouncycastle.version} org.bouncycastle bcprov-jdk15on - 1.50 + ${bouncycastle.version} org.codehaus.enunciate enunciate-core-annotations ${enunciate.version} - org.codehaus.jettison jettison - 1.3.3 + ${jettison.version} @@ -531,17 +589,17 @@ org.eclipse.persistence org.eclipse.persistence.antlr - 2.5.0 + ${eclipse.persistence.version} org.eclipse.persistence org.eclipse.persistence.core - 2.5.0 + ${eclipse.persistence.version} org.eclipse.persistence org.eclipse.persistence.moxy - 2.5.0 + ${eclipse.persistence.version} @@ -565,10 +623,15 @@ jolokia-osgi ${jolokia.version} + + org.json + json + ${org.json.version} + org.opendaylight.controller appauth - 0.4.2-SNAPSHOT + ${appauth.version} org.opendaylight.controller @@ -605,7 +668,7 @@ org.opendaylight.controller clustering.test - 0.4.2-SNAPSHOT + ${clustering.test.version} org.opendaylight.controller @@ -617,7 +680,7 @@ org.opendaylight.controller commons.northbound - 0.4.2-SNAPSHOT + ${commmons.northbound.version} org.opendaylight.controller @@ -693,7 +756,7 @@ org.opendaylight.controller configuration.implementation - 0.4.3-SNAPSHOT + ${configuration.implementation.version} org.opendaylight.controller @@ -728,27 +791,27 @@ org.opendaylight.controller containermanager.northbound - 0.4.2-SNAPSHOT + ${containermanager.northbound.version} org.opendaylight.controller controllermanager.northbound - 0.0.2-SNAPSHOT + ${controllermanager.northbound.version} org.opendaylight.controller devices.web - 0.4.2-SNAPSHOT + ${devices.web.version} org.opendaylight.controller flowprogrammer.northbound - 0.4.2-SNAPSHOT + ${flowprogrammer.northbound.version} org.opendaylight.controller flows.web - 0.4.2-SNAPSHOT + ${flows.web.version} org.opendaylight.controller @@ -758,7 +821,7 @@ org.opendaylight.controller forwarding.staticrouting.northbound - 0.4.2-SNAPSHOT + ${forwarding.staticrouting.northbound.version} org.opendaylight.controller @@ -768,7 +831,7 @@ org.opendaylight.controller forwardingrulesmanager.implementation - 0.4.2-SNAPSHOT + ${forwardingrulesmanager.implementation.version} @@ -784,7 +847,7 @@ org.opendaylight.controller hosttracker.northbound - 0.4.2-SNAPSHOT + ${hosttracker.northbound.version} org.opendaylight.controller @@ -824,6 +887,13 @@ netconf-client ${netconf.version} + + + + org.opendaylight.controller + netconf-config-dispatcher + ${netconf.version} + org.opendaylight.controller netconf-impl @@ -897,22 +967,22 @@ org.opendaylight.controller networkconfig.neutron - 0.4.2-SNAPSHOT + ${networkconfig.neutron.version} org.opendaylight.controller networkconfig.neutron.implementation - 0.4.2-SNAPSHOT + ${networkconfig.neutron.implementation.version} org.opendaylight.controller networkconfig.neutron.northbound - 0.4.2-SNAPSHOT + ${networkconfig.neutron.northbound.version} org.opendaylight.controller osgi-brandfragment.web - 0.0.2-SNAPSHOT + ${osgi-brandfragment.web.version} @@ -925,17 +995,17 @@ org.opendaylight.controller protocol_plugins.openflow - 0.4.2-SNAPSHOT + ${protocol_plugins.openflow.version} org.opendaylight.controller protocol_plugins.stub - ${protocol_plugin.stub.version} + ${protocol_plugins.stub.version} org.opendaylight.controller routing.dijkstra_implementation - 0.4.2-SNAPSHOT + ${routing.dijkstra_implementation.version} @@ -1029,6 +1099,11 @@ sal-rest-connector ${mdsal.version} + + org.opendaylight.controller + sal-rest-docgen + ${mdsal.version} + org.opendaylight.controller sal-restconf-broker @@ -1049,7 +1124,7 @@ org.opendaylight.controller sal.implementation - 0.4.2-SNAPSHOT + ${sal.implementation.version} org.opendaylight.controller @@ -1071,12 +1146,12 @@ org.opendaylight.controller samples.loadbalancer.northbound - 0.4.2-SNAPSHOT + ${samples.loadbalancer.northbound.version} org.opendaylight.controller samples.simpleforwarding - 0.4.2-SNAPSHOT + ${samples.simpleforwarding.version} org.opendaylight.controller @@ -1086,7 +1161,7 @@ org.opendaylight.controller security - 0.4.2-SNAPSHOT + ${security.version} @@ -1102,7 +1177,7 @@ org.opendaylight.controller statistics.northbound - 0.4.2-SNAPSHOT + ${statistics.northbound.version} org.opendaylight.controller @@ -1112,12 +1187,12 @@ org.opendaylight.controller statisticsmanager.implementation - 0.4.2-SNAPSHOT + ${statisticsmanager.implementation.version} org.opendaylight.controller subnets.northbound - 0.4.2-SNAPSHOT + ${subnets.northbound.version} org.opendaylight.controller @@ -1127,12 +1202,12 @@ org.opendaylight.controller switchmanager.implementation - 0.4.2-SNAPSHOT + ${switchmanager.implementation.version} org.opendaylight.controller switchmanager.northbound - 0.4.2-SNAPSHOT + ${switchmanager.northbound.version} @@ -1149,12 +1224,12 @@ org.opendaylight.controller topology.northbound - 0.4.2-SNAPSHOT + ${topology.northbound.version} org.opendaylight.controller topology.web - 0.4.2-SNAPSHOT + ${topology.web.version} org.opendaylight.controller @@ -1164,7 +1239,7 @@ org.opendaylight.controller troubleshoot.web - 0.4.2-SNAPSHOT + ${troubleshoot.web.version} org.opendaylight.controller @@ -1174,19 +1249,19 @@ org.opendaylight.controller usermanager.implementation - ${usermanager.version} + ${usermanager.implementation.version} org.opendaylight.controller usermanager.northbound - 0.0.2-SNAPSHOT + ${usermanager.northbound.version} org.opendaylight.controller web - 0.4.2-SNAPSHOT + ${web.version} org.opendaylight.controller @@ -1264,16 +1339,6 @@ ganymed 1.1-SNAPSHOT - - org.opendaylight.controller.thirdparty - nagasena - ${exi.nagasena.version} - - - org.opendaylight.controller.thirdparty - nagasena-rta - ${exi.nagasena.version} - org.opendaylight.controller.thirdparty @@ -1367,6 +1432,11 @@ yang-model-util ${yangtools.version} + + org.opendaylight.yangtools + yang-parser-api + ${yangtools.version} + org.opendaylight.yangtools yang-parser-impl @@ -1403,10 +1473,20 @@ yang-ext ${yang-ext.version} + + org.openexi + nagasena + ${exi.nagasena.version} + + + org.openexi + nagasena-rta + ${exi.nagasena.version} + org.osgi org.osgi.compendium - ${osgi.core.version} + ${osgi.compendium.version} org.osgi @@ -1693,6 +1773,11 @@ enunciate.xml + + org.codehaus.enunciate + enunciate-swagger + ${enunciate.version} + org.opendaylight.controller commons.logback_settings @@ -1720,6 +1805,7 @@ generate-sources + src/main/yang ${jmxGeneratorPath} ${salGeneratorPath} ${xtend.dstdir} @@ -1816,7 +1902,7 @@ - + diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java index 5e55cddf8e..916ef9a88b 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java @@ -77,9 +77,6 @@ public abstract class AbstractDispatcher, L extends */ protected ChannelFuture createServer(final InetSocketAddress address, final PipelineInitializer initializer) { final ServerBootstrap b = new ServerBootstrap(); - b.group(this.bossGroup, this.workerGroup); - b.channel(NioServerSocketChannel.class); - b.option(ChannelOption.SO_BACKLOG, 128); b.childHandler(new ChannelInitializer() { @Override @@ -87,10 +84,20 @@ public abstract class AbstractDispatcher, L extends initializer.initializeChannel(ch, new DefaultPromise(executor)); } }); - b.childOption(ChannelOption.SO_KEEPALIVE, true); + b.option(ChannelOption.SO_BACKLOG, 128); + b.childOption(ChannelOption.SO_KEEPALIVE, true); customizeBootstrap(b); + if (b.group() == null) { + b.group(bossGroup, workerGroup); + } + try { + b.channel(NioServerSocketChannel.class); + } catch (IllegalStateException e) { + LOG.trace("Not overriding channelFactory on bootstrap {}", b, e); + } + // Bind and start to accept incoming connections. final ChannelFuture f = b.bind(address); LOG.debug("Initiated server {} at {}.", f, address); diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java index d77c9aa962..1148c6bebe 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java @@ -7,12 +7,6 @@ */ package org.opendaylight.controller.config.yang.protocol.framework; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; - import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.api.ConflictingVersionException; @@ -23,6 +17,12 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory; +import javax.management.InstanceAlreadyExistsException; +import javax.management.ObjectName; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + public class NeverReconnectStrategyModuleTest extends AbstractConfigTest { private static final String INSTANCE_NAME = "never-reconect-strategy-factory-impl"; @@ -30,7 +30,7 @@ public class NeverReconnectStrategyModuleTest extends AbstractConfigTest { @Before public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver( + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, new NeverReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory())); } diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java index 24a0e912a3..9beadc4dbb 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java @@ -29,7 +29,7 @@ public class ReconnectImmediatelyStrategyModuleTest extends AbstractConfigTest { @Before public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver( + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, new ReconnectImmediatelyStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory())); } diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java index d051a00a12..a8cdff7119 100644 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java +++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java @@ -7,15 +7,6 @@ */ package org.opendaylight.controller.config.yang.protocol.framework; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.math.BigDecimal; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; - import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.api.ConflictingVersionException; @@ -26,6 +17,14 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory; +import javax.management.InstanceAlreadyExistsException; +import javax.management.ObjectName; +import java.math.BigDecimal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + public class TimedReconnectStrategyModuleTest extends AbstractConfigTest { private static final String INSTANCE_NAME = "timed-reconect-stategy-facotry-impl"; @@ -33,7 +32,7 @@ public class TimedReconnectStrategyModuleTest extends AbstractConfigTest { @Before public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver( + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, new TimedReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory())); } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java index 8c325079d3..bf010bb3a6 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java @@ -9,9 +9,12 @@ package org.opendaylight.controller.config.manager.impl; import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; +/** + * Interface exposing some internal state on top of ServiceReferenceReadableRegistry. This will + * not be exposed via JMX. + */ public interface CloseableServiceReferenceReadableRegistry extends AutoCloseable, ServiceReferenceReadableRegistry { - void close(); } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java index e914162671..8f85972d05 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java @@ -11,8 +11,8 @@ import com.google.common.collect.Maps; import org.opendaylight.controller.config.api.ConflictingVersionException; import org.opendaylight.controller.config.api.ModuleIdentifier; import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule; -import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.ValidationException; +import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; import org.opendaylight.controller.config.api.jmx.CommitStatus; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.dependencyresolver.DestroyedModule; @@ -159,13 +159,24 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe } }; - Map> allCurrentFactories = Collections.unmodifiableMap( + Map> allCurrentFactories = new HashMap<>( resolver.getAllFactories()); + // add all factories that disappeared from SR but are still committed + for (ModuleInternalInfo moduleInternalInfo : currentConfig.getEntries()) { + String name = moduleInternalInfo.getModuleFactory().getImplementationName(); + if (allCurrentFactories.containsKey(name) == false) { + logger.trace("Factory {} not found in SR, using reference from previous commit", name); + allCurrentFactories.put(name, + Maps.immutableEntry(moduleInternalInfo.getModuleFactory(), moduleInternalInfo.getBundleContext())); + } + } + allCurrentFactories = Collections.unmodifiableMap(allCurrentFactories); + // closed by transaction controller ConfigTransactionLookupRegistry txLookupRegistry = new ConfigTransactionLookupRegistry(new TransactionIdentifier( transactionName), factory, allCurrentFactories); - ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry( + SearchableServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry( readableSRRegistry, txLookupRegistry, allCurrentFactories); ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl( @@ -216,16 +227,14 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe // non recoverable from here: try { return secondPhaseCommit(configTransactionController, commitInfo, configTransactionControllerEntry.getValue()); - } catch (Throwable t) { // some libs throw Errors: e.g. + } catch (Error | RuntimeException t) { // some libs throw Errors: e.g. // javax.xml.ws.spi.FactoryFinder$ConfigurationError isHealthy = false; logger.error("Configuration Transaction failed on 2PC, server is unhealthy", t); if (t instanceof RuntimeException) { throw (RuntimeException) t; - } else if (t instanceof Error) { - throw (Error) t; } else { - throw new RuntimeException(t); + throw (Error) t; } } } @@ -344,24 +353,20 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe // register to JMX try { - newModuleJMXRegistrator.registerMBean(newReadableConfigBean, - primaryReadOnlyON); + newModuleJMXRegistrator.registerMBean(newReadableConfigBean, primaryReadOnlyON); } catch (InstanceAlreadyExistsException e) { - throw new IllegalStateException(e); + throw new IllegalStateException("Possible code error, already registered:" + primaryReadOnlyON,e); } - // register to OSGi + // register services to OSGi + Map annotationMapping = configTransactionController.getWritableRegistry().findServiceInterfaces(moduleIdentifier); + BundleContext bc = configTransactionController.getModuleFactoryBundleContext( + entry.getModuleFactory().getImplementationName()); if (osgiRegistration == null) { - ModuleFactory moduleFactory = entry.getModuleFactory(); - if (moduleFactory != null) { - BundleContext bc = configTransactionController. - getModuleFactoryBundleContext(moduleFactory.getImplementationName()); - osgiRegistration = beanToOsgiServiceManager.registerToOsgi(realModule.getClass(), - newReadableConfigBean.getInstance(), entry.getIdentifier(), bc); - } else { - throw new NullPointerException(entry.getIdentifier().getFactoryName() + " ModuleFactory not found."); - } - + osgiRegistration = beanToOsgiServiceManager.registerToOsgi( + newReadableConfigBean.getInstance(), moduleIdentifier, bc, annotationMapping); + } else { + osgiRegistration.updateRegistrations(annotationMapping, bc, instance); } RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator = runtimeRegistrators @@ -369,7 +374,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe ModuleInternalInfo newInfo = new ModuleInternalInfo( entry.getIdentifier(), newReadableConfigBean, osgiRegistration, runtimeBeanRegistrator, newModuleJMXRegistrator, - orderingIdx, entry.isDefaultBean()); + orderingIdx, entry.isDefaultBean(), entry.getModuleFactory(), entry.getBundleContext()); newConfigEntries.put(realModule, newInfo); orderingIdx++; diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java index bc4de5cc15..3e23120182 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java @@ -7,9 +7,25 @@ */ package org.opendaylight.controller.config.manager.impl; +import static java.lang.String.format; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; +import javax.management.DynamicMBean; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanServer; +import javax.management.ObjectName; import org.opendaylight.controller.config.api.DependencyResolver; import org.opendaylight.controller.config.api.ModuleIdentifier; -import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager; @@ -28,25 +44,7 @@ import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; -import javax.management.DynamicMBean; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.MBeanServer; -import javax.management.ObjectName; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - import static com.google.common.base.Preconditions.checkNotNull; -import static java.lang.String.format; - /** * This is a JMX bean representing current transaction. It contains * transaction identifier, unique version and parent version for @@ -82,13 +80,13 @@ class ConfigTransactionControllerImpl implements private final boolean blankTransaction; @GuardedBy("this") - private final ServiceReferenceWritableRegistry writableSRRegistry; + private final SearchableServiceReferenceWritableRegistry writableSRRegistry; public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry, long parentVersion, CodecRegistry codecRegistry, long currentVersion, Map> currentlyRegisteredFactories, MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer, - boolean blankTransaction, ServiceReferenceWritableRegistry writableSRRegistry) { + boolean blankTransaction, SearchableServiceReferenceWritableRegistry writableSRRegistry) { this.txLookupRegistry = txLookupRegistry; String transactionName = txLookupRegistry.getTransactionIdentifier().getName(); this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName); @@ -139,14 +137,16 @@ class ConfigTransactionControllerImpl implements } // add default modules for (ModuleFactory moduleFactory : toBeAdded) { + BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName()); Set defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, - getModuleFactoryBundleContext(moduleFactory.getImplementationName())); + bundleContext); for (Module module : defaultModules) { // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier()); try { boolean defaultBean = true; - putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver, defaultBean); + putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, + dependencyResolver, defaultBean, bundleContext); } catch (InstanceAlreadyExistsException e) { throw new IllegalStateException(e); } @@ -163,21 +163,26 @@ class ConfigTransactionControllerImpl implements } - private synchronized void copyExistingModule( - ModuleInternalInfo oldConfigBeanInfo) - throws InstanceAlreadyExistsException { + private synchronized void copyExistingModule(ModuleInternalInfo oldConfigBeanInfo) throws InstanceAlreadyExistsException { + transactionStatus.checkNotCommitStarted(); transactionStatus.checkNotAborted(); ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getIdentifier(); dependencyResolverManager.assertNotExists(moduleIdentifier); - ModuleFactory moduleFactory = factoriesHolder - .findByModuleName(moduleIdentifier.getFactoryName()); + ModuleFactory moduleFactory; + BundleContext bc; + try { + moduleFactory = factoriesHolder.findByModuleName(moduleIdentifier.getFactoryName()); + bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName()); + } catch (InstanceNotFoundException e) { + throw new IllegalStateException(e); + } Module module; DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier); try { - BundleContext bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName()); + module = moduleFactory.createModule( moduleIdentifier.getInstanceName(), dependencyResolver, oldConfigBeanInfo.getReadableModule(), bc); @@ -187,7 +192,7 @@ class ConfigTransactionControllerImpl implements oldConfigBeanInfo, moduleFactory), e); } putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver, - oldConfigBeanInfo.isDefaultBean()); + oldConfigBeanInfo.isDefaultBean(), bc); } @Override @@ -200,19 +205,26 @@ class ConfigTransactionControllerImpl implements dependencyResolverManager.assertNotExists(moduleIdentifier); // find factory - ModuleFactory moduleFactory = factoriesHolder.findByModuleName(factoryName); + ModuleFactory moduleFactory; + try { + moduleFactory = factoriesHolder.findByModuleName(factoryName); + } catch (InstanceNotFoundException e) { + throw new IllegalArgumentException(e); + } DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier); + BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName()); Module module = moduleFactory.createModule(instanceName, dependencyResolver, - getModuleFactoryBundleContext(moduleFactory.getImplementationName())); + bundleContext); boolean defaultBean = false; return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, - moduleFactory, null, dependencyResolver, defaultBean); + moduleFactory, null, dependencyResolver, defaultBean, bundleContext); } private synchronized ObjectName putConfigBeanToJMXAndInternalMaps( ModuleIdentifier moduleIdentifier, Module module, ModuleFactory moduleFactory, - @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver, boolean isDefaultBean) + @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver, + boolean isDefaultBean, BundleContext bundleContext) throws InstanceAlreadyExistsException { logger.debug("Adding module {} to transaction {}", moduleIdentifier, this); @@ -237,7 +249,7 @@ class ConfigTransactionControllerImpl implements dependencyResolverManager.put( moduleIdentifier, module, moduleFactory, - maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean); + maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean, bundleContext); return writableON; } @@ -263,14 +275,15 @@ class ConfigTransactionControllerImpl implements logger.debug("Destroying module {} in transaction {}", moduleIdentifier, this); transactionStatus.checkNotAborted(); + ModuleInternalTransactionalInfo found = dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier); if (blankTransaction == false) { - ModuleInternalTransactionalInfo found = - dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier); + if (found.isDefaultBean()) { logger.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem"); } } // first remove refNames, it checks for objectname existence + try { writableSRRegistry.removeServiceReferences( ObjectNameUtil.createTransactionModuleON(getTransactionName(), moduleIdentifier)); @@ -570,7 +583,7 @@ class ConfigTransactionControllerImpl implements } @Override - public ServiceReferenceWritableRegistry getWritableRegistry() { + public SearchableServiceReferenceWritableRegistry getWritableRegistry() { return writableSRRegistry; } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java index f6164e3256..c9df3409db 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java @@ -7,17 +7,15 @@ */ package org.opendaylight.controller.config.manager.impl; -import java.util.Collection; -import java.util.List; - -import javax.management.ObjectName; - import org.opendaylight.controller.config.api.ModuleIdentifier; -import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.spi.ModuleFactory; import org.osgi.framework.BundleContext; +import javax.management.ObjectName; +import java.util.Collection; +import java.util.List; + /** * Defines contract between {@link ConfigTransactionControllerImpl} (producer) * and {@link ConfigRegistryImpl} (consumer). @@ -73,7 +71,7 @@ interface ConfigTransactionControllerInternal extends BundleContext getModuleFactoryBundleContext(String factoryName); - ServiceReferenceWritableRegistry getWritableRegistry(); + SearchableServiceReferenceWritableRegistry getWritableRegistry(); TransactionIdentifier getTransactionIdentifier(); diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/DeadlockMonitor.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/DeadlockMonitor.java index ba7ab7fcba..d34a739703 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/DeadlockMonitor.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/DeadlockMonitor.java @@ -6,6 +6,8 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import javax.annotation.concurrent.GuardedBy; +import java.util.Deque; +import java.util.LinkedList; import java.util.concurrent.TimeUnit; public class DeadlockMonitor implements AutoCloseable { @@ -16,7 +18,9 @@ public class DeadlockMonitor implements AutoCloseable { private final TransactionIdentifier transactionIdentifier; private final DeadlockMonitorRunnable thread; @GuardedBy("this") - private ModuleIdentifierWithNanos moduleIdentifierWithNanos = new ModuleIdentifierWithNanos(); + private final Deque moduleIdentifierWithNanosStack = new LinkedList<>(); + @GuardedBy("this") + private ModuleIdentifierWithNanos top = ModuleIdentifierWithNanos.EMPTY; public DeadlockMonitor(TransactionIdentifier transactionIdentifier) { this.transactionIdentifier = transactionIdentifier; @@ -25,7 +29,21 @@ public class DeadlockMonitor implements AutoCloseable { } public synchronized void setCurrentlyInstantiatedModule(ModuleIdentifier currentlyInstantiatedModule) { - this.moduleIdentifierWithNanos = new ModuleIdentifierWithNanos(currentlyInstantiatedModule); + + boolean popping = currentlyInstantiatedModule == null; + if (popping) { + moduleIdentifierWithNanosStack.pop(); + if (moduleIdentifierWithNanosStack.isEmpty()) { + top = ModuleIdentifierWithNanos.EMPTY; + } else { + top = moduleIdentifierWithNanosStack.peekLast(); + } + } else { + ModuleIdentifierWithNanos current = new ModuleIdentifierWithNanos(currentlyInstantiatedModule); + moduleIdentifierWithNanosStack.push(current); + top = current; + } + logger.trace("setCurrentlyInstantiatedModule {}, top {}", currentlyInstantiatedModule, top); } public boolean isAlive() { @@ -52,11 +70,11 @@ public class DeadlockMonitor implements AutoCloseable { public void run() { ModuleIdentifierWithNanos old = new ModuleIdentifierWithNanos(); // null moduleId while (this.isInterrupted() == false) { - ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.moduleIdentifierWithNanos); - if (old.moduleIdentifier == null) { + ModuleIdentifierWithNanos copy = new ModuleIdentifierWithNanos(DeadlockMonitor.this.top); + if (old.moduleIdentifier == null || old.equals(copy) == false) { // started old = copy; - } else if (old.moduleIdentifier != null && old.equals(copy)) { + } else { // is the getInstance() running longer than WARN_AFTER_MILLIS ? long runningTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - copy.nanoTime); if (runningTime > WARN_AFTER_MILLIS) { @@ -78,14 +96,18 @@ public class DeadlockMonitor implements AutoCloseable { } } - private class ModuleIdentifierWithNanos { + + + + private static class ModuleIdentifierWithNanos { + private static ModuleIdentifierWithNanos EMPTY = new ModuleIdentifierWithNanos(); @Nullable private final ModuleIdentifier moduleIdentifier; + private final long nanoTime; private ModuleIdentifierWithNanos() { - moduleIdentifier = null; - nanoTime = System.nanoTime(); + this((ModuleIdentifier)null); } private ModuleIdentifierWithNanos(ModuleIdentifier moduleIdentifier) { @@ -118,5 +140,12 @@ public class DeadlockMonitor implements AutoCloseable { result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32)); return result; } + + @Override + public String toString() { + return "ModuleIdentifierWithNanos{" + + moduleIdentifier + + '}'; + } } } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java index fd6262cb8c..76299e67a2 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java @@ -15,7 +15,9 @@ import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicReada import org.opendaylight.controller.config.manager.impl.jmx.ModuleJMXRegistrator; import org.opendaylight.controller.config.manager.impl.jmx.RootRuntimeBeanRegistratorImpl; import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceManager.OsgiRegistration; +import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.yangtools.concepts.Identifiable; +import org.osgi.framework.BundleContext; /** * Provides metadata about Module from controller to registry. @@ -37,13 +39,15 @@ public class ModuleInternalInfo implements Comparable, private final ModuleJMXRegistrator moduleJMXRegistrator; private final int orderingIdx; private final boolean isDefaultBean; + private final ModuleFactory moduleFactory; + private final BundleContext bundleContext; public ModuleInternalInfo(ModuleIdentifier name, @Nullable DynamicReadableWrapper readableModule, OsgiRegistration osgiRegistration, RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator, ModuleJMXRegistrator moduleJMXRegistrator, int orderingIdx, - boolean isDefaultBean) { + boolean isDefaultBean, ModuleFactory moduleFactory, BundleContext bundleContext) { if (osgiRegistration == null) { throw new IllegalArgumentException( @@ -60,6 +64,8 @@ public class ModuleInternalInfo implements Comparable, this.moduleJMXRegistrator = moduleJMXRegistrator; this.orderingIdx = orderingIdx; this.isDefaultBean = isDefaultBean; + this.moduleFactory = moduleFactory; + this.bundleContext = bundleContext; } public DynamicReadableWrapper getReadableModule() { @@ -120,4 +126,12 @@ public class ModuleInternalInfo implements Comparable, public boolean isDefaultBean() { return isDefaultBean; } + + public ModuleFactory getModuleFactory() { + return moduleFactory; + } + + public BundleContext getBundleContext() { + return bundleContext; + } } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/SearchableServiceReferenceWritableRegistry.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/SearchableServiceReferenceWritableRegistry.java new file mode 100644 index 0000000000..7a41a3bfa2 --- /dev/null +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/SearchableServiceReferenceWritableRegistry.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.manager.impl; + +import java.util.Map; +import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; +import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; + +public interface SearchableServiceReferenceWritableRegistry extends ServiceReferenceWritableRegistry { + /** + * Return mapping between service ref names and service interface annotation for given + * module. + * + * @throws java.lang.IllegalArgumentException if any of service qNames is not found + * @throws java.lang.NullPointerException if parameter is null + */ + Map findServiceInterfaces(ModuleIdentifier moduleIdentifier); + +} diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java index bf35fd1ed8..ceea994154 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java @@ -7,6 +7,17 @@ */ package org.opendaylight.controller.config.manager.impl; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; import org.opendaylight.controller.config.api.LookupRegistry; import org.opendaylight.controller.config.api.ModuleIdentifier; import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; @@ -26,17 +37,7 @@ import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry { +public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, SearchableServiceReferenceWritableRegistry { private static final Logger logger = LoggerFactory.getLogger(ServiceReferenceRegistryImpl.class); private final Map factories; @@ -46,8 +47,11 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe private final ServiceReferenceRegistrator serviceReferenceRegistrator; // helper method for getting QName of SI from namespace + local name private final Map> namespacesToAnnotations; + private final Map serviceQNamesToAnnotations; // all Service Interface qNames for sanity checking private final Set allQNames; + Map> modulesToServiceRef = new HashMap<>(); + // actual reference database private final Map refNames = new HashMap<>(); @@ -124,7 +128,7 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe /** * Static constructor for transaction controller. Take current state as seen by config registry, allow writing new data. */ - public static ServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry, + public static SearchableServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry, ConfigTransactionLookupRegistry txLookupRegistry, Map> currentlyRegisteredFactories) { @@ -198,16 +202,15 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe Map> modifiableFactoryNamesToQNames = new HashMap<>(); Set allAnnotations = new HashSet<>(); Set allQNames = new HashSet<>(); + + for (Entry entry : factories.entrySet()) { if (entry.getKey().equals(entry.getValue().getImplementationName()) == false) { logger.error("Possible error in code: Mismatch between supplied and actual name of {}", entry); throw new IllegalArgumentException("Possible error in code: Mismatch between supplied and actual name of " + entry); } Set siAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(entry.getValue()); - Set qNames = new HashSet<>(); - for (ServiceInterfaceAnnotation sia: siAnnotations) { - qNames.add(sia.value()); - } + Set qNames = InterfacesHelper.getQNames(siAnnotations); allAnnotations.addAll(siAnnotations); allQNames.addAll(qNames); modifiableFactoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames)); @@ -217,6 +220,7 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe // fill namespacesToAnnotations Map> modifiableNamespacesToAnnotations = new HashMap<>(); + Map modifiableServiceQNamesToAnnotations = new HashMap<>(); for (ServiceInterfaceAnnotation sia : allAnnotations) { Map ofNamespace = modifiableNamespacesToAnnotations.get(sia.namespace()); if (ofNamespace == null) { @@ -229,12 +233,21 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe throw new IllegalArgumentException("Conflict between local names in " + sia.namespace() + " : " + sia.localName()); } ofNamespace.put(sia.localName(), sia); + modifiableServiceQNamesToAnnotations.put(sia.value(), sia); } this.namespacesToAnnotations = Collections.unmodifiableMap(modifiableNamespacesToAnnotations); - // copy refNames + this.serviceQNamesToAnnotations = Collections.unmodifiableMap(modifiableServiceQNamesToAnnotations); logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames); } + @Override + public Map findServiceInterfaces(ModuleIdentifier moduleIdentifier) { + Map result = modulesToServiceRef.get(moduleIdentifier); + if (result == null) { + return Collections.emptyMap(); + } + return Collections.unmodifiableMap(result); + } @Override public synchronized Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { @@ -271,7 +284,7 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe public synchronized Map> getServiceMapping() { Map> result = new HashMap<>(); for (Entry entry: refNames.entrySet()) { - String qName = entry.getKey().getServiceInterfaceName(); + String qName = entry.getKey().getServiceInterfaceQName(); Map innerMap = result.get(qName); if (innerMap == null) { innerMap = new HashMap<>(); @@ -379,9 +392,9 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + moduleIdentifier.getFactoryName()); } // supplied serviceInterfaceName must exist in this collection - if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceName()) == false) { - logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames); - throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName() + " within factory " + moduleIdentifier.getFactoryName()); + if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceQName()) == false) { + logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceQName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames); + throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceQName() + " within factory " + moduleIdentifier.getFactoryName()); } @@ -404,6 +417,15 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe } // save to refNames refNames.put(serviceReference, moduleIdentifier); + Map refNamesToAnnotations = modulesToServiceRef.get(moduleIdentifier); + if (refNamesToAnnotations == null){ + refNamesToAnnotations = new HashMap<>(); + modulesToServiceRef.put(moduleIdentifier, refNamesToAnnotations); + } + + ServiceInterfaceAnnotation annotation = serviceQNamesToAnnotations.get(serviceReference.getServiceInterfaceQName()); + checkNotNull(annotation, "Possible error in code, cannot find annotation for " + serviceReference); + refNamesToAnnotations.put(serviceReference.getRefName(), annotation); return result; } @@ -430,9 +452,9 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe private ObjectName getServiceON(ServiceReference serviceReference) { if (writable) { return ObjectNameUtil.createTransactionServiceON(serviceReferenceRegistrator.getNullableTransactionName(), - serviceReference.getServiceInterfaceName(), serviceReference.getRefName()); + serviceReference.getServiceInterfaceQName(), serviceReference.getRefName()); } else { - return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceName(), serviceReference.getRefName()); + return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceQName(), serviceReference.getRefName()); } } @@ -446,13 +468,13 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe logger.debug("Removing service reference {} from {}", serviceReference, this); assertWritable(); // is the qName known? - if (allQNames.contains(serviceReference.getServiceInterfaceName()) == false) { - logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceName(), allQNames); - throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName()); + if (allQNames.contains(serviceReference.getServiceInterfaceQName()) == false) { + logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceQName(), allQNames); + throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceQName()); } ModuleIdentifier removed = refNames.remove(serviceReference); if (removed == null){ - throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceName()); + throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceQName()); } Entry entry = mBeans.remove(serviceReference); if (entry == null) { @@ -475,21 +497,28 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe @Override public synchronized boolean removeServiceReferences(ObjectName moduleObjectName) throws InstanceNotFoundException { + lookupRegistry.checkConfigBeanExists(moduleObjectName); + String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName); + // check that service interface name exist + Set serviceInterfaceQNames = factoryNamesToQNames.get(factoryName); + return removeServiceReferences(moduleObjectName, serviceInterfaceQNames); + } + + + private boolean removeServiceReferences(ObjectName moduleObjectName, Set qNames) throws InstanceNotFoundException { + ObjectNameUtil.checkType(moduleObjectName, ObjectNameUtil.TYPE_MODULE); assertWritable(); - Set serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName); + Set serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName, qNames); for (ServiceReference sr : serviceReferencesLinkingTo) { removeServiceReference(sr); } return serviceReferencesLinkingTo.isEmpty() == false; } - private synchronized Set findServiceReferencesLinkingTo(ObjectName moduleObjectName) throws InstanceNotFoundException { - lookupRegistry.checkConfigBeanExists(moduleObjectName); + private Set findServiceReferencesLinkingTo(ObjectName moduleObjectName, Set serviceInterfaceQNames) { String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName); - // check that service interface name exist - Set serviceInterfaceQNames = factoryNamesToQNames.get(factoryName); if (serviceInterfaceQNames == null) { - logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName); + logger.warn("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName); throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName); } String instanceName = ObjectNameUtil.getInstanceName(moduleObjectName); @@ -503,7 +532,6 @@ public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceRe return result; } - @Override public String toString() { return "ServiceReferenceRegistryImpl{" + diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java index b99bf8330e..0c1531728f 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java @@ -7,8 +7,19 @@ */ package org.opendaylight.controller.config.manager.impl.dependencyresolver; +import static com.google.common.base.Preconditions.checkState; + import com.google.common.reflect.AbstractInvocationHandler; import com.google.common.reflect.Reflection; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.concurrent.GuardedBy; +import javax.management.InstanceAlreadyExistsException; import org.opendaylight.controller.config.api.DependencyResolver; import org.opendaylight.controller.config.api.DependencyResolverFactory; import org.opendaylight.controller.config.api.JmxAttribute; @@ -24,18 +35,7 @@ import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXR import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry; - -import javax.annotation.concurrent.GuardedBy; -import javax.management.InstanceAlreadyExistsException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.google.common.base.Preconditions.checkState; +import org.osgi.framework.BundleContext; /** * Holds information about modules being created and destroyed within this @@ -117,7 +117,7 @@ public class DependencyResolverManager implements DependencyResolverFactory, Aut ModuleFactory moduleFactory, ModuleInternalInfo maybeOldInternalInfo, TransactionModuleJMXRegistration transactionModuleJMXRegistration, - boolean isDefaultBean) { + boolean isDefaultBean, BundleContext bundleContext) { transactionStatus.checkNotCommitted(); Class moduleClass = Module.class; @@ -159,7 +159,7 @@ public class DependencyResolverManager implements DependencyResolverFactory, Aut ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo( moduleIdentifier, proxiedModule, moduleFactory, - maybeOldInternalInfo, transactionModuleJMXRegistration, isDefaultBean, module); + maybeOldInternalInfo, transactionModuleJMXRegistration, isDefaultBean, module, bundleContext); modulesHolder.put(moduleInternalTransactionalInfo); } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/ModuleInternalTransactionalInfo.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/ModuleInternalTransactionalInfo.java index e9f573a05d..13424a60eb 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/ModuleInternalTransactionalInfo.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/ModuleInternalTransactionalInfo.java @@ -16,6 +16,7 @@ import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.yangtools.concepts.Identifiable; import javax.annotation.Nullable; +import org.osgi.framework.BundleContext; public class ModuleInternalTransactionalInfo implements Identifiable { private final ModuleIdentifier name; @@ -25,12 +26,13 @@ public class ModuleInternalTransactionalInfo implements Identifiable result = moduleNamesToConfigBeanFactories.get(moduleName); if (result == null) { - throw new IllegalArgumentException( + throw new InstanceNotFoundException( "ModuleFactory not found with module name: " + moduleName); } return result.getKey(); @@ -73,7 +72,4 @@ public class HierarchicalConfigMBeanFactoriesHolder { return moduleFactories; } - public Map> getModuleNamesToConfigBeanFactories() { - return moduleNamesToConfigBeanFactories; - } } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java index cd74ddf756..3ad35ac5b5 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java @@ -15,7 +15,7 @@ public class ServiceReference { this.refName = refName; } - public String getServiceInterfaceName() { + public String getServiceInterfaceQName() { return serviceInterfaceName; } @@ -50,4 +50,12 @@ public class ServiceReference { result = 31 * result + refName.hashCode(); return result; } + + @Override + public String toString() { + return "ServiceReference{" + + "serviceInterfaceName='" + serviceInterfaceName + '\'' + + ", refName='" + refName + '\'' + + '}'; + } } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java index 41f577844a..fbc7eb6cbe 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BeanToOsgiServiceManager.java @@ -7,109 +7,108 @@ */ package org.opendaylight.controller.config.manager.impl.osgi; -import org.opendaylight.controller.config.api.ModuleIdentifier; -import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; -import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper; -import org.opendaylight.controller.config.spi.Module; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; +import static com.google.common.base.Preconditions.checkState; import java.util.Dictionary; import java.util.HashSet; import java.util.Hashtable; +import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import javax.annotation.concurrent.GuardedBy; +import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Registers instantiated beans as OSGi services and unregisters these services * if beans are destroyed. */ public class BeanToOsgiServiceManager { - // name of properties submitted to osgi - static final String INSTANCE_NAME_OSGI_PROP = "instanceName"; - static final String IMPLEMENTATION_NAME_OSGI_PROP = "implementationName"; + private static final String SERVICE_NAME_OSGI_PROP = "name"; /** * To be called for every created, reconfigured and recreated config bean. * It is expected that before using this method OSGi service registry will * be cleaned from previous registrations. */ - public OsgiRegistration registerToOsgi( - Class configBeanClass, AutoCloseable instance, - ModuleIdentifier moduleIdentifier, BundleContext bundleContext) { - try { - final Set> configuresInterfaces = InterfacesHelper - .getOsgiRegistrationTypes(configBeanClass); - checkInstanceImplementing(instance, configuresInterfaces); - - // bundleContext.registerService blows up with empty 'clazzes' - if (configuresInterfaces.isEmpty() == false) { - final Dictionary propertiesForOsgi = getPropertiesForOsgi(moduleIdentifier); - final ServiceRegistration serviceRegistration = bundleContext - .registerService(classesToNames(configuresInterfaces), instance, propertiesForOsgi); - return new OsgiRegistration(serviceRegistration); - } else { - return new OsgiRegistration(); - } - } catch (IllegalStateException e) { - throw new IllegalStateException( - "Error while registering instance into OSGi Service Registry: " - + moduleIdentifier, e); - } + public OsgiRegistration registerToOsgi(AutoCloseable instance, ModuleIdentifier moduleIdentifier, + BundleContext bundleContext, + Map serviceNamesToAnnotations) { + return new OsgiRegistration(instance, moduleIdentifier, bundleContext, serviceNamesToAnnotations); } - private static String[] classesToNames(Set> cfgs) { - String[] result = new String[cfgs.size()]; - int i = 0; - for (Class cfg : cfgs) { - result[i] = cfg.getName(); - i++; - } + private static Dictionary createProps(String serviceName) { + Hashtable result = new Hashtable<>(); + result.put(SERVICE_NAME_OSGI_PROP, serviceName); return result; } - private void checkInstanceImplementing(AutoCloseable instance, - Set> configures) { - Set> missing = new HashSet<>(); - for (Class requiredIfc : configures) { - if (requiredIfc.isInstance(instance) == false) { - missing.add(requiredIfc); - } - } - if (missing.isEmpty() == false) { - throw new IllegalStateException( - instance.getClass() - + " does not implement following interfaces as announced by " - + ServiceInterfaceAnnotation.class.getName() - + " annotation :" + missing); - } - } - - private static Dictionary getPropertiesForOsgi( - ModuleIdentifier moduleIdentifier) { - Hashtable table = new Hashtable<>(); - table.put(IMPLEMENTATION_NAME_OSGI_PROP, - moduleIdentifier.getFactoryName()); - table.put(INSTANCE_NAME_OSGI_PROP, moduleIdentifier.getInstanceName()); - return table; - } public static class OsgiRegistration implements AutoCloseable { - private final ServiceRegistration serviceRegistration; + private static final Logger logger = LoggerFactory.getLogger(OsgiRegistration.class); - public OsgiRegistration(ServiceRegistration serviceRegistration) { - this.serviceRegistration = serviceRegistration; + @GuardedBy("this") + private AutoCloseable instance; + private final ModuleIdentifier moduleIdentifier; + @GuardedBy("this") + private final Set> serviceRegistrations; + @GuardedBy("this") + private final Map serviceNamesToAnnotations; + + public OsgiRegistration(AutoCloseable instance, ModuleIdentifier moduleIdentifier, + BundleContext bundleContext, + Map serviceNamesToAnnotations) { + this.instance = instance; + this.moduleIdentifier = moduleIdentifier; + this.serviceNamesToAnnotations = serviceNamesToAnnotations; + this.serviceRegistrations = registerToSR(instance, bundleContext, serviceNamesToAnnotations); } - public OsgiRegistration() { - this.serviceRegistration = null; + private static Set> registerToSR(AutoCloseable instance, BundleContext bundleContext, + Map serviceNamesToAnnotations) { + Set> serviceRegistrations = new HashSet<>(); + for (Entry entry : serviceNamesToAnnotations.entrySet()) { + Class requiredInterface = entry.getValue().osgiRegistrationType(); + checkState(requiredInterface.isInstance(instance), instance.getClass().getName() + + " instance should implement " + requiredInterface.getName()); + Dictionary propertiesForOsgi = createProps(entry.getKey()); + ServiceRegistration serviceRegistration = bundleContext + .registerService(requiredInterface.getName(), instance, propertiesForOsgi); + serviceRegistrations.add(serviceRegistration); + } + return serviceRegistrations; } @Override - public void close() { - if (serviceRegistration != null) { - serviceRegistration.unregister(); + public synchronized void close() { + for (ServiceRegistration serviceRegistration : serviceRegistrations) { + try { + serviceRegistration.unregister(); + } catch(IllegalStateException e) { + logger.trace("Cannot unregister {}", serviceRegistration, e); + } } + serviceRegistrations.clear(); } - } + public synchronized void updateRegistrations(Map newAnnotationMapping, + BundleContext bundleContext, AutoCloseable newInstance) { + boolean notEquals = this.instance != newInstance; + notEquals |= newAnnotationMapping.equals(serviceNamesToAnnotations) == false; + if (notEquals) { + // FIXME: changing from old state to new state can be improved by computing the diff + logger.debug("Detected change in service registrations for {}: old: {}, new: {}", moduleIdentifier, + serviceNamesToAnnotations, newAnnotationMapping); + close(); + this.instance = newInstance; + Set> newRegs = registerToSR(instance, bundleContext, newAnnotationMapping); + serviceRegistrations.clear(); + serviceRegistrations.addAll(newRegs); + } + } + } } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java index 033f7222fc..a6e9b1ba96 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java @@ -120,6 +120,13 @@ public class InterfacesHelper { return result; } + public static Set getQNames(Set siAnnotations) { + Set qNames = new HashSet<>(); + for (ServiceInterfaceAnnotation sia: siAnnotations) { + qNames.add(sia.value()); + } + return Collections.unmodifiableSet(qNames); + } public static Set getServiceInterfaceAnnotations(ModuleFactory factory) { Set> implementedServiceIntefaces = Collections.unmodifiableSet(factory.getImplementedServiceIntefaces()); @@ -136,7 +143,7 @@ public class InterfacesHelper { result.add(annotation); } } - return result; + return Collections.unmodifiableSet(result); } static Set> getAllAbstractServiceInterfaceClasses( diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/ConfigRegistryImplTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/ConfigRegistryImplTest.java index 9178dc40d0..7efd3ee030 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/ConfigRegistryImplTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/ConfigRegistryImplTest.java @@ -7,13 +7,6 @@ */ package org.opendaylight.controller.config.manager; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyZeroInteractions; - -import java.lang.management.ManagementFactory; - import org.junit.Test; import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest; import org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl; @@ -25,6 +18,13 @@ import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.lang.management.ManagementFactory; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyZeroInteractions; + public class ConfigRegistryImplTest extends AbstractLockedPlatformMBeanServerTest { private static final Logger logger = LoggerFactory @@ -36,7 +36,7 @@ public class ConfigRegistryImplTest extends BundleContext context = mock(BundleContext.class); ConfigRegistryImpl configRegistry = null; try { - ModuleFactoriesResolver resolver = new HardcodedModuleFactoriesResolver( + ModuleFactoriesResolver resolver = new HardcodedModuleFactoriesResolver(mock(BundleContext.class), factory, factory); configRegistry = new ConfigRegistryImpl(resolver, diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java index 001af7525b..63a37de0c3 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java @@ -8,9 +8,11 @@ package org.opendaylight.controller.config.manager.impl; import com.google.common.base.Preconditions; -import junit.framework.Assert; import org.junit.After; +import org.junit.Before; import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.opendaylight.controller.config.api.jmx.CommitStatus; @@ -26,24 +28,18 @@ import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.management.InstanceAlreadyExistsException; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.RuntimeMBeanException; -import java.io.Closeable; -import java.io.InputStream; import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Dictionary; +import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -69,29 +65,58 @@ public abstract class AbstractConfigTest extends protected ConfigRegistryJMXClient configRegistryClient; protected BaseJMXRegistrator baseJmxRegistrator; protected InternalJMXRegistrator internalJmxRegistrator; - protected BundleContext mockedContext = mock(BundleContext.class); + @Mock + protected BundleContext mockedContext; + @Mock protected ServiceRegistration mockedServiceRegistration; - private static final Logger logger = LoggerFactory.getLogger(AbstractConfigTest.class); + @Before + public void setUpMocks() { + MockitoAnnotations.initMocks(this); + } + // Default handler for OSGi service registration - private static final BundleContextServiceRegistrationHandler noopServiceRegHandler = new BundleContextServiceRegistrationHandler() { + protected static class RecordingBundleContextServiceRegistrationHandler implements BundleContextServiceRegistrationHandler { + private final List registrations = new LinkedList<>(); @Override - public void handleServiceRegistration(Object serviceInstance) {} - }; + public void handleServiceRegistration(Class clazz, Object serviceInstance, Dictionary props) { + + registrations.add(new RegistrationHolder(clazz, serviceInstance, props)); + } + + public List getRegistrations() { + return registrations; + } + + protected static class RegistrationHolder { + protected final Class clazz; + protected final Object instance; + protected final Dictionary props; + + public RegistrationHolder(Class clazz, Object instance, Dictionary props) { + this.clazz = clazz; + this.instance = instance; + this.props = props; + } + } + + } + + protected BundleContextServiceRegistrationHandler currentBundleContextServiceRegistrationHandler; protected BundleContextServiceRegistrationHandler getBundleContextServiceRegistrationHandler(Class serviceType) { - return noopServiceRegHandler; + return currentBundleContextServiceRegistrationHandler; } // this method should be called in @Before protected void initConfigTransactionManagerImpl( ModuleFactoriesResolver resolver) { + final MBeanServer platformMBeanServer = ManagementFactory .getPlatformMBeanServer(); - configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator( - platformMBeanServer); + configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(platformMBeanServer); initBundleContext(); internalJmxRegistrator = new InternalJMXRegistrator(platformMBeanServer); @@ -106,35 +131,14 @@ public abstract class AbstractConfigTest extends throw new RuntimeException(e); } configRegistryClient = new ConfigRegistryJMXClient(platformMBeanServer); + currentBundleContextServiceRegistrationHandler = new RecordingBundleContextServiceRegistrationHandler(); } private void initBundleContext() { - this.mockedServiceRegistration = mock(ServiceRegistration.class); doNothing().when(mockedServiceRegistration).unregister(); - RegisterServiceAnswer answer = new RegisterServiceAnswer(); - - doAnswer(answer).when(mockedContext).registerService(Matchers.any(String[].class), - any(Closeable.class), Matchers.>any()); - doAnswer(answer).when(mockedContext).registerService(Matchers.>any(), any(Closeable.class), - Matchers.>any()); - } - - - public Collection getFilesAsInputStreams(List paths) { - final Collection resources = new ArrayList<>(); - List failedToFind = new ArrayList<>(); - for (String path : paths) { - InputStream resourceAsStream = getClass().getResourceAsStream(path); - if (resourceAsStream == null) { - failedToFind.add(path); - } else { - resources.add(resourceAsStream); - } - } - Assert.assertEquals("Some files were not found", Collections.emptyList(), failedToFind); - - return resources; + doAnswer(answer).when(mockedContext).registerService(Matchers.any(), any(), Matchers.>any()); + doAnswer(answer).when(mockedContext).registerService(Matchers.any(), any(), Matchers.>any()); } @After @@ -161,13 +165,6 @@ public abstract class AbstractConfigTest extends transaction.commit(); } - protected void assertSame(ObjectName oN1, ObjectName oN2) { - assertEquals(oN1.getKeyProperty("instanceName"), - oN2.getKeyProperty("instanceName")); - assertEquals(oN1.getKeyProperty("interfaceName"), - oN2.getKeyProperty("interfaceName")); - } - protected void assertStatus(CommitStatus status, int expectedNewInstances, int expectedRecreatedInstances, int expectedReusedInstances) { assertEquals("New instances mismatch in " + status, expectedNewInstances, status.getNewInstances().size()); @@ -177,25 +174,12 @@ public abstract class AbstractConfigTest extends .size()); } - protected ObjectName createTestConfigBean( - ConfigTransactionJMXClient transaction, String implementationName, - String name) throws InstanceAlreadyExistsException { - return transaction.createModule(implementationName, - name); - } protected void assertBeanCount(int i, String configMXBeanName) { assertEquals(i, configRegistry.lookupConfigBeans(configMXBeanName) .size()); } - protected void assertBeanExists(int count, String moduleName, - String instanceName) { - assertEquals(1, - configRegistry.lookupConfigBeans(moduleName, instanceName) - .size()); - } - /** * * @param configBeanClass @@ -215,7 +199,7 @@ public abstract class AbstractConfigTest extends public static interface BundleContextServiceRegistrationHandler { - void handleServiceRegistration(Object serviceInstance); + void handleServiceRegistration(Class clazz, Object serviceInstance, Dictionary props); } @@ -229,32 +213,40 @@ public abstract class AbstractConfigTest extends Object serviceTypeRaw = args[0]; Object serviceInstance = args[1]; + Dictionary props = (Dictionary) args[2]; if (serviceTypeRaw instanceof Class) { Class serviceType = (Class) serviceTypeRaw; - invokeServiceHandler(serviceInstance, serviceType); + invokeServiceHandler(serviceInstance, serviceType, props); } else if(serviceTypeRaw instanceof String[]) { for (String className : (String[]) serviceTypeRaw) { - try { - Class serviceType = Class.forName(className); - invokeServiceHandler(serviceInstance, serviceType); - } catch (ClassNotFoundException e) { - logger.warn("Not handling service registration of type {} ", className, e); - } + invokeServiceHandler(serviceInstance, className, props); } + } else if (serviceTypeRaw instanceof String) { + invokeServiceHandler(serviceInstance, (String) serviceTypeRaw, props); + } else { + throw new IllegalStateException("Not handling service registration of type, Unknown type" + serviceTypeRaw); + } - } else - logger.debug("Not handling service registration of type {}, Unknown type", serviceTypeRaw); return mockedServiceRegistration; } - private void invokeServiceHandler(Object serviceInstance, Class serviceType) { + public void invokeServiceHandler(Object serviceInstance, String className, Dictionary props) { + try { + Class serviceType = Class.forName(className); + invokeServiceHandler(serviceInstance, serviceType, props); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Not handling service registration of type " + className, e); + } + } + + private void invokeServiceHandler(Object serviceInstance, Class serviceType, Dictionary props) { BundleContextServiceRegistrationHandler serviceRegistrationHandler = getBundleContextServiceRegistrationHandler(serviceType); if (serviceRegistrationHandler != null) { - serviceRegistrationHandler.handleServiceRegistration(serviceType.cast(serviceInstance)); + serviceRegistrationHandler.handleServiceRegistration(serviceType, serviceInstance, props); } } } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java index 09aea0895f..5a3747ee14 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java @@ -11,7 +11,6 @@ import com.google.common.collect.Sets; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator; import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator; @@ -70,7 +69,7 @@ public class ConfigTransactionControllerImplTest extends } }, currentlyRegisteredFactories); - ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry( + SearchableServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry( ServiceReferenceRegistryImpl.createInitialSRLookupRegistry(), txLookupRegistry, currentlyRegisteredFactories); diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionManagerImplTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionManagerImplTest.java index bbb3784b33..9595e60ff6 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionManagerImplTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionManagerImplTest.java @@ -23,7 +23,7 @@ public class ConfigTransactionManagerImplTest extends @Before public void setUp() { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver()); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext)); } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java index 6d0b340cd3..3e7b65e1bd 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java @@ -11,6 +11,7 @@ import com.google.common.collect.ImmutableMap; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; +import org.opendaylight.controller.config.manager.impl.AbstractConfigTest.RecordingBundleContextServiceRegistrationHandler.RegistrationHolder; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBean; import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory; @@ -18,6 +19,7 @@ import org.opendaylight.controller.config.manager.testingservices.parallelapsp.t import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory; import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface; import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory; +import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolIfc; import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import javax.management.Attribute; @@ -27,7 +29,7 @@ import javax.management.JMX; import javax.management.MBeanException; import javax.management.ObjectName; import javax.management.ReflectionException; - +import java.util.List; import java.util.Map; import java.util.Set; @@ -41,6 +43,7 @@ public class ServiceReferenceRegistryImplTest extends AbstractParallelAPSPTest { @Before public void setUp() { super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver( + mockedContext, new TestingFixedThreadPoolModuleFactory(), new TestingParallelAPSPModuleFactory(), new TestingScheduledThreadPoolModuleFactory())); @@ -71,11 +74,19 @@ public class ServiceReferenceRegistryImplTest extends AbstractParallelAPSPTest { // create apsp-parallel createParallelAPSP(transaction1, serviceReference); transaction1.commit(); + // check fixed1 is used ServiceReferenceMXBean serviceReferenceMXBean = JMX.newMXBeanProxy(platformMBeanServer, withoutTransactionName(serviceReference), ServiceReferenceMXBean.class); assertEquals(withoutTransactionName(fixedTPTransactionON), serviceReferenceMXBean.getCurrentImplementation()); checkApspThreadCount(fixedNrOfThreads); + // check OSGi SR + List registrations = + ((RecordingBundleContextServiceRegistrationHandler) currentBundleContextServiceRegistrationHandler).getRegistrations(); + assertEquals(1, registrations.size()); + RegistrationHolder record = registrations.get(0); + assertEquals(TestingThreadPoolIfc.class, record.clazz); + assertEquals(ImmutableMap.of("name","ref"), (Map) record.props); // switch reference to scheduled ConfigTransactionJMXClient transaction2 = configRegistryClient.createTransaction(); diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java index 123e52f675..d5d3823ef0 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java @@ -7,6 +7,14 @@ */ package org.opendaylight.controller.config.manager.impl.dependencyresolver; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; + +import java.util.Arrays; +import java.util.List; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.api.JmxAttribute; @@ -19,15 +27,7 @@ import org.opendaylight.controller.config.manager.impl.TransactionStatus; import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration; import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.spi.ModuleFactory; - -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; +import org.osgi.framework.BundleContext; public class DependencyResolverManagerTest { @@ -101,7 +101,7 @@ public class DependencyResolverManagerTest { moduleFactory, maybeOldInternalInfo, transactionModuleJMXRegistration, - isDefaultBean); + isDefaultBean, mock(BundleContext.class)); } private static Module mockedModule() { diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/factoriesresolver/HardcodedModuleFactoriesResolver.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/factoriesresolver/HardcodedModuleFactoriesResolver.java index 3c2230735e..dd6588f3f6 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/factoriesresolver/HardcodedModuleFactoriesResolver.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/factoriesresolver/HardcodedModuleFactoriesResolver.java @@ -60,10 +60,6 @@ public class HardcodedModuleFactoriesResolver implements ModuleFactoriesResolver } } - public HardcodedModuleFactoriesResolver(ModuleFactory... list) { - this(mockBundleContext(),list); - } - private static BundleContext mockBundleContext() { BundleContext bundleContext = Mockito.mock(BundleContext.class); ServiceRegistration serviceRegistration = mock(ServiceRegistration.class); diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java index 978d375cd2..f42b9559c4 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java @@ -37,7 +37,7 @@ public class DependentWiringTest extends AbstractParallelAPSPTest { @Before public void setUp() { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver( + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, new TestingFixedThreadPoolModuleFactory(), new TestingParallelAPSPModuleFactory())); } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java index 642f526efd..0d4fc91a51 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java @@ -7,12 +7,6 @@ */ package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test; -import java.io.Closeable; -import java.io.IOException; -import java.util.concurrent.Executor; - -import javax.management.ObjectName; - import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; @@ -27,6 +21,11 @@ import org.opendaylight.controller.config.manager.testingservices.threadpool.Tes import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; +import javax.management.ObjectName; +import java.io.Closeable; +import java.io.IOException; +import java.util.concurrent.Executor; + public class MockedDependenciesTest extends AbstractParallelAPSPTest { private final String threadPoolImplementationName = "mockedthreadpool"; @@ -36,7 +35,7 @@ public class MockedDependenciesTest extends AbstractParallelAPSPTest { ClassBasedModuleFactory mockedThreadPoolConfigFactory = new ClassBasedModuleFactory( threadPoolImplementationName, MockedThreadPoolModule.class); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver( + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, new TestingParallelAPSPModuleFactory(), mockedThreadPoolConfigFactory)); } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/test/AbstractScheduledTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/test/AbstractScheduledTest.java index 28fea454fe..340e194801 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/test/AbstractScheduledTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/test/AbstractScheduledTest.java @@ -7,18 +7,17 @@ */ package org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.test; -import static org.junit.Assert.assertEquals; - import org.junit.After; import org.junit.Before; import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory; import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolImpl; -import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool - .TestingScheduledThreadPoolModuleFactory; +import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory; import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory; +import static org.junit.Assert.assertEquals; + public abstract class AbstractScheduledTest extends AbstractConfigTest { protected static final String scheduled1 = "scheduled1"; @@ -26,7 +25,7 @@ public abstract class AbstractScheduledTest extends AbstractConfigTest { public final void setUp() { assertEquals(0, TestingScheduledThreadPoolImpl.getNumberOfCloseMethodCalls()); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver( + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, new TestingScheduledThreadPoolModuleFactory(), new TestingFixedThreadPoolModuleFactory(), new TestingParallelAPSPModuleFactory())); diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/TestingFixedThreadPool.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/TestingFixedThreadPool.java index d5434d2ed5..25125fcd82 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/TestingFixedThreadPool.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/TestingFixedThreadPool.java @@ -53,6 +53,7 @@ public class TestingFixedThreadPool implements TestingThreadPoolIfc, Closeable, @Override public void close() throws IOException { executorService.shutdown(); + allExecutors.remove(executorService); } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/ShutdownTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/ShutdownTest.java new file mode 100644 index 0000000000..e047a1ecca --- /dev/null +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/ShutdownTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.manager.testingservices.threadpool.test; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.doReturn; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; +import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleFactoriesResolver; +import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool; +import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory; +import org.opendaylight.controller.config.spi.ModuleFactory; +import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; +import org.osgi.framework.BundleContext; + +public class ShutdownTest extends AbstractConfigTest { + private final TestingFixedThreadPoolModuleFactory testingFixedThreadPoolModuleFactory = new TestingFixedThreadPoolModuleFactory(); + + @Mock + ModuleFactoriesResolver mockedResolver; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + Map> allFactories = ImmutableMap.of( + testingFixedThreadPoolModuleFactory.getImplementationName(), + Maps.immutableEntry(testingFixedThreadPoolModuleFactory, mockedContext)); + doReturn(allFactories).when(mockedResolver).getAllFactories(); + super.initConfigTransactionManagerImpl(mockedResolver); + } + + + @Test + public void testCreateAndDestroyBeanInSameTransaction() throws Exception { + { + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + SimpleConfigurationTest.createFixedThreadPool(transaction); + transaction.commit(); + } + assertEquals(1, TestingFixedThreadPool.allExecutors.size()); + doReturn(Collections.emptyMap()).when(mockedResolver).getAllFactories(); + { + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); + transaction.commit(); + } + assertEquals(1, TestingFixedThreadPool.allExecutors.size()); + } +} diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java index 9852a45853..97d1c63ed2 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java @@ -56,7 +56,7 @@ import static org.junit.Assert.fail; * dependencies. */ public class SimpleConfigurationTest extends AbstractConfigTest { - private final int numberOfThreads = 5; + private static final int numberOfThreads = 5; private final int numberOfThreads2 = 10; private static final String fixed1 = "fixed1"; private static final List emptyONs = Collections @@ -68,7 +68,7 @@ public class SimpleConfigurationTest extends AbstractConfigTest { @Before public void setUp() { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver( + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, new TestingFixedThreadPoolModuleFactory())); } @@ -96,7 +96,7 @@ public class SimpleConfigurationTest extends AbstractConfigTest { return fixed1names; } - private ObjectName createFixedThreadPool( + static ObjectName createFixedThreadPool( ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException, InstanceNotFoundException { transaction.assertVersion(0, 1); @@ -246,8 +246,7 @@ public class SimpleConfigurationTest extends AbstractConfigTest { // 4, check assertEquals(2, configRegistryClient.getVersion()); - assertEquals(1, TestingFixedThreadPool.allExecutors.size()); - assertTrue(TestingFixedThreadPool.allExecutors.get(0).isShutdown()); + assertEquals(0, TestingFixedThreadPool.allExecutors.size()); // dynamic config should be removed from platform try { @@ -278,7 +277,7 @@ public class SimpleConfigurationTest extends AbstractConfigTest { // commit transaction.commit(); // check that first threadpool is closed - checkThreadPools(2, numberOfThreads2); + checkThreadPools(1, numberOfThreads2); } private void checkThreadPools(int expectedTotalNumberOfExecutors, @@ -308,7 +307,7 @@ public class SimpleConfigurationTest extends AbstractConfigTest { // commit CommitStatus commitStatus = transaction.commit(); // check that new threadpool is created and old one is closed - checkThreadPools(2, numberOfThreads); + checkThreadPools(1, numberOfThreads); CommitStatus expected = new CommitStatus(emptyONs, emptyONs, fixed1List); assertEquals(expected, commitStatus); } @@ -337,6 +336,7 @@ public class SimpleConfigurationTest extends AbstractConfigTest { platformMBeanServer.getMBeanInfo(transaction.getObjectName()); fail(); }catch(InstanceNotFoundException e){ + assertEquals("org.opendaylight.controller:TransactionName=ConfigTransaction-0-1,type=ConfigTransaction", e.getMessage()); } } diff --git a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/PropertiesProvider.java b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/PropertiesProvider.java index 1d4139f885..156fa580ce 100644 --- a/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/PropertiesProvider.java +++ b/opendaylight/config/config-persister-api/src/main/java/org/opendaylight/controller/config/persist/api/PropertiesProvider.java @@ -18,4 +18,7 @@ public interface PropertiesProvider { * @return prefix + key as used in getProperty method. */ String getFullKeyForReporting(String key); + + String getPrefix(); + String getPropertyWithoutPrefix(String fullKey); } diff --git a/opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java b/opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java index 2df07b114c..3d4757b926 100644 --- a/opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java +++ b/opendaylight/config/config-persister-api/src/test/java/org/opendaylight/controller/config/persist/test/PropertiesProviderTest.java @@ -26,4 +26,14 @@ public class PropertiesProviderTest implements PropertiesProvider { public String getFullKeyForReporting(String key) { return null; } + + @Override + public String getPrefix() { + return null; + } + + @Override + public String getPropertyWithoutPrefix(String fullKey) { + return null; + } } diff --git a/opendaylight/config/feature/pom.xml b/opendaylight/config/feature/pom.xml new file mode 100644 index 0000000000..aaf33ccc0f --- /dev/null +++ b/opendaylight/config/feature/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + org.opendaylight.controller + config-subsystem + 0.2.5-SNAPSHOT + + config-features + + pom + + + features.xml + + + + + + + + true + src/main/resources + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + diff --git a/opendaylight/config/feature/src/main/resources/features.xml b/opendaylight/config/feature/src/main/resources/features.xml new file mode 100644 index 0000000000..81972c3661 --- /dev/null +++ b/opendaylight/config/feature/src/main/resources/features.xml @@ -0,0 +1,27 @@ + + + + + odl-config-subsystem + + + + yangtools-concepts + yangtools-binding + yangtools-binding-generator + odl-mdsal-commons + mvn:org.opendaylight.controller/config-api/${project.version} + mvn:org.opendaylight.controller/config-manager/${project.version} + mvn:org.opendaylight.controller/yang-jmx-generator/${project.version} + mvn:org.opendaylight.controller/config-persister-api/${project.version} + mvn:org.opendaylight.controller/config-persister-file-xml-adapter/${project.version} + mvn:org.opendaylight.controller/config-persister-directory-xml-adapter/${project.version} + mvn:org.opendaylight.controller/shutdown-api/${project.version} + mvn:org.opendaylight.controller/shutdown-impl/${project.version} + mvn:org.osgi/org.osgi.core/${osgi.core.version} + wrap:mvn:com.google.guava/guava/${guava.version} + mvn:org.javassist/javassist/${javassist.version} + + \ No newline at end of file diff --git a/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleTest.java b/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleTest.java index 296ce79f6e..d9c9dada62 100644 --- a/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleTest.java +++ b/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleTest.java @@ -35,7 +35,7 @@ public class LogbackModuleTest extends AbstractConfigTest { public void setUp() throws Exception { factory = new LogbackModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory)); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory)); } @Test diff --git a/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleWithInitialConfigurationTest.java b/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleWithInitialConfigurationTest.java index e543f752e1..37bfb6d957 100644 --- a/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleWithInitialConfigurationTest.java +++ b/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackModuleWithInitialConfigurationTest.java @@ -49,7 +49,7 @@ public class LogbackModuleWithInitialConfigurationTest extends AbstractConfigTes public void setUp() throws IOException, ClassNotFoundException { factory = new LogbackModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory)); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory)); } /** diff --git a/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackWithXmlConfigModuleTest.java b/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackWithXmlConfigModuleTest.java index 8149659812..3c21e57f6e 100644 --- a/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackWithXmlConfigModuleTest.java +++ b/opendaylight/config/logback-config/src/test/java/org/opendaylight/controller/config/yang/logback/config/LogbackWithXmlConfigModuleTest.java @@ -42,7 +42,7 @@ public class LogbackWithXmlConfigModuleTest extends AbstractConfigTest { public void setUp() throws JoranException, IOException { factory = new LogbackModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory)); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory)); lc = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); diff --git a/opendaylight/config/netconf-config-dispatcher/pom.xml b/opendaylight/config/netconf-config-dispatcher/pom.xml new file mode 100644 index 0000000000..65ebdaf938 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/pom.xml @@ -0,0 +1,52 @@ + + + + 4.0.0 + + org.opendaylight.controller + config-plugin-parent + 0.2.5-SNAPSHOT + ../config-plugin-parent + + + netconf-config-dispatcher + bundle + + + + ${project.groupId} + config-api + + + ${project.groupId} + netconf-client + ${netconf.version} + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.opendaylight.controller.config.yang.config.netconf, + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.netconf.rev140408, + * + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + + diff --git a/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModule.java b/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModule.java new file mode 100644 index 0000000000..344ef3dec3 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModule.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.config.yang.config.netconf.client.dispatcher; + +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; + +/** +* +*/ +public final class NetconfClientDispatcherModule extends org.opendaylight.controller.config.yang.config.netconf.client.dispatcher.AbstractNetconfClientDispatcherModule + { + + public NetconfClientDispatcherModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public NetconfClientDispatcherModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + NetconfClientDispatcherModule oldModule, java.lang.AutoCloseable oldInstance) { + + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + protected void customValidation(){ + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new NetconfClientDispatcherImpl(getBossThreadGroupDependency(), getWorkerThreadGroupDependency(), getTimerDependency()); + } +} diff --git a/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleFactory.java b/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleFactory.java new file mode 100644 index 0000000000..cfd4ef69a5 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/src/main/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleFactory.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.config.yang.config.netconf.client.dispatcher; + +/** +* +*/ +public class NetconfClientDispatcherModuleFactory extends org.opendaylight.controller.config.yang.config.netconf.client.dispatcher.AbstractNetconfClientDispatcherModuleFactory +{ + + +} diff --git a/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconf-cfg.yang b/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconf-cfg.yang new file mode 100644 index 0000000000..16c2bcb062 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconf-cfg.yang @@ -0,0 +1,31 @@ +// vi: set smarttab et sw=4 tabstop=4: +module odl-netconf-cfg { + + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:netconf"; + prefix "cfg-net"; + + import config { prefix config; revision-date 2013-04-05; } + + description + "This module contains the base YANG definitions for + netconf related services. + + Copyright (c)2013 Cisco Systems, Inc. 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"; + + revision "2014-04-08" { + description + "Initial revision."; + } + + identity netconf-client-dispatcher { + + base "config:service-type"; + config:java-class "org.opendaylight.controller.netconf.client.NetconfClientDispatcher"; + } +} \ No newline at end of file diff --git a/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconfig-client-cfg.yang b/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconfig-client-cfg.yang new file mode 100644 index 0000000000..e00bdeb687 --- /dev/null +++ b/opendaylight/config/netconf-config-dispatcher/src/main/yang/odl-netconfig-client-cfg.yang @@ -0,0 +1,64 @@ +// vi: set smarttab et sw=4 tabstop=4: +module odl-netconfig-client-cfg { + + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher"; + prefix "cfg-net-client"; + + import config { prefix config; revision-date 2013-04-05; } + import odl-netconf-cfg { prefix cfg-net; revision-date 2014-04-08; } + import netty {prefix netty; } + + description + "This module contains the base YANG definitions for + netconf-client-dispatcher implementation. + + Copyright (c)2013 Cisco Systems, Inc. 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"; + + revision "2014-04-08" { + description + "Initial revision."; + } + + identity netconf-client-dispatcher { + base config:module-type; + config:provided-service cfg-net:netconf-client-dispatcher; + config:java-name-prefix NetconfClientDispatcher; + } + + augment "/config:modules/config:module/config:configuration" { + case netconf-client-dispatcher { + when "/config:modules/config:module/config:type = 'netconf-client-dispatcher'"; + + container boss-thread-group { + uses config:service-ref { + refine type { + config:required-identity netty:netty-threadgroup; + } + } + } + + container worker-thread-group { + uses config:service-ref { + refine type { + config:required-identity netty:netty-threadgroup; + } + } + } + + container timer { + uses config:service-ref { + refine type { + config:required-identity netty:netty-timer; + } + } + } + } + } + +} \ No newline at end of file diff --git a/opendaylight/config/netty-config-api/src/main/yang/netty.yang b/opendaylight/config/netty-config-api/src/main/yang/netty.yang index 7cac5ad5bc..e274b058dc 100644 --- a/opendaylight/config/netty-config-api/src/main/yang/netty.yang +++ b/opendaylight/config/netty-config-api/src/main/yang/netty.yang @@ -49,4 +49,12 @@ module netty { base "config:service-type"; config:java-class "io.netty.util.Timer"; } -} \ No newline at end of file + + identity channel-factory { + description + "Configuration wrapper around netty's channel factory"; + + base "config:service-type"; + config:java-class "io.netty.bootstrap.ChannelFactory"; + } +} diff --git a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java index f29895c6d0..e89d82a28f 100644 --- a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java +++ b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java @@ -31,7 +31,7 @@ public class GlobalEventExecutorModuleTest extends AbstractConfigTest { @Before public void setUp() { factory = new GlobalEventExecutorModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory)); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory)); } @Test diff --git a/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java b/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java index 590bd9185e..76134b025c 100644 --- a/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java +++ b/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java @@ -28,7 +28,7 @@ public class NettyThreadgroupModuleTest extends AbstractConfigTest { @Before public void setUp() { factory = new NettyThreadgroupModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory)); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory)); } @Test diff --git a/opendaylight/config/pom.xml b/opendaylight/config/pom.xml index bd2924ad9d..613940144b 100644 --- a/opendaylight/config/pom.xml +++ b/opendaylight/config/pom.xml @@ -38,7 +38,9 @@ yang-test-plugin shutdown-api shutdown-impl + netconf-config-dispatcher config-module-archetype + feature @@ -112,31 +114,6 @@ gmaven-plugin 1.0 - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.opendaylight.yangtools - yang-maven-plugin - [0.5.7-SNAPSHOT,) - - generate-sources - - - - - - - - - - org.opendaylight.yangtools yang-maven-plugin @@ -186,7 +163,6 @@ org.jacoco jacoco-maven-plugin - ${jacoco.version} diff --git a/opendaylight/config/shutdown-impl/src/main/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownServiceImpl.java b/opendaylight/config/shutdown-impl/src/main/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownServiceImpl.java index f9622192fe..4abbd3b36f 100644 --- a/opendaylight/config/shutdown-impl/src/main/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownServiceImpl.java +++ b/opendaylight/config/shutdown-impl/src/main/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownServiceImpl.java @@ -82,7 +82,6 @@ class Impl implements ShutdownService { class StopSystemBundleThread extends Thread { private static final Logger logger = LoggerFactory.getLogger(StopSystemBundleThread.class); - public static final String CONFIG_MANAGER_SYMBOLIC_NAME = "org.opendaylight.controller.config-manager"; private final Bundle systemBundle; StopSystemBundleThread(Bundle systemBundle) { @@ -95,13 +94,6 @@ class StopSystemBundleThread extends Thread { try { // wait so that JMX response is received Thread.sleep(1000); - // first try to stop config-manager - Bundle configManager = findConfigManager(); - if (configManager != null){ - logger.debug("Stopping config-manager"); - configManager.stop(); - Thread.sleep(1000); - } logger.debug("Stopping system bundle"); systemBundle.stop(); } catch (BundleException e) { @@ -110,16 +102,6 @@ class StopSystemBundleThread extends Thread { logger.warn("Shutdown process interrupted", e); } } - - private Bundle findConfigManager() { - for(Bundle bundle: systemBundle.getBundleContext().getBundles()){ - if (CONFIG_MANAGER_SYMBOLIC_NAME.equals(bundle.getSymbolicName())) { - return bundle; - } - } - return null; - } - } class CallSystemExitThread extends Thread { diff --git a/opendaylight/config/shutdown-impl/src/test/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownTest.java b/opendaylight/config/shutdown-impl/src/test/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownTest.java index d4a3160b89..358586f634 100644 --- a/opendaylight/config/shutdown-impl/src/test/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownTest.java +++ b/opendaylight/config/shutdown-impl/src/test/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownTest.java @@ -7,6 +7,17 @@ */ package org.opendaylight.controller.config.yang.shutdown.impl; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; +import static org.opendaylight.controller.config.yang.shutdown.impl.ShutdownModuleFactory.NAME; + +import java.util.Collections; +import javax.management.InstanceNotFoundException; +import javax.management.JMX; +import javax.management.ObjectName; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -20,22 +31,10 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleF import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.osgi.framework.Bundle; -import javax.management.InstanceNotFoundException; -import javax.management.JMX; -import javax.management.ObjectName; -import java.util.Collections; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.verify; -import static org.opendaylight.controller.config.yang.shutdown.impl.ShutdownModuleFactory.NAME; - public class ShutdownTest extends AbstractConfigTest { private final ShutdownModuleFactory factory = new ShutdownModuleFactory(); @Mock - private Bundle mockedSysBundle, mockedConfigManager; + private Bundle mockedSysBundle; @Before @@ -46,11 +45,10 @@ public class ShutdownTest extends AbstractConfigTest { doReturn(mockedSysBundle).when(mockedContext).getBundle(0); mockedContext.getBundle(0); doNothing().when(mockedSysBundle).stop(); - doNothing().when(mockedConfigManager).stop(); doReturn(mockedContext).when(mockedSysBundle).getBundleContext(); - doReturn(new Bundle[]{mockedSysBundle, mockedConfigManager}).when(mockedContext).getBundles(); + doReturn(new Bundle[]{mockedSysBundle}).when(mockedContext).getBundles(); doReturn("system bundle").when(mockedSysBundle).getSymbolicName(); - doReturn(StopSystemBundleThread.CONFIG_MANAGER_SYMBOLIC_NAME).when(mockedConfigManager).getSymbolicName(); + ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); @@ -129,7 +127,6 @@ public class ShutdownTest extends AbstractConfigTest { private void assertStopped() throws Exception { Thread.sleep(3000); // happens on another thread - verify(mockedConfigManager).stop(); verify(mockedSysBundle).stop(); } } diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/async/AsyncEventBusConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/async/AsyncEventBusConfigBeanTest.java index 177adc1588..0b339fc600 100644 --- a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/async/AsyncEventBusConfigBeanTest.java +++ b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/async/AsyncEventBusConfigBeanTest.java @@ -40,7 +40,7 @@ public class AsyncEventBusConfigBeanTest extends AbstractConfigTest { TestingScheduledThreadPoolModule.class, poolImplName); factory = new AsyncEventBusModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory, + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory, scheduledThreadPoolConfigFactory)); } diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/SyncEventBusConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/SyncEventBusConfigBeanTest.java index bc5e98bcb3..aeb6d6b959 100644 --- a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/SyncEventBusConfigBeanTest.java +++ b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/eventbus/SyncEventBusConfigBeanTest.java @@ -7,14 +7,6 @@ */ package org.opendaylight.controller.config.threadpool.eventbus; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; -import static org.junit.matchers.JUnitMatchers.containsString; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; - import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.api.ConflictingVersionException; @@ -25,6 +17,14 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.opendaylight.controller.config.yang.threadpool.impl.EventBusModuleFactory; +import javax.management.InstanceAlreadyExistsException; +import javax.management.ObjectName; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.junit.matchers.JUnitMatchers.containsString; + public class SyncEventBusConfigBeanTest extends AbstractConfigTest { private EventBusModuleFactory factory; @@ -34,7 +34,7 @@ public class SyncEventBusConfigBeanTest extends AbstractConfigTest { public void setUp() { factory = new EventBusModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory)); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory)); } @Test diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/FixedThreadPoolConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/FixedThreadPoolConfigBeanTest.java index 781215da43..c95661d9c9 100644 --- a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/FixedThreadPoolConfigBeanTest.java +++ b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/fixed/FixedThreadPoolConfigBeanTest.java @@ -36,7 +36,7 @@ public class FixedThreadPoolConfigBeanTest extends AbstractConfigTest { @Before public void setUp() { factory = new FixedThreadPoolModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory, + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory, new NamingThreadFactoryModuleFactory())); } diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/flexible/FlexibleThreadPoolConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/flexible/FlexibleThreadPoolConfigBeanTest.java index f0e8a108e7..a1d1c40655 100644 --- a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/flexible/FlexibleThreadPoolConfigBeanTest.java +++ b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/flexible/FlexibleThreadPoolConfigBeanTest.java @@ -38,7 +38,7 @@ public class FlexibleThreadPoolConfigBeanTest extends AbstractConfigTest { public void setUp() { flexibleFactory = new FlexibleThreadPoolModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(flexibleFactory, + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,flexibleFactory, new NamingThreadFactoryModuleFactory())); } diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/NamingThreadPoolFactoryConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/NamingThreadPoolFactoryConfigBeanTest.java index 6dea96e21f..499beced5f 100644 --- a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/NamingThreadPoolFactoryConfigBeanTest.java +++ b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/naming/NamingThreadPoolFactoryConfigBeanTest.java @@ -16,7 +16,6 @@ import static org.junit.matchers.JUnitMatchers.containsString; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.ObjectName; - import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.config.api.ConflictingVersionException; @@ -38,7 +37,7 @@ public class NamingThreadPoolFactoryConfigBeanTest extends AbstractConfigTest { public void setUp() { factory = new NamingThreadFactoryModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory)); + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory)); } @Test diff --git a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/ScheduledThreadPoolConfigBeanTest.java b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/ScheduledThreadPoolConfigBeanTest.java index 538d43726b..ef06e43d2f 100644 --- a/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/ScheduledThreadPoolConfigBeanTest.java +++ b/opendaylight/config/threadpool-config-impl/src/test/java/org/opendaylight/controller/config/threadpool/scheduled/ScheduledThreadPoolConfigBeanTest.java @@ -39,7 +39,7 @@ public class ScheduledThreadPoolConfigBeanTest extends AbstractConfigTest { public void setUp() { factory = new ScheduledThreadPoolModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory, + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory, new NamingThreadFactoryModuleFactory())); } diff --git a/opendaylight/config/yang-jmx-generator-it/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/it/ITTest.java b/opendaylight/config/yang-jmx-generator-it/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/it/ITTest.java index 598b6b3d5b..7505fcf485 100644 --- a/opendaylight/config/yang-jmx-generator-it/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/it/ITTest.java +++ b/opendaylight/config/yang-jmx-generator-it/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/it/ITTest.java @@ -7,11 +7,6 @@ */ package org.opendaylight.controller.config.yangjmxgenerator.it; -import static org.junit.Assert.fail; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; - import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -26,6 +21,11 @@ import org.opendaylight.controller.config.yang.test.impl.DtoB; import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory; import org.opendaylight.controller.config.yang.test.impl.TestImplModuleMXBean; +import javax.management.InstanceAlreadyExistsException; +import javax.management.ObjectName; + +import static org.junit.Assert.fail; + @Ignore // ietf beans are not JMX compliant beans: // Do not know how to make a @@ -42,7 +42,7 @@ public class ITTest extends AbstractConfigTest { public void setUp() { factory = new TestImplModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver( + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory)); } diff --git a/opendaylight/config/yang-jmx-generator-plugin/pom.xml b/opendaylight/config/yang-jmx-generator-plugin/pom.xml index 2d49ed7fab..b8831f6979 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/pom.xml +++ b/opendaylight/config/yang-jmx-generator-plugin/pom.xml @@ -126,30 +126,4 @@ - - - - maven-compiler-plugin - 3.1 - - groovy-eclipse-compiler - false - - - - - org.codehaus.groovy - groovy-eclipse-batch - 2.1.8-01 - - - org.codehaus.groovy - groovy-eclipse-compiler - 2.8.0-01 - - - - - - diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleFieldSerializer.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleFieldSerializer.java index c0e3bc1ad8..6211efe417 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleFieldSerializer.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/ModuleFieldSerializer.java @@ -16,7 +16,7 @@ public class ModuleFieldSerializer { public static String toString(ModuleField moduleField) { StringBuilder builder = new StringBuilder(); builder.append(" "); - builder.append("protected final " + builder.append("public static final " + JmxAttribute.class.getCanonicalName() + " " + moduleField.getName() + "JmxAttribute = new " + JmxAttribute.class.getCanonicalName() + "(\"" diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.groovy b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.groovy deleted file mode 100644 index baff88c8f3..0000000000 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.groovy +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory -import com.google.common.base.Optional -import org.opendaylight.controller.config.api.DependencyResolver -import org.opendaylight.controller.config.api.DynamicMBeanWithInstance -import org.opendaylight.controller.config.api.ModuleIdentifier -import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface -import org.opendaylight.controller.config.api.annotations.Description -import org.opendaylight.controller.config.spi.Module -import org.opendaylight.controller.config.spi.ModuleFactory -import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractFactoryTemplate -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field -import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.* -import org.opendaylight.yangtools.yang.common.QName -import org.osgi.framework.BundleContext - -public class AbsFactoryGeneratedObjectFactory { - - public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional copyright) { - FullyQualifiedName absFactoryFQN = new FullyQualifiedName(mbe.packageName, mbe.abstractFactoryName) - FullyQualifiedName moduleFQN = new FullyQualifiedName(mbe.packageName, mbe.stubModuleName) - Optional classJavaDoc = Optional.fromNullable(mbe.getNullableDescription()) - - AbstractFactoryTemplate abstractFactoryTemplate = TemplateFactory.abstractFactoryTemplateFromMbe(mbe) - Optional header = abstractFactoryTemplate.headerString; - List providedServices = mbe.providedServices.keySet().collect { - FullyQualifiedName.fromString(it) - } - - - return toGeneratedObject(absFactoryFQN, copyright, - header, classJavaDoc, mbe.yangModuleQName, - mbe.globallyUniqueName, - providedServices, - moduleFQN, - abstractFactoryTemplate.fields) - } - - public GeneratedObject toGeneratedObject(FullyQualifiedName absFactoryFQN, Optional copyright, - Optional header, Optional classJavaDoc, QName yangModuleQName, - String globallyUniqueName, - List providedServices, - FullyQualifiedName moduleFQN, - List moduleFields) { - JavaFileInputBuilder b = new JavaFileInputBuilder() - Annotation moduleQNameAnnotation = Annotation.createModuleQNameANnotation(yangModuleQName) - b.addClassAnnotation(moduleQNameAnnotation) - - b.setFqn(absFactoryFQN) - b.setTypeName(TypeName.absClassType) - - b.setCopyright(copyright); - b.setHeader(header); - b.setClassJavaDoc(classJavaDoc); - b.addImplementsFQN(new FullyQualifiedName(ModuleFactory)) - if (classJavaDoc.isPresent()) { - b.addClassAnnotation("@${Description.canonicalName}(value=\"${classJavaDoc.get()}\")") - } - - b.addToBody("public static final java.lang.String NAME = \"${globallyUniqueName}\";") - b.addToBody("private static final java.util.Set> serviceIfcs;") - - b.addToBody("@Override\n public final String getImplementationName() { \n return NAME; \n}") - - b.addToBody(getServiceIfcsInitialization(providedServices)) - - // createModule - b.addToBody(""" - @Override - public ${Module.canonicalName} createModule(String instanceName, ${DependencyResolver.canonicalName} dependencyResolver, ${BundleContext.canonicalName} bundleContext) { - return instantiateModule(instanceName, dependencyResolver, bundleContext); - } - """) - - b.addToBody(getCreateModule(moduleFQN, moduleFields)) - - b.addToBody(""" - public ${moduleFQN} instantiateModule(String instanceName, ${DependencyResolver.canonicalName} dependencyResolver, ${moduleFQN} oldModule, ${AutoCloseable.canonicalName} oldInstance, ${BundleContext.canonicalName} bundleContext) { - return new ${moduleFQN}(new ${ModuleIdentifier.canonicalName}(NAME, instanceName), dependencyResolver, oldModule, oldInstance); - } - """) - - b.addToBody(""" - public ${moduleFQN} instantiateModule(String instanceName, ${DependencyResolver.canonicalName} dependencyResolver, ${BundleContext.canonicalName} bundleContext) { - return new ${moduleFQN}(new ${ModuleIdentifier.canonicalName}(NAME, instanceName), dependencyResolver); - } - """) - - b.addToBody(""" - public ${moduleFQN} handleChangedClass(${DynamicMBeanWithInstance.canonicalName} old) throws Exception { - throw new UnsupportedOperationException("Class reloading is not supported"); - } - """) - - b.addToBody(""" - @Override - public java.util.Set<${moduleFQN}> getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory dependencyResolverFactory, ${BundleContext.canonicalName} bundleContext) { - return new java.util.HashSet<${moduleFQN}>(); - } - """) - - return new GeneratedObjectBuilder(b.build()).toGeneratedObject() - } - - private static String getCreateModule(FullyQualifiedName moduleFQN, List moduleFields) { - String result = """ - @Override - public ${Module.canonicalName} createModule(String instanceName, ${DependencyResolver.canonicalName} dependencyResolver, ${DynamicMBeanWithInstance.canonicalName} old, ${BundleContext.canonicalName} bundleContext) throws Exception { - ${moduleFQN} oldModule = null; - try { - oldModule = (${moduleFQN}) old.getModule(); - } catch(Exception e) { - return handleChangedClass(old); - } - ${moduleFQN} module = instantiateModule(instanceName, dependencyResolver, oldModule, old.getInstance(), bundleContext); - """ - result += moduleFields.collect{"module.set${it.name}(oldModule.get${it.name}());"}.join("\n") - result += """ - return module; - } - """ - return result - } - - private static String getServiceIfcsInitialization(List providedServices) { - String generic = "Class" - - String result = """static { - java.util.Set<${generic}> serviceIfcs2 = new java.util.HashSet<${generic}>(); - """ - result += providedServices.collect{"serviceIfcs2.add(${it}.class);"}.join("\n") - result += """serviceIfcs = java.util.Collections.unmodifiableSet(serviceIfcs2); - } - """ - - // add isModuleImplementingServiceInterface and getImplementedServiceIntefaces methods - - result += """ - @Override - public final boolean isModuleImplementingServiceInterface(Class serviceInterface) { - for (Class ifc: serviceIfcs) { - if (serviceInterface.isAssignableFrom(ifc)){ - return true; - } - } - return false; - } - - @Override - public java.util.Set> getImplementedServiceIntefaces() { - return serviceIfcs; - } - """ - - return result - } - -} diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.java new file mode 100644 index 0000000000..48a6c15706 --- /dev/null +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory; + +import static java.lang.String.format; + +import com.google.common.base.Optional; +import java.util.ArrayList; +import java.util.List; +import org.opendaylight.controller.config.api.DependencyResolver; +import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; +import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface; +import org.opendaylight.controller.config.api.annotations.Description; +import org.opendaylight.controller.config.spi.Module; +import org.opendaylight.controller.config.spi.ModuleFactory; +import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractFactoryTemplate; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObjectBuilder; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.TypeName; +import org.opendaylight.yangtools.yang.common.QName; +import org.osgi.framework.BundleContext; + +public class AbsFactoryGeneratedObjectFactory { + + public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional copyright) { + FullyQualifiedName absFactoryFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getAbstractFactoryName()); + FullyQualifiedName moduleFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getStubModuleName()); + Optional classJavaDoc = Optional.fromNullable(mbe.getNullableDescription()); + + AbstractFactoryTemplate abstractFactoryTemplate = TemplateFactory.abstractFactoryTemplateFromMbe(mbe); + Optional header = abstractFactoryTemplate.getHeaderString(); + + List providedServices = new ArrayList<>(); + for(String providedService: mbe.getProvidedServices().keySet()) { + providedServices.add(FullyQualifiedName.fromString(providedService)); + } + + return toGeneratedObject(absFactoryFQN, copyright, + header, classJavaDoc, mbe.getYangModuleQName(), + mbe.getGloballyUniqueName(), + providedServices, + moduleFQN, + abstractFactoryTemplate.getFields()); + } + + public GeneratedObject toGeneratedObject(FullyQualifiedName absFactoryFQN, Optional copyright, + Optional header, Optional classJavaDoc, QName yangModuleQName, + String globallyUniqueName, + List providedServices, + FullyQualifiedName moduleFQN, + List moduleFields) { + JavaFileInputBuilder b = new JavaFileInputBuilder(); + Annotation moduleQNameAnnotation = Annotation.createModuleQNameANnotation(yangModuleQName); + b.addClassAnnotation(moduleQNameAnnotation); + + b.setFqn(absFactoryFQN); + b.setTypeName(TypeName.absClassType); + + b.setCopyright(copyright); + b.setHeader(header); + b.setClassJavaDoc(classJavaDoc); + b.addImplementsFQN(new FullyQualifiedName(ModuleFactory.class)); + if (classJavaDoc.isPresent()) { + b.addClassAnnotation(format("@%s(value=\"%s\")", Description.class.getCanonicalName(), classJavaDoc.get())); + } + + b.addToBody(format("public static final java.lang.String NAME = \"%s\";", globallyUniqueName)); + b.addToBody(format("private static final java.util.Set> serviceIfcs;", + AbstractServiceInterface.class.getCanonicalName())); + + b.addToBody("@Override\n public final String getImplementationName() { \n return NAME; \n}"); + + b.addToBody(getServiceIfcsInitialization(providedServices)); + + // createModule + b.addToBody(format("\n"+ + "@Override\n"+ + "public %s createModule(String instanceName, %s dependencyResolver, %s bundleContext) {\n"+ + "return instantiateModule(instanceName, dependencyResolver, bundleContext);\n"+ + "}\n", + Module.class.getCanonicalName(), DependencyResolver.class.getCanonicalName(), BundleContext.class.getCanonicalName())); + + b.addToBody(getCreateModule(moduleFQN, moduleFields)); + + b.addToBody(format("\n"+ + "public %s instantiateModule(String instanceName, %s dependencyResolver, %s oldModule, %s oldInstance, %s bundleContext) {\n"+ + "return new %s(new %s(NAME, instanceName), dependencyResolver, oldModule, oldInstance);\n"+ + "}\n", + moduleFQN, DependencyResolver.class.getCanonicalName(), moduleFQN, AutoCloseable.class.getCanonicalName(), + BundleContext.class.getCanonicalName(), moduleFQN, ModuleIdentifier.class.getCanonicalName())); + + b.addToBody(format("\n"+ + "public %s instantiateModule(String instanceName, %s dependencyResolver, %s bundleContext) {\n"+ + "return new %s(new %s(NAME, instanceName), dependencyResolver);\n"+ + "}\n", moduleFQN, DependencyResolver.class.getCanonicalName(), BundleContext.class.getCanonicalName(), + moduleFQN, ModuleIdentifier.class.getCanonicalName() + )); + + b.addToBody(format("\n"+ + "public %s handleChangedClass(%s old) throws Exception {\n"+ + "throw new UnsupportedOperationException(\"Class reloading is not supported\");\n"+ + "}\n", moduleFQN, DynamicMBeanWithInstance.class.getCanonicalName())); + + b.addToBody(format("\n"+ + "@Override\n"+ + "public java.util.Set<%s> getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory dependencyResolverFactory, %s bundleContext) {\n"+ + "return new java.util.HashSet<%s>();\n"+ + "}\n", moduleFQN, BundleContext.class.getCanonicalName(), moduleFQN)); + + return new GeneratedObjectBuilder(b.build()).toGeneratedObject(); + } + + private static String getCreateModule(FullyQualifiedName moduleFQN, List moduleFields) { + String result = "\n"+ + "@Override\n"+ + format("public %s createModule(String instanceName, %s dependencyResolver, %s old, %s bundleContext) throws Exception {\n", + Module.class.getCanonicalName(),DependencyResolver.class.getCanonicalName(), + DynamicMBeanWithInstance.class.getCanonicalName(),BundleContext.class.getCanonicalName())+ + format("%s oldModule = null;\n",moduleFQN)+ + "try {\n"+ + format("oldModule = (%s) old.getModule();\n",moduleFQN)+ + "} catch(Exception e) {\n"+ + "return handleChangedClass(old);\n"+ + "}\n"+ + format("%s module = instantiateModule(instanceName, dependencyResolver, oldModule, old.getInstance(), bundleContext);\n", moduleFQN); + + for(Field field: moduleFields) { + result += format("module.set%s(oldModule.get%1$s());\n", field.getName()); + } + + result += "\n"+ + "return module;\n"+ + "}\n"; + return result; + } + + private static String getServiceIfcsInitialization(List providedServices) { + String generic = format("Class", AbstractServiceInterface.class.getCanonicalName()); + + String result = format("static {\n"+ + "java.util.Set<%1$s> serviceIfcs2 = new java.util.HashSet<%1$s>();\n", generic); + + for(FullyQualifiedName fqn: providedServices) { + result += format("serviceIfcs2.add(%s.class);\n", fqn); + } + result += "serviceIfcs = java.util.Collections.unmodifiableSet(serviceIfcs2);\n"+ + "}\n"; + + // add isModuleImplementingServiceInterface and getImplementedServiceIntefaces methods + + result += format("\n"+ + "@Override\n"+ + "public final boolean isModuleImplementingServiceInterface(Class serviceInterface) {\n"+ + "for (Class ifc: serviceIfcs) {\n"+ + "if (serviceInterface.isAssignableFrom(ifc)){\n"+ + "return true;\n"+ + "}\n"+ + "}\n"+ + "return false;\n"+ + "}\n"+ + "\n"+ + "@Override\n"+ + "public java.util.Set> getImplementedServiceIntefaces() {\n"+ + "return serviceIfcs;\n"+ + "}\n", AbstractServiceInterface.class.getCanonicalName()); + + return result; + } + +} diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.groovy b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.groovy deleted file mode 100644 index 930acff7bc..0000000000 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.groovy +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory -import com.google.common.base.Optional -import org.opendaylight.controller.config.api.DependencyResolver -import org.opendaylight.controller.config.api.ModuleIdentifier -import org.opendaylight.controller.config.api.annotations.Description -import org.opendaylight.controller.config.api.runtime.RootRuntimeBeanRegistrator -import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractModuleTemplate -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.IdentityRefModuleField -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Method -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField -import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.* -import org.opendaylight.yangtools.yang.common.QName -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -public class AbsModuleGeneratedObjectFactory { - - public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional copyright) { - FullyQualifiedName abstractFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getAbstractModuleName()) - Optional classJavaDoc = Optional.fromNullable(mbe.getNullableDescription()) - AbstractModuleTemplate abstractModuleTemplate = TemplateFactory.abstractModuleTemplateFromMbe(mbe) - Optional header = abstractModuleTemplate.headerString; - List implementedInterfaces = abstractModuleTemplate.getTypeDeclaration().getImplemented().collect { - FullyQualifiedName.fromString(it) - } - Optional maybeRegistratorType - if (abstractModuleTemplate.isRuntime()) { - maybeRegistratorType = Optional.of(FullyQualifiedName.fromString(abstractModuleTemplate.getRegistratorType())) - } else { - maybeRegistratorType = Optional.absent() - } - - return toGeneratedObject(abstractFQN, copyright, header, classJavaDoc, implementedInterfaces, - abstractModuleTemplate.getModuleFields(), maybeRegistratorType, abstractModuleTemplate.getMethods(), - mbe.yangModuleQName - ) - } - - public GeneratedObject toGeneratedObject(FullyQualifiedName abstractFQN, - Optional copyright, - Optional header, - Optional classJavaDoc, - List implementedInterfaces, - List moduleFields, - Optional maybeRegistratorType, - List methods, - QName yangModuleQName) { - JavaFileInputBuilder b = new JavaFileInputBuilder() - - Annotation moduleQNameAnnotation = Annotation.createModuleQNameANnotation(yangModuleQName) - b.addClassAnnotation(moduleQNameAnnotation) - - b.setFqn(abstractFQN) - b.setTypeName(TypeName.absClassType) - - b.setCopyright(copyright); - b.setHeader(header); - b.setClassJavaDoc(classJavaDoc); - implementedInterfaces.each { b.addImplementsFQN(it) } - if (classJavaDoc.isPresent()) { - b.addClassAnnotation("@${Description.canonicalName}(value=\"${classJavaDoc.get()}\")") - } - - // add logger: - b.addToBody(getLogger(abstractFQN)); - - b.addToBody("//attributes start"); - - b.addToBody(moduleFields.collect { it.toString() }.join("\n")) - - b.addToBody("//attributes end"); - - - b.addToBody(getCommonFields(abstractFQN)); - - - b.addToBody(getNewConstructor(abstractFQN)) - b.addToBody(getCopyFromOldConstructor(abstractFQN)) - - b.addToBody(getRuntimeRegistratorCode(maybeRegistratorType)) - b.addToBody(getValidationMethods(moduleFields)) - - b.addToBody(getCachesOfResolvedDependencies(moduleFields)) - b.addToBody(getCachesOfResolvedIdentityRefs(moduleFields)) - b.addToBody(getGetInstance(moduleFields)) - b.addToBody(getReuseLogic(moduleFields, abstractFQN)) - b.addToBody(getEqualsAndHashCode(abstractFQN)) - - b.addToBody(getMethods(methods)) - - return new GeneratedObjectBuilder(b.build()).toGeneratedObject() - } - - private static String getMethods(List methods) { - String result = """ - // getters and setters - """ - result += methods.collect{it.toString()}.join("\n") - return result - } - - private static String getEqualsAndHashCode(FullyQualifiedName abstractFQN) { - return """ - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ${abstractFQN.typeName} that = (${abstractFQN.typeName}) o; - return identifier.equals(that.identifier); - } - - @Override - public int hashCode() { - return identifier.hashCode(); - } - """ - } - - private static String getReuseLogic(List moduleFields, FullyQualifiedName abstractFQN) { - String result = """ - public boolean canReuseInstance(${abstractFQN.typeName} oldModule){ - // allow reusing of old instance if no parameters was changed - return isSame(oldModule); - } - - public ${AutoCloseable.canonicalName} reuseInstance(${AutoCloseable.canonicalName} oldInstance){ - // implement if instance reuse should be supported. Override canReuseInstance to change the criteria. - return oldInstance; - } - """ - // isSame method that detects changed fields - result += """ - public boolean isSame(${abstractFQN.typeName} other) { - if (other == null) { - throw new IllegalArgumentException("Parameter 'other' is null"); - } - """ - // loop through fields, do deep equals on each field - result += moduleFields.collect { field -> - if (field.isListOfDependencies()) { - return """ - if (${field.name}Dependency.equals(other.${field.name}Dependency) == false) { - return false; - } - for (int idx = 0; idx < ${field.name}Dependency.size(); idx++) { - if (${field.name}Dependency.get(idx) != other.${field.name}Dependency.get(idx)) { - return false; - } - } - """ - } else if (field.isDependent()) { - return """ - if (${field.name}Dependency != other.${field.name}Dependency) { // reference to dependency must be same - return false; - } - """ - } else { - return """ - if (java.util.Objects.deepEquals(${field.name}, other.${field.name}) == false) { - return false; - } - """ - } - }.join("\n") - - - result += """ - return true; - } - """ - - return result - } - - private static String getGetInstance(List moduleFields) { - String result = """ - @Override - public final ${AutoCloseable.canonicalName} getInstance() { - if(instance==null) { - """ - // create instance start - - // loop through dependent fields, use dependency resolver to instantiate dependencies. Do it in loop in case field represents list of dependencies. - Map resolveDependenciesMap = moduleFields.findAll { - it.isDependent() - }.collectEntries { ModuleField field -> - [field, field.isList() ? - """ - ${field.name}Dependency = new java.util.ArrayList<${field.dependency.sie.exportedOsgiClassName}>(); - for(javax.management.ObjectName dep : ${field.name}) { - ${field.name}Dependency.add(dependencyResolver.resolveInstance(${ - field.dependency.sie.exportedOsgiClassName - }.class, dep, ${field.name}JmxAttribute)); - } - """ - : - """ - ${field.name}Dependency = dependencyResolver.resolveInstance(${ - field.dependency.sie.exportedOsgiClassName - }.class, ${field.name}, ${field.name}JmxAttribute); - """ - ] - } - // wrap each field resolvation statement with if !=null when dependency is not mandatory - def wrapWithNullCheckClosure = {Map map, predicate -> map.collect { ModuleField key, String value -> - predicate(key) ? """ - if(${key.name}!=null) { - ${value} - } - """ : value - }.join("\n") - } - - result += wrapWithNullCheckClosure(resolveDependenciesMap, {ModuleField key -> - key.getDependency().isMandatory() == false} ) - - // add code to inject dependency resolver to fields that support it - Map injectDepsMap = moduleFields.findAll { it.needsDepResolver }.collectEntries { field -> - if (field.isList()) { - return [field,""" - for(${field.genericInnerType} candidate : ${field.name}) { - candidate.injectDependencyResolver(dependencyResolver); - } - """] - } else { - return [field, "${field.name}.injectDependencyResolver(dependencyResolver);"] - } - } - - result += wrapWithNullCheckClosure(injectDepsMap, {true}) - - // identity refs need to be injected with dependencyResolver and base class - Map resolveIdentityMap = moduleFields.findAll { it.isIdentityRef() }.collectEntries { IdentityRefModuleField field -> - [field, - "set${field.attributeName}(${field.name}.resolveIdentity(dependencyResolver, ${field.identityBaseClass}.class));"] - } - - result += wrapWithNullCheckClosure(resolveIdentityMap, {true}) - - // create instance end: reuse and recreate logic - result += """ - if(oldInstance!=null && canReuseInstance(oldModule)) { - instance = reuseInstance(oldInstance); - } else { - if(oldInstance!=null) { - try { - oldInstance.close(); - } catch(Exception e) { - logger.error("An error occurred while closing old instance " + oldInstance, e); - } - } - instance = createInstance(); - if (instance == null) { - throw new IllegalStateException("Error in createInstance - null is not allowed as return value"); - } - } - } - return instance; - } - public abstract ${AutoCloseable.canonicalName} createInstance(); - """ - return result - } - - private static String getCommonFields(FullyQualifiedName abstractFQN) { - return """ - private final ${abstractFQN.typeName} oldModule; - private final ${AutoCloseable.canonicalName} oldInstance; - private ${AutoCloseable.canonicalName} instance; - private final ${DependencyResolver.canonicalName} dependencyResolver; - private final ${ModuleIdentifier.canonicalName} identifier; - @Override - public ${ModuleIdentifier.canonicalName} getIdentifier() { - return identifier; - } - """ - } - - private static String getCachesOfResolvedIdentityRefs(List moduleFields) { - return moduleFields.findAll { it.isIdentityRef() }.collect { IdentityRefModuleField field -> - "private ${field.identityClassType} ${field.identityClassName};" - }.join("\n") - } - - private static String getCachesOfResolvedDependencies(List moduleFields) { - return moduleFields.findAll { it.dependent }.collect { field -> - if (field.isList()) { - return """ - private java.util.List<${field.dependency.sie.exportedOsgiClassName}> ${ - field.name - }Dependency = new java.util.ArrayList<${field.dependency.sie.exportedOsgiClassName}>(); - protected final java.util.List<${field.dependency.sie.exportedOsgiClassName}> get${ - field.attributeName - }Dependency(){ - return ${field.name}Dependency; - } - """ - } else { - return """ - private ${field.dependency.sie.exportedOsgiClassName} ${field.name}Dependency; - protected final ${field.dependency.sie.exportedOsgiClassName} get${field.attributeName}Dependency(){ - return ${field.name}Dependency; - } - """ - } - }.join("\n") - } - - private static String getRuntimeRegistratorCode(Optional maybeRegistratorType) { - if (maybeRegistratorType.isPresent()) { - String registratorType = maybeRegistratorType.get() - - return """ - private ${registratorType} rootRuntimeBeanRegistratorWrapper; - - public ${registratorType} getRootRuntimeBeanRegistratorWrapper(){ - return rootRuntimeBeanRegistratorWrapper; - } - - @Override - public void setRuntimeBeanRegistrator(${RootRuntimeBeanRegistrator.canonicalName} rootRuntimeRegistrator){ - this.rootRuntimeBeanRegistratorWrapper = new ${registratorType}(rootRuntimeRegistrator); - } - """ - } else { - return "" - } - } - - private static String getValidationMethods(List moduleFields) { - String result = """ - @Override - public void validate() { - """ - // validate each mandatory dependency - List lines = moduleFields.findAll{(it.dependent && it.dependency.mandatory)}.collect { field -> - if (field.isList()) { - return "" + - "for(javax.management.ObjectName dep : ${field.name}) {\n" + - " dependencyResolver.validateDependency(${field.dependency.sie.fullyQualifiedName}.class, dep, ${field.name}JmxAttribute);\n" + - "}\n" - } else { - return "dependencyResolver.validateDependency(${field.dependency.sie.fullyQualifiedName}.class, ${field.name}, ${field.name}JmxAttribute);" - } - } - result += lines.findAll { it.isEmpty() == false }.join("\n") - result += """ - customValidation(); - } - - protected void customValidation(){ - } - """ - return result - } - - private static String getLogger(FullyQualifiedName fqn) { - return "private static final ${Logger.canonicalName} logger = ${LoggerFactory.canonicalName}.getLogger(${fqn.toString()}.class);" - } - - // assumes that each parameter name corresponds to an field in this class, constructs lines setting this.field = field; - private static String getConstructorStart(FullyQualifiedName fqn, - LinkedHashMap parameters, String after) { - return "public ${fqn.typeName}(" + - parameters.collect { it.key + " " + it.value }.join(",") + - ") {\n" + - parameters.values().collect { "this.${it}=${it};\n" }.join() + - after + - "}\n" - } - - private static String getNewConstructor(FullyQualifiedName abstractFQN) { - LinkedHashMap parameters = [ - (ModuleIdentifier.canonicalName): "identifier", - (DependencyResolver.canonicalName): "dependencyResolver" - ] - String setToNulls = ["oldInstance", "oldModule"].collect { "this.${it}=null;\n" }.join() - return getConstructorStart(abstractFQN, parameters, setToNulls) - } - - private static String getCopyFromOldConstructor(FullyQualifiedName abstractFQN) { - LinkedHashMap parameters = [ - (ModuleIdentifier.canonicalName): "identifier", - (DependencyResolver.canonicalName): "dependencyResolver", - (abstractFQN.typeName): "oldModule", - (AutoCloseable.canonicalName): "oldInstance" - ] - return getConstructorStart(abstractFQN, parameters, "") - } -} diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java new file mode 100644 index 0000000000..aa06cb97d7 --- /dev/null +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory; + +import static java.lang.String.format; + +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.opendaylight.controller.config.api.DependencyResolver; +import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.annotations.Description; +import org.opendaylight.controller.config.api.runtime.RootRuntimeBeanRegistrator; +import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractModuleTemplate; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.IdentityRefModuleField; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Method; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObjectBuilder; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.TypeName; +import org.opendaylight.yangtools.yang.common.QName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AbsModuleGeneratedObjectFactory { + + public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional copyright) { + FullyQualifiedName abstractFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getAbstractModuleName()); + Optional classJavaDoc = Optional.fromNullable(mbe.getNullableDescription()); + AbstractModuleTemplate abstractModuleTemplate = TemplateFactory.abstractModuleTemplateFromMbe(mbe); + Optional header = abstractModuleTemplate.getHeaderString(); + + List implementedInterfaces = new ArrayList<>(); + for(String implemented: abstractModuleTemplate.getTypeDeclaration().getImplemented()) { + implementedInterfaces.add(FullyQualifiedName.fromString(implemented)); + } + Optional maybeRegistratorType; + if (abstractModuleTemplate.isRuntime()) { + maybeRegistratorType = Optional.of(FullyQualifiedName.fromString(abstractModuleTemplate.getRegistratorType())); + } else { + maybeRegistratorType = Optional.absent(); + } + + return toGeneratedObject(abstractFQN, copyright, header, classJavaDoc, implementedInterfaces, + abstractModuleTemplate.getModuleFields(), maybeRegistratorType, abstractModuleTemplate.getMethods(), + mbe.getYangModuleQName()); + } + + public GeneratedObject toGeneratedObject(FullyQualifiedName abstractFQN, + Optional copyright, + Optional header, + Optional classJavaDoc, + List implementedInterfaces, + List moduleFields, + Optional maybeRegistratorType, + List methods, + QName yangModuleQName) { + JavaFileInputBuilder b = new JavaFileInputBuilder(); + + Annotation moduleQNameAnnotation = Annotation.createModuleQNameANnotation(yangModuleQName); + b.addClassAnnotation(moduleQNameAnnotation); + + b.setFqn(abstractFQN); + b.setTypeName(TypeName.absClassType); + + b.setCopyright(copyright); + b.setHeader(header); + b.setClassJavaDoc(classJavaDoc); + for(FullyQualifiedName implemented: implementedInterfaces) { + b.addImplementsFQN(implemented); + } + if (classJavaDoc.isPresent()) { + b.addClassAnnotation(format("@%s(value=\"%s\")", Description.class.getCanonicalName(), classJavaDoc.get())); + } + + // add logger: + b.addToBody(getLogger(abstractFQN)); + + b.addToBody("//attributes start"); + for(ModuleField moduleField: moduleFields) { + b.addToBody(moduleField.toString() +"\n"); + } + + b.addToBody("//attributes end"); + + + b.addToBody(getCommonFields(abstractFQN)); + + + b.addToBody(getNewConstructor(abstractFQN)); + b.addToBody(getCopyFromOldConstructor(abstractFQN)); + + b.addToBody(getRuntimeRegistratorCode(maybeRegistratorType)); + b.addToBody(getValidationMethods(moduleFields)); + + b.addToBody(getCachesOfResolvedDependencies(moduleFields)); + b.addToBody(getCachesOfResolvedIdentityRefs(moduleFields)); + b.addToBody(getGetInstance(moduleFields)); + b.addToBody(getReuseLogic(moduleFields, abstractFQN)); + b.addToBody(getEqualsAndHashCode(abstractFQN)); + + b.addToBody(getMethods(methods)); + + return new GeneratedObjectBuilder(b.build()).toGeneratedObject(); + } + + private static String getMethods(List methods) { + String result = "\n// getters and setters\n"; + for(Method method: methods) { + result += method.toString()+"\n"; + } + return result; + } + + private static String getEqualsAndHashCode(FullyQualifiedName abstractFQN) { + return "\n"+ + "@Override\n"+ + "public boolean equals(Object o) {\n"+ + "if (this == o) return true;\n"+ + "if (o == null || getClass() != o.getClass()) return false;\n"+ + format("%s that = (%1$s) o;\n", abstractFQN.getTypeName())+ + "return identifier.equals(that.identifier);\n"+ + "}\n"+ + "\n"+ + "@Override\n"+ + "public int hashCode() {\n"+ + "return identifier.hashCode();\n"+ + "}\n"; + } + + private static String getReuseLogic(List moduleFields, FullyQualifiedName abstractFQN) { + String result = "\n"+ + format("public boolean canReuseInstance(%s oldModule){\n", abstractFQN.getTypeName())+ + "// allow reusing of old instance if no parameters was changed\n"+ + "return isSame(oldModule);\n"+ + "}\n"+ + "\n"+ + format("public %s reuseInstance(%1$s oldInstance){\n", AutoCloseable.class.getCanonicalName())+ + "// implement if instance reuse should be supported. Override canReuseInstance to change the criteria.\n"+ + "return oldInstance;\n"+ + "}\n"; + // isSame method that detects changed fields + result += "\n"+ + format("public boolean isSame(%s other) {\n", abstractFQN.getTypeName())+ + "if (other == null) {\n"+ + "throw new IllegalArgumentException(\"Parameter 'other' is null\");\n"+ + "}\n"; + // loop through fields, do deep equals on each field + + for (ModuleField moduleField : moduleFields) { + if (moduleField.isListOfDependencies()) { + result += format( + "if (%1$sDependency.equals(other.%1$sDependency) == false) {\n"+ + "return false;\n"+ + "}\n"+ + "for (int idx = 0; idx < %1$sDependency.size(); idx++) {\n"+ + "if (%1$sDependency.get(idx) != other.%1$sDependency.get(idx)) {\n"+ + "return false;\n"+ + "}\n"+ + "}\n" ,moduleField.getName()); + } else if (moduleField.isDependent()) { + result += format( + "if (%sDependency != other.%1$sDependency) { // reference to dependency must be same\n"+ + "return false;\n"+ + "}\n",moduleField.getName()); + } else { + result += format( + "if (java.util.Objects.deepEquals(%s, other.%1$s) == false) {\n"+ + "return false;\n"+ + "}\n", moduleField.getName()); + } + } + result += "\n"+ + "return true;\n"+ + "}\n"; + + return result; + } + + private static String getGetInstance(List moduleFields) { + String result = "\n"+ + "@Override\n"+ + format("public final %s getInstance() {\n", AutoCloseable.class.getCanonicalName())+ + "if(instance==null) {\n"; + // create instance start + + // loop through dependent fields, use dependency resolver to instantiate dependencies. Do it in loop in case field represents list of dependencies. + Map resolveDependenciesMap = new HashMap<>(); + for(ModuleField moduleField: moduleFields) { + if (moduleField.isDependent()) { + String str; + String osgi = moduleField.getDependency().getSie().getExportedOsgiClassName(); + if (moduleField.isList()) { + str = format( + "%sDependency = new java.util.ArrayList<%s>();\n"+ + "for(javax.management.ObjectName dep : %1$s) {\n"+ + "%1$sDependency.add(dependencyResolver.resolveInstance(%2$s.class, dep, %1$sJmxAttribute));\n"+ + "}\n", moduleField.getName(), osgi); + } else { + str = format( + "%1$sDependency = dependencyResolver.resolveInstance(%2$s.class, %1$s, %1$sJmxAttribute);", + moduleField.getName(), osgi); + } + resolveDependenciesMap.put(moduleField, str); + } + } + + // wrap each field resolvation statement with if !=null when dependency is not mandatory + for (Map.Entry entry : resolveDependenciesMap.entrySet()) { + if (entry.getKey().getDependency().isMandatory() == false) { + result += format("if (%s!=null) {\n%s;\n}", entry.getKey().getName(), entry.getValue()); + } else { + result += entry.getValue(); + } + } + + // add code to inject dependency resolver to fields that support it + for(ModuleField moduleField: moduleFields) { + if (moduleField.isNeedsDepResolver()) { + result += format("if (%s!=null){\n", moduleField.getName()); + if (moduleField.isList()) { + result += format( + "for(%s candidate : %s) {\n"+ + "candidate.injectDependencyResolver(dependencyResolver);\n"+ + "}\n", moduleField.getGenericInnerType(), moduleField.getName()); + } else { + result += format("%s.injectDependencyResolver(dependencyResolver);\n", moduleField.getName()); + } + result += "}\n"; + } + } + + // identity refs need to be injected with dependencyResolver and base class + for (ModuleField moduleField : moduleFields) { + if (moduleField.isIdentityRef()) { + result += format("if (%s!=null) {", moduleField.getName()); + result += format("set%s(%s.resolveIdentity(dependencyResolver, %s.class));", + moduleField.getAttributeName(), moduleField.getName(), + ((IdentityRefModuleField)moduleField).getIdentityBaseClass()); + result += "}\n"; + } + } + + // create instance end: reuse and recreate logic + result += "if(oldInstance!=null && canReuseInstance(oldModule)) {\n"+ + "instance = reuseInstance(oldInstance);\n"+ + "} else {\n"+ + "if(oldInstance!=null) {\n"+ + "try {\n"+ + "oldInstance.close();\n"+ + "} catch(Exception e) {\n"+ + "logger.error(\"An error occurred while closing old instance \" + oldInstance, e);\n"+ + "}\n"+ + "}\n"+ + "instance = createInstance();\n"+ + "if (instance == null) {\n"+ + "throw new IllegalStateException(\"Error in createInstance - null is not allowed as return value\");\n"+ + "}\n"+ + "}\n"+ + "}\n"+ + "return instance;\n"+ + "}\n"+ + format("public abstract %s createInstance();\n", AutoCloseable.class.getCanonicalName()); + + return result; + } + + private static String getCommonFields(FullyQualifiedName abstractFQN) { + return "\n"+ + format("private final %s oldModule;\n", abstractFQN.getTypeName())+ + format("private final %s oldInstance;\n", AutoCloseable.class.getCanonicalName())+ + format("private %s instance;\n", AutoCloseable.class.getCanonicalName())+ + format("private final %s dependencyResolver;\n", DependencyResolver.class.getCanonicalName())+ + format("private final %s identifier;\n", ModuleIdentifier.class.getCanonicalName())+ + "@Override\n"+ + format("public %s getIdentifier() {\n", ModuleIdentifier.class.getCanonicalName())+ + "return identifier;\n"+ + "}\n"; + } + + private static String getCachesOfResolvedIdentityRefs(List moduleFields) { + StringBuilder result = new StringBuilder(); + for (ModuleField moduleField : moduleFields) { + if (moduleField.isIdentityRef()) { + IdentityRefModuleField field = (IdentityRefModuleField) moduleField; + result.append(format("private %s %s;\n", field.getIdentityClassType(), field.getIdentityClassName())); + } + } + return result.toString(); + } + + private static String getCachesOfResolvedDependencies(List moduleFields) { + StringBuilder result = new StringBuilder(); + for (ModuleField moduleField: moduleFields) { + if (moduleField.isDependent()) { + String osgi = moduleField.getDependency().getSie().getExportedOsgiClassName(); + if (moduleField.isList()) { + result + .append(format("private java.util.List<%s> %sDependency = new java.util.ArrayList<%s>();", osgi, moduleField.getName(), osgi)) + .append(format("protected final java.util.List<%s> get%sDependency(){\n", osgi, moduleField.getAttributeName())) + .append(format("return %sDependency;\n", moduleField.getName())) + .append("}\n"); + } else { + result.append(format( + "private %s %sDependency;\n"+ + "protected final %s get%sDependency(){\n"+ + "return %sDependency;\n"+ + "}", + osgi, moduleField.getName(), osgi, moduleField.getAttributeName(), moduleField.getName())); + } + } + } + return result.toString(); + } + + private static String getRuntimeRegistratorCode(Optional maybeRegistratorType) { + if (maybeRegistratorType.isPresent()) { + String registratorType = maybeRegistratorType.get().toString(); + + return "\n"+ + format("private %s rootRuntimeBeanRegistratorWrapper;\n", registratorType)+ + "\n"+ + format("public %s getRootRuntimeBeanRegistratorWrapper(){\n", registratorType)+ + "return rootRuntimeBeanRegistratorWrapper;\n"+ + "}\n"+ + "\n"+ + "@Override\n"+ + format("public void setRuntimeBeanRegistrator(%s rootRuntimeRegistrator){\n", RootRuntimeBeanRegistrator.class.getCanonicalName())+ + format("this.rootRuntimeBeanRegistratorWrapper = new %s(rootRuntimeRegistrator);\n", registratorType)+ + "}\n"; + } else { + return ""; + } + } + + private static String getValidationMethods(List moduleFields) { + String result = "\n"+ + "@Override\n"+ + "public void validate() {\n"; + // validate each mandatory dependency + for(ModuleField moduleField: moduleFields) { + if (moduleField.isDependent() && moduleField.getDependency().isMandatory()) { + if (moduleField.isList()) { + result += "" + + format("for(javax.management.ObjectName dep : %s) {\n", moduleField.getName()) + + format(" dependencyResolver.validateDependency(%s.class, dep, %sJmxAttribute);\n", + moduleField.getDependency().getSie().getFullyQualifiedName(), moduleField.getName()) + + "}\n"; + } else { + result += format("dependencyResolver.validateDependency(%s.class, %s, %sJmxAttribute);", + moduleField.getDependency().getSie().getFullyQualifiedName(), moduleField.getName(), moduleField.getName()); + } + } + } + result += "\n"+ + "customValidation();\n"+ + "}\n"+ + "\n"+ + "protected void customValidation() {\n"+ + "}\n"; + return result; + } + + private static String getLogger(FullyQualifiedName fqn) { + return format("private static final %s logger = %s.getLogger(%s.class);", + Logger.class.getCanonicalName(), LoggerFactory.class.getCanonicalName(), fqn); + } + + // assumes that each parameter name corresponds to an field in this class, constructs lines setting this.field = field; + private static String getConstructorStart(FullyQualifiedName fqn, + LinkedHashMap parameters, String after) { + String paramString = Joiner.on(",").withKeyValueSeparator(" ").join(parameters); + String setters = ""; + for (String paramName : parameters.values()) { + setters += format("this.%s = %1$s;\n", paramName); + } + return format("public %s(", fqn.getTypeName()) + + paramString + + ") {\n" + + setters + + after + + "}\n"; + } + + private static String getNewConstructor(FullyQualifiedName abstractFQN) { + LinkedHashMap parameters = new LinkedHashMap<>(); + parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier"); + parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver"); + + String setToNulls = "this.oldInstance=null;\n;" + + "this.oldModule=null;\n"; + return getConstructorStart(abstractFQN, parameters, setToNulls); + } + + private static String getCopyFromOldConstructor(FullyQualifiedName abstractFQN) { + LinkedHashMap parameters = new LinkedHashMap<>(); + parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier"); + parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver"); + parameters.put(abstractFQN.getTypeName(), "oldModule"); + parameters.put(AutoCloseable.class.getCanonicalName(), "oldInstance"); + return getConstructorStart(abstractFQN, parameters, ""); + } +} diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/ConcreteModuleGeneratedObjectFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/ConcreteModuleGeneratedObjectFactory.java index fbc507d0b4..051b1a7f5b 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/ConcreteModuleGeneratedObjectFactory.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/ConcreteModuleGeneratedObjectFactory.java @@ -1,7 +1,7 @@ package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory; -import com.google.common.base.Joiner; -import com.google.common.base.Optional; +import java.util.LinkedHashMap; + import org.opendaylight.controller.config.api.DependencyResolver; import org.opendaylight.controller.config.api.ModuleIdentifier; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; @@ -11,7 +11,8 @@ import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.Generated import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder; import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.TypeName; -import java.util.LinkedHashMap; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; public class ConcreteModuleGeneratedObjectFactory { @@ -46,12 +47,10 @@ public class ConcreteModuleGeneratedObjectFactory { } private static String getNewCtor(FullyQualifiedName fqn) { - LinkedHashMap parameters = new LinkedHashMap(){ - { - put(ModuleIdentifier.class.getCanonicalName(), "identifier"); - put(DependencyResolver.class.getCanonicalName(), "dependencyResolver"); - } - }; + LinkedHashMap parameters = new LinkedHashMap<>(); + parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier"); + parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver"); + StringBuilder stringBuilder = getCtor(fqn, parameters); return stringBuilder.toString(); } @@ -72,14 +71,11 @@ public class ConcreteModuleGeneratedObjectFactory { } private static String getCopyCtor(final FullyQualifiedName fqn) { - LinkedHashMap parameters = new LinkedHashMap(){ - { - put(ModuleIdentifier.class.getCanonicalName(), "identifier"); - put(DependencyResolver.class.getCanonicalName(), "dependencyResolver"); - put(fqn.toString(), "oldModule"); - put(AutoCloseable.class.getCanonicalName(), "oldInstance"); - } - }; + LinkedHashMap parameters = new LinkedHashMap<>(); + parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier"); + parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver"); + parameters.put(fqn.toString(), "oldModule"); + parameters.put(AutoCloseable.class.getCanonicalName(), "oldInstance"); StringBuilder stringBuilder = getCtor(fqn, parameters); return stringBuilder.toString(); } diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.groovy b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.groovy deleted file mode 100644 index 6504aac7d4..0000000000 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.groovy +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory - -import com.google.common.base.Optional -import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.FtlTemplate -import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName -import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject -import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObjectBuilder -import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder - -public class GenericGeneratedObjectFactory { - - public GeneratedObject toGeneratedObject(FtlTemplate template, Optional copyright) { - JavaFileInputBuilder b = new JavaFileInputBuilder(); - b.setHeader(template.headerString) - b.setFqn(new FullyQualifiedName(template.packageName, template.typeDeclaration.name)) - b.setClassJavaDoc(template.maybeJavadoc) - template.annotations.each { b.addClassAnnotation(it) } - // type declaration - template.typeDeclaration.extended.each { b.addExtendsFQN(FullyQualifiedName.fromString(it)) } - template.typeDeclaration.implemented.each { b.addImplementsFQN(FullyQualifiedName.fromString(it)) } - b.setCopyright(copyright); - b.setTypeName(template.typeDeclaration.toTypeName()) - // fields - template.fields.each { b.addToBody(it.toString()) } - // constructors - template.constructors.each { b.addToBody(it.toString()) } - // methods - template.methods.each { b.addToBody(it.toString()) } - - return new GeneratedObjectBuilder(b.build()).toGeneratedObject(); - } -} diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.java new file mode 100644 index 0000000000..11bb6774ae --- /dev/null +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory; + +import com.google.common.base.Optional; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.FtlTemplate; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Constructor; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Method; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObjectBuilder; +import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder; + +public class GenericGeneratedObjectFactory { + + public GeneratedObject toGeneratedObject(FtlTemplate template, Optional copyright) { + JavaFileInputBuilder b = new JavaFileInputBuilder(); + b.setHeader(template.getHeaderString()); + b.setFqn(new FullyQualifiedName(template.getPackageName(), template.getTypeDeclaration().getName())); + b.setClassJavaDoc(template.getMaybeJavadoc()); + for (Annotation annotation : template.getAnnotations()) { + b.addClassAnnotation(annotation); + } + // type declaration + for (String extended : template.getTypeDeclaration().getExtended()) { + b.addExtendsFQN(FullyQualifiedName.fromString(extended)); + } + for (String implemented : template.getTypeDeclaration().getImplemented()) { + b.addImplementsFQN(FullyQualifiedName.fromString(implemented)); + } + b.setCopyright(copyright); + b.setTypeName(template.getTypeDeclaration().toTypeName()); + // fields + for (Field field : template.getFields()) { + b.addToBody(field.toString()); + } + // constructors + for (Constructor constructor : template.getConstructors()) { + b.addToBody(constructor.toString()); + } + // methods + for (Method method : template.getMethods()) { + b.addToBody(method.toString()); + } + return new GeneratedObjectBuilder(b.build()).toGeneratedObject(); + } +} diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/util/StringUtil.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/util/StringUtil.java index 265aea10c5..bcc55a203e 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/util/StringUtil.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/util/StringUtil.java @@ -4,14 +4,11 @@ import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.base.Splitter; import com.google.common.base.Strings; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.io.InputStream; import java.util.List; import java.util.regex.Pattern; @@ -61,13 +58,18 @@ public class StringUtil { public static Optional loadCopyright() { - try (InputStream in = StringUtil.class.getResourceAsStream("/copyright.txt")) { - if (in != null) { - return Optional.of(IOUtils.toString(in)); + /* + * FIXME: BUG-980: this is a nice feature, but the copyright needs to come + * from the project being processed, not this one. + try (InputStream in = StringUtil.class.getResourceAsStream("/copyright.txt")) { + if (in != null) { + return Optional.of(IOUtils.toString(in)); + } + } catch (IOException e) { + logger.warn("Cannot load copyright.txt", e); } - } catch (IOException e) { - logger.warn("Cannot load copyright.txt", e); - } + + */ return Optional.absent(); } diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/copyright.txt b/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/copyright.txt deleted file mode 100644 index 4a0c355685..0000000000 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/copyright.txt +++ /dev/null @@ -1,5 +0,0 @@ -Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - -This program and the accompanying materials are made available under the -terms of the Eclipse Public License v1.0 which accompanies this distribution, -and is available at http://www.eclipse.org/legal/epl-v10.html diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/util/StringUtilTest.java b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/util/StringUtilTest.java index b0217a4ba9..1ad0207c2b 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/util/StringUtilTest.java +++ b/opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/util/StringUtilTest.java @@ -1,5 +1,6 @@ package org.opendaylight.controller.config.yangjmxgenerator.plugin.util; +import org.junit.Ignore; import org.junit.Test; import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName; @@ -24,6 +25,7 @@ public class StringUtilTest { } @Test + @Ignore public void testCopyright() throws IOException { assertTrue(StringUtil.loadCopyright().isPresent()); } diff --git a/opendaylight/config/yang-test-plugin/src/main/java/org/opendaylight/controller/config/yang/test/plugin/ProcessSources.java b/opendaylight/config/yang-test-plugin/src/main/java/org/opendaylight/controller/config/yang/test/plugin/ProcessSources.java index f2a56f2b1b..7a20f22440 100644 --- a/opendaylight/config/yang-test-plugin/src/main/java/org/opendaylight/controller/config/yang/test/plugin/ProcessSources.java +++ b/opendaylight/config/yang-test-plugin/src/main/java/org/opendaylight/controller/config/yang/test/plugin/ProcessSources.java @@ -44,22 +44,53 @@ public class ProcessSources extends AbstractMojo{ File[] sourceFiles = sourceDirectory.listFiles(); for (File sourceFile: sourceFiles) { - if(sourceFile.getName().endsWith("Module.java") || sourceFile.getName().endsWith("ModuleFactory.java")) { - File stubFile = new File(sourceFile.getPath().replace(".java", "Stub.txt")); - if (stubFile.exists()) { - try { - rewrite(sourceFile, FileUtils.readFileToString(stubFile)); - } catch (IOException e) { - getLog().error("Error while reading/writing to files.", e); + if (sourceFile.getName().endsWith(".java")) { + String sourceContent; + try { + sourceContent = FileUtils.readFileToString(sourceFile); + } catch (IOException e) { + getLog().error("Cannot read " + sourceFile.getAbsolutePath(), e); + continue; + } + if (sourceFile.getName().endsWith("Module.java") || sourceFile.getName().endsWith("ModuleFactory.java")) { + File stubFile = new File(sourceFile.getPath().replace(".java", "Stub.txt")); + if (stubFile.exists()) { + String stubContent = null; + try { + stubContent = FileUtils.readFileToString(stubFile); + } catch (IOException e) { + getLog().error("Cannot read " + stubFile.getAbsolutePath(), e); + } + if (stubContent != null) { + sourceContent = rewriteStub(sourceContent, stubContent); + } } } + // remove copyright headers as they can contain timestamp + sourceContent = removeCopyrights(sourceContent); + + // replace the file content + try { + FileUtils.write(sourceFile, sourceContent); + } catch (IOException e) { + getLog().error("Cannot write " + sourceFile.getAbsolutePath(), e); + } } + } } - private static void rewrite(File sourceFile, String replaceTODOWith) throws IOException { - String source = FileUtils.readFileToString(sourceFile); - String target = Pattern.compile("^.*TODO.*\n.*throw new java.lang.UnsupportedOperationException.*$", Pattern.MULTILINE).matcher(source).replaceFirst(replaceTODOWith); - FileUtils.write(sourceFile, target); + private static Pattern MULTILINE_COMMENT_PATTERN = Pattern.compile("/\\*.*\\*/", Pattern.MULTILINE | Pattern.DOTALL); + private static String removeCopyrights(String source) { + String target = MULTILINE_COMMENT_PATTERN.matcher(source).replaceAll("\n"); + //FileUtils.write(sourceFile, target); + return target; + } + + private static Pattern UNSUPPORTED_OP_PATTERN = Pattern.compile("^.*TODO.*\n.*throw new java.lang.UnsupportedOperationException.*$", Pattern.MULTILINE); + + private static String rewriteStub(String source, String replaceTODOWith) { + String target = UNSUPPORTED_OP_PATTERN.matcher(source).replaceFirst(replaceTODOWith); + return target; } } diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java index 07d7438a00..78ac362e59 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModule.java @@ -1,10 +1,5 @@ -/* -* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. -* -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v1.0 which accompanies this distribution, -* and is available at http://www.eclipse.org/legal/epl-v10.html -*/ + + package org.opendaylight.controller.config.yang.test.impl; public class DepTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModule { public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java index 330f804e0e..026dd9aca2 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/DepTestImplModuleFactory.java @@ -1,19 +1,5 @@ -/* -* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. -* -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v1.0 which accompanies this distribution, -* and is available at http://www.eclipse.org/legal/epl-v10.html -*/ -/* -* Generated file -* -* Generated from: yang module name: config-test-impl yang module local name: impl-dep -* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator -* Generated at: Fri Apr 25 09:12:08 CEST 2014 -* -* Do not modify this file unless it is present under src/main directory -*/ + + package org.opendaylight.controller.config.yang.test.impl; public class DepTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory { diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java index a5b7f55df3..ddf72f39b4 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModule.java @@ -1,10 +1,5 @@ -/* -* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. -* -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v1.0 which accompanies this distribution, -* and is available at http://www.eclipse.org/legal/epl-v10.html -*/ + + package org.opendaylight.controller.config.yang.test.impl; public class IdentityTestModule extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModule { public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java index b57d1dc1d4..3a4348d376 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/IdentityTestModuleFactory.java @@ -1,19 +1,5 @@ -/* -* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. -* -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v1.0 which accompanies this distribution, -* and is available at http://www.eclipse.org/legal/epl-v10.html -*/ -/* -* Generated file -* -* Generated from: yang module name: config-test-impl yang module local name: impl-identity-test -* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator -* Generated at: Fri Apr 25 09:12:08 CEST 2014 -* -* Do not modify this file unless it is present under src/main directory -*/ + + package org.opendaylight.controller.config.yang.test.impl; public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory { diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java index ecbf4aba33..943fe3b0d7 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModule.java @@ -1,10 +1,5 @@ -/* -* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. -* -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v1.0 which accompanies this distribution, -* and is available at http://www.eclipse.org/legal/epl-v10.html -*/ + + package org.opendaylight.controller.config.yang.test.impl; public class NetconfTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModule { public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java index 74a05496df..587089b10f 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleFactory.java @@ -1,19 +1,5 @@ -/* -* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. -* -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v1.0 which accompanies this distribution, -* and is available at http://www.eclipse.org/legal/epl-v10.html -*/ -/* -* Generated file -* -* Generated from: yang module name: config-test-impl yang module local name: impl-netconf -* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator -* Generated at: Fri Apr 25 09:12:08 CEST 2014 -* -* Do not modify this file unless it is present under src/main directory -*/ + + package org.opendaylight.controller.config.yang.test.impl; public class NetconfTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory { diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java index 4de9804337..1d5cda036f 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleUtil.java @@ -1,10 +1,5 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ + + package org.opendaylight.controller.config.yang.test.impl; import com.google.common.collect.Lists; diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java index 9132407356..7b049e7b57 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModule.java @@ -1,10 +1,5 @@ -/* -* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. -* -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v1.0 which accompanies this distribution, -* and is available at http://www.eclipse.org/legal/epl-v10.html -*/ + + package org.opendaylight.controller.config.yang.test.impl; public class TestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModule { public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { diff --git a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java index 9680bffd6b..de9ac2fef3 100644 --- a/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java +++ b/opendaylight/config/yang-test/src/main/java/org/opendaylight/controller/config/yang/test/impl/TestImplModuleFactory.java @@ -1,19 +1,5 @@ -/* -* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. -* -* This program and the accompanying materials are made available under the -* terms of the Eclipse Public License v1.0 which accompanies this distribution, -* and is available at http://www.eclipse.org/legal/epl-v10.html -*/ -/* -* Generated file -* -* Generated from: yang module name: config-test-impl yang module local name: impl -* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator -* Generated at: Fri Apr 25 09:12:08 CEST 2014 -* -* Do not modify this file unless it is present under src/main directory -*/ + + package org.opendaylight.controller.config.yang.test.impl; public class TestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory { diff --git a/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java b/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java index 281c1aade5..13a31f5976 100644 --- a/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java +++ b/opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java @@ -48,7 +48,7 @@ public class NetconfTestImplModuleTest extends AbstractConfigTest { public void setUp() { factory = new NetconfTestImplModuleFactory(); - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory, + super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory, new DepTestImplModuleFactory(), new IdentityTestModuleFactory())); } diff --git a/opendaylight/configuration/api/pom.xml b/opendaylight/configuration/api/pom.xml index 992e4b08d1..ef27bfd5e4 100644 --- a/opendaylight/configuration/api/pom.xml +++ b/opendaylight/configuration/api/pom.xml @@ -23,7 +23,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/configuration/implementation/pom.xml b/opendaylight/configuration/implementation/pom.xml index b6d2229121..a4a7ba6746 100644 --- a/opendaylight/configuration/implementation/pom.xml +++ b/opendaylight/configuration/implementation/pom.xml @@ -35,7 +35,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/connectionmanager/api/pom.xml b/opendaylight/connectionmanager/api/pom.xml index b3a427a8f7..c4ced042d0 100644 --- a/opendaylight/connectionmanager/api/pom.xml +++ b/opendaylight/connectionmanager/api/pom.xml @@ -27,7 +27,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/connectionmanager/implementation/pom.xml b/opendaylight/connectionmanager/implementation/pom.xml index 5adcc89ee8..8be119d507 100644 --- a/opendaylight/connectionmanager/implementation/pom.xml +++ b/opendaylight/connectionmanager/implementation/pom.xml @@ -39,7 +39,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/containermanager/api/pom.xml b/opendaylight/containermanager/api/pom.xml index 5bfededfe5..a19e27189a 100644 --- a/opendaylight/containermanager/api/pom.xml +++ b/opendaylight/containermanager/api/pom.xml @@ -27,7 +27,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/containermanager/implementation/pom.xml b/opendaylight/containermanager/implementation/pom.xml index b7b9e0abda..3ead8be65a 100644 --- a/opendaylight/containermanager/implementation/pom.xml +++ b/opendaylight/containermanager/implementation/pom.xml @@ -43,7 +43,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/containermanager/it.implementation/pom.xml b/opendaylight/containermanager/it.implementation/pom.xml index 2727f77d90..a3f140d7e1 100644 --- a/opendaylight/containermanager/it.implementation/pom.xml +++ b/opendaylight/containermanager/it.implementation/pom.xml @@ -35,7 +35,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/distribution/opendaylight-karaf/pom.xml b/opendaylight/distribution/opendaylight-karaf/pom.xml new file mode 100644 index 0000000000..1414fac2f3 --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/pom.xml @@ -0,0 +1,222 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.2-SNAPSHOT + ../../commons/opendaylight + + distribution.opendaylight-karaf + pom + + 3.0 + + + + + + org.apache.karaf.features + framework + ${karaf.version} + kar + + + org.opendaylight.controller + config-features + ${config.version} + features + xml + runtime + + + + + org.opendaylight.controller + mdsal-features + ${mdsal.version} + features + xml + runtime + + + org.opendaylight.yangtools + features-file + ${yangtools.version} + features + xml + runtime + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.apache.felix + maven-bundle-plugin + [0,) + + cleanVersions + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + [0,) + + copy + unpack + + + + + + + + + org.apache.karaf.tooling + karaf-maven-plugin + [0,) + + commands-generate-help + + + + + + + + + org.fusesource.scalate + maven-scalate-plugin + [0,) + + sitegen + + + + + + + + + org.apache.servicemix.tooling + depends-maven-plugin + [0,) + + generate-depends-file + + + + + + + + + + + + + + + org.apache.karaf.tooling + karaf-maven-plugin + ${karaf.version} + true + + + + standard + + + + + + process-resources + + install-kars + + process-resources + + + package + + instance-create-archive + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${checkstyle.version} + + **\/target\/,**\/bin\/,**\/target-ide\/,**\/configuration\/initial\/ + + + + maven-resources-plugin + 2.6 + + + copy-resources + + copy-resources + + + process-resources + + ${basedir}/target/assembly + true + + + ${basedir}/src/main/resources + + + + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main + + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/context.xml b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/context.xml new file mode 100644 index 0000000000..90b9ddf1c8 --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/context.xml @@ -0,0 +1 @@ + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/00-netty.xml b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/00-netty.xml new file mode 100644 index 0000000000..2365c700f9 --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/00-netty.xml @@ -0,0 +1,60 @@ + + + urn:opendaylight:params:xml:ns:yang:controller:netty?module=netty&revision=2013-11-19 + urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12 + urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup?module=threadgroup&revision=2013-11-07 + urn:opendaylight:params:xml:ns:yang:controller:netty:timer?module=netty-timer&revision=2013-11-19 + + + + + + + netty:netty-threadgroup-fixed + global-boss-group + + + netty:netty-threadgroup-fixed + global-worker-group + + + netty:netty-hashed-wheel-timer + global-timer + + + netty:netty-global-event-executor + singleton + + + + + + netty:netty-threadgroup + + global-boss-group + /modules/module[type='netty-threadgroup-fixed'][name='global-boss-group'] + + + global-worker-group + /modules/module[type='netty-threadgroup-fixed'][name='global-worker-group'] + + + + netty:netty-event-executor + + global-event-executor + /modules/module[type='netty-global-event-executor'][name='singleton'] + + + + netty:netty-timer + + global-timer + /modules/module[type='netty-hashed-wheel-timer'][name='global-timer'] + + + + + + + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/01-md-sal.xml b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/01-md-sal.xml new file mode 100644 index 0000000000..619ab06d8d --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/01-md-sal.xml @@ -0,0 +1,203 @@ + + + + + + + + + prefix:schema-service-singleton + yang-schema-service + + + + + prefix:hash-map-data-store + hash-map-data-store + + + + + + + prefix:dom-broker-impl + dom-broker + + + dom:dom-data-store + + hash-map-data-store + + + + + + + + + prefix:binding-broker-impl + binding-broker-impl + + binding:binding-notification-service + binding-notification-broker + + + binding:binding-data-broker + binding-data-broker + + + + prefix:runtime-generated-mapping + runtime-mapping-singleton + + + prefix:binding-notification-broker + binding-notification-broker + + + + prefix:binding-data-broker + binding-data-broker + + dom:dom-broker-osgi-registry + dom-broker + + + binding:binding-dom-mapping-service + runtime-mapping-singleton + + + + + + + + + + dom:schema-service + + yang-schema-service + /modules/module[type='schema-service-singleton'][name='yang-schema-service'] + + + + binding:binding-notification-service + + binding-notification-broker + /modules/module[type='binding-notification-broker'][name='binding-notification-broker'] + + + + + dom:dom-data-store + + hash-map-data-store + /modules/module[type='hash-map-data-store'][name='hash-map-data-store'] + + + + + + + + binding:binding-broker-osgi-registry + + binding-osgi-broker + /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] + + + + binding:binding-rpc-registry + + binding-rpc-broker + /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] + + + + binding-impl:binding-dom-mapping-service + + runtime-mapping-singleton + /modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton'] + + + + dom:dom-broker-osgi-registry + + dom-broker + /modules/module[type='dom-broker-impl'][name='dom-broker'] + + + + + binding:binding-data-broker + + binding-data-broker + + /modules/module[type='binding-data-broker'][name='binding-data-broker'] + + + + + + + + + + + + urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor?module=netty-event-executor&revision=2013-11-12 + urn:opendaylight:params:xml:ns:yang:controller:threadpool?module=threadpool&revision=2013-04-09 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28 + + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml new file mode 100644 index 0000000000..7853b8681b --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml @@ -0,0 +1,27 @@ + + + + + + prefix:remote-zeromq-rpc-server + remoter + 5666 + + prefix:dom-broker-osgi-registry + dom-broker + + + + + + + + + + urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc?module=odl-sal-dom-rpc-remote-cfg&revision=2013-10-28 + + + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/03-toaster-sample.xml b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/03-toaster-sample.xml new file mode 100644 index 0000000000..c481485c92 --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/03-toaster-sample.xml @@ -0,0 +1,73 @@ + + + + + + + prefix:toaster-provider-impl + + toaster-provider-impl + + + binding:binding-rpc-registry + binding-rpc-broker + + + + + binding:binding-notification-service + + binding-notification-broker + + + + + + prefix:toaster-consumer-impl + + toaster-consumer-impl + + + binding:binding-rpc-registry + binding-rpc-broker + + + + + binding:binding-notification-service + + binding-notification-broker + + + + + + + toaster:toaster-provider + + toaster-provider + /modules/module[type='toaster-provider-impl'][name='toaster-provider-impl'] + + + + toaster:toaster-consumer + + toaster-consumer + /modules/module[type='toaster-consumer-impl'][name='toaster-consumer-impl'] + + + + + + + + + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer?module=toaster-consumer&revision=2014-01-31 + urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl?module=toaster-consumer-impl&revision=2014-01-31 + urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider?module=toaster-provider&revision=2014-01-31 + urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&revision=2014-01-31 + + + + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/logback.xml b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/logback.xml new file mode 100644 index 0000000000..d1a5dcc416 --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/logback.xml @@ -0,0 +1,97 @@ + + + + + %date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n + + + + logs/opendaylight.log + + + logs/opendaylight.%d.log.zip + 1 + + + + 10MB + + + + %date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{35} - %msg%n + + + + logs/audit.log + true + + %date{"yyyy-MM-dd HH:mm:ss.SSS z"} %msg %n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/tomcat-logging.properties b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/tomcat-logging.properties new file mode 100644 index 0000000000..3dbd9921b3 --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/tomcat-logging.properties @@ -0,0 +1,42 @@ +############################################################ +# Configuration file for tomcat logging +############################################################ +# Handlers: +# "handlers" specifies a comma separated list of log Handler +# classes. These handlers will be installed during VM startup. +# Note that these classes must be on the system classpath. +# Following line configures a ConsoleHandler and a FileHandler + +handlers= java.util.logging.FileHandler,java.util.logging.ConsoleHandler + +############################################################ +# Handler specific properties +# Describes specific configuration info for Handlers +# JUL does not support rolling file handler based on date +# For now we will keep count of files to 5 with rolling size of 10MB +############################################################ + +java.util.logging.FileHandler.pattern = logs/tomcat%g.log +java.util.logging.FileHandler.limit = 104857600 +java.util.logging.FileHandler.count = 5 +java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter +java.util.logging.FileHandler.append = true +java.util.logging.FileHandler.level = INFO + +# Limit the message that are printed on the console to SEVERE and above. +java.util.logging.ConsoleHandler.level = WARNING +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter + +# SimpleFormatter output format to print one-line log message like this: +# --
:: [] > +# +java.util.logging.SimpleFormatter.format=%1$tF %1$tT %1$tZ [%3$s] %4$s %2$s %5$s%6$s%n + +############################################################ +# Facility specific properties. +# Provides extra control for each logger. +############################################################ + +# For example, set the com.xyz.foo logger to only log SEVERE +# messages +#org.apache.catalina = SEVERE diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/tomcat-server.xml b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/tomcat-server.xml new file mode 100644 index 0000000000..f6f923e0d2 --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/tomcat-server.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/custom.properties b/opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/custom.properties new file mode 100644 index 0000000000..9a86866080 --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/etc/custom.properties @@ -0,0 +1,114 @@ +# Extra packages to import from the boot class loader +org.osgi.framework.system.packages.extra=sun.reflect,sun.reflect.misc,sun.misc,sun.nio.ch + +# https://bugs.eclipse.org/bugs/show_bug.cgi?id=325578 +# Extend the framework to avoid the resources to be presented with +# a URL of type bundleresource: but to be presented as file: +osgi.hook.configurators.include=org.eclipse.virgo.kernel.equinox.extensions.hooks.ExtensionsHookConfigurator + +# Embedded Tomcat configuration File +org.eclipse.gemini.web.tomcat.config.path=configuration/tomcat-server.xml +org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true + +# Use Equinox as default OSGi Framework Implementation +karaf.framework=equinox + +# Netconf startup configuration +netconf.tcp.address=127.0.0.1 +netconf.tcp.port=8383 + +netconf.tcp.client.address=127.0.0.1 +netconf.tcp.client.port=8383 + +netconf.ssh.address=0.0.0.0 +netconf.ssh.port=1830 +netconf.ssh.pk.path = ./configuration/RSA.pk + + +netconf.config.persister.active=1,2 +# read startup configuration +netconf.config.persister.1.storageAdapterClass=org.opendaylight.controller.config.persist.storage.directory.xml.XmlDirectoryStorageAdapter +netconf.config.persister.1.properties.directoryStorage=configuration/initial/ + +# include only xml files, files with other extensions will be skipped, multiple extensions are permitted e.g. netconf.config.persister.1.properties.includeExtensions=xml,cfg,config +netconf.config.persister.1.properties.includeExtensions=xml +netconf.config.persister.1.readonly=true + +netconf.config.persister.2.storageAdapterClass=org.opendaylight.controller.config.persist.storage.file.xml.XmlFileStorageAdapter +netconf.config.persister.2.properties.fileStorage=configuration/current/controller.currentconfig.xml +netconf.config.persister.2.properties.numberOfBackups=1 + +# logback configuration +logback.configurationFile=configuration/logback.xml + +# Container configuration +container.profile = Container + +# Connection manager configuration +connection.scheme = ANY_CONTROLLER_ONE_MASTER + +# Open Flow related system parameters +# TCP port on which the controller is listening (default 6633) +# of.listenPort=6633 +# IP address of the controller (default: wild card) +# of.address = 127.0.0.1 +# The time (in milliseconds) the controller will wait for a response after sending a Barrier Request or a Statistic Request message (default 2000 msec) +# of.messageResponseTimer=2000 +# The switch liveness timeout value (default 60500 msec) +# of.switchLivenessTimeout=60500 +# The size of the queue holding pending statistics requests (default 64). For large networks of n switches, it is recommended to set the queue size to n +# of.statsQueueSize = 64 +# The flow statistics polling interval in second (default 10 sec) +# of.flowStatsPollInterval=10 +# The port statistics polling interval in second (default 5 sec) +# of.portStatsPollInterval=5 +# The description statistics polling interval in second (default 60 sec) +# of.descStatsPollInterval=60 +# The table statistics polling interval in second (default 10 sec) +# of.tableStatsPollInterval=10 +# The maximum number of asynchronous messages can be sent before sending a Barrier Request (default 100) +# of.barrierMessagePriorCount=100 +# The interval which determines how often the discovery packets should be sent (default 300 sec) +# of.discoveryInterval=300 +# The timeout multiple of discovery interval +# of.discoveryTimeoutMultiple=2 +# For newly added ports, allow one more retry if the elapsed time exceeds this threshold (default 30 sec) +# of.discoveryThreshold=30 +# The maximum number of ports handled in one discovery batch (default 512) +# of.discoveryBatchMaxPorts=512 + +# OVSDB configuration +# ovsdb plugin supports both active and passive connections. It listens on port 6640 by default for Active connections. +ovsdb.listenPort=6640 + +# ovsdb creates Openflow nodes/bridges. This configuration configures the bridge's Openflow version. +# default Openflow version = 1.0, we also support 1.3. +# ovsdb.of.version=1.3 + +# TLS configuration +# To enable TLS, set secureChannelEnabled=true and specify the location of controller Java KeyStore and TrustStore files. +# The Java KeyStore contains controller's private key and certificate. The Java TrustStore contains the trusted certificate +# entries, including switches' Certification Authority (CA) certificates. For example, +# secureChannelEnabled=true +# controllerKeyStore=./configuration/ctlKeyStore +# controllerKeyStorePassword=xxxxxxxx (this password should match the password used for KeyStore generation and at least 6 characters) +# controllerTrustStore=./configuration/ctlTrustStore +# controllerTrustStorePassword=xxxxxxxx (this password should match the password used for TrustStore generation and at least 6 characters) + +secureChannelEnabled=false +controllerKeyStore= +controllerKeyStorePassword= +controllerTrustStore= +controllerTrustStorePassword= + +# User Manager configurations +enableStrongPasswordCheck = false + +#Jolokia configurations +org.jolokia.listenForHttpService=false + +# Logging configuration for Tomcat-JUL logging +java.util.logging.config.file=configuration/tomcat-logging.properties + +#Hosttracker hostsdb key scheme setting +hosttracker.keyscheme=IP \ No newline at end of file diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/version.properties b/opendaylight/distribution/opendaylight-karaf/src/main/resources/version.properties new file mode 100644 index 0000000000..90af49dfc2 --- /dev/null +++ b/opendaylight/distribution/opendaylight-karaf/src/main/resources/version.properties @@ -0,0 +1,6 @@ +org.opendaylight.controller.version = 0.1 +org.opendaylight.controller.build.scm.version = ${buildNumber} +org.opendaylight.controller.build.user = ${env.USER} +org.opendaylight.controller.build.workspace = ********** +org.opendaylight.controller.build.timestamp = ${timestamp} +org.opendaylight.controller.build.machine = ********** diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index f9985cbcc1..72ce89d14e 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -39,6 +39,11 @@ jackson-databind + + com.fasterxml.jackson.datatype + jackson-datatype-json-org + + com.fasterxml.jackson.jaxrs jackson-jaxrs-base @@ -53,6 +58,7 @@ com.fasterxml.jackson.module jackson-module-jaxb-annotations + com.google.code.gson gson @@ -341,6 +347,11 @@ org.jolokia jolokia-osgi + + + org.json + json + org.opendaylight.controller appauth @@ -865,6 +876,12 @@ org.opendaylight.controller netconf-client + + + + org.opendaylight.controller + netconf-config-dispatcher + org.opendaylight.controller netconf-impl @@ -981,6 +998,10 @@ org.opendaylight.controller sal-rest-connector + + org.opendaylight.controller + sal-rest-docgen + org.opendaylight.controller sal-restconf-broker @@ -1074,14 +1095,6 @@ org.opendaylight.controller.thirdparty ganymed - - org.opendaylight.controller.thirdparty - nagasena - - - org.opendaylight.controller.thirdparty - nagasena-rta - org.opendaylight.yangtools binding-generator-api @@ -1090,17 +1103,14 @@ org.opendaylight.yangtools binding-generator-impl - ${yangtools.version} org.opendaylight.yangtools binding-generator-spi - ${yangtools.version} org.opendaylight.yangtools binding-generator-util - ${yangtools.version} org.opendaylight.yangtools @@ -1110,7 +1120,6 @@ org.opendaylight.yangtools binding-type-provider - ${yangtools.version} org.opendaylight.yangtools @@ -1156,12 +1165,10 @@ org.opendaylight.yangtools yang-parser-api - ${yangtools.version} org.opendaylight.yangtools yang-parser-impl - ${yangtools.version} @@ -1195,6 +1202,14 @@ xtend-lib-osgi 2.4.3 + + org.openexi + nagasena + + + org.openexi + nagasena-rta + org.zeromq jeromq diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini index 9d0d6c1888..234e0feb45 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini @@ -22,6 +22,8 @@ netconf.tcp.client.port=8383 netconf.ssh.address=0.0.0.0 netconf.ssh.port=1830 netconf.ssh.pk.path = ./configuration/RSA.pk +netconf.ssh.default.user = netconf +netconf.ssh.default.password = netconf netconf.config.persister.active=1,2 diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml index 619ab06d8d..d872bfd47b 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml @@ -15,48 +15,13 @@ prefix:schema-service-singleton yang-schema-service - - - - prefix:hash-map-data-store - hash-map-data-store - - - - - - prefix:dom-broker-impl - dom-broker - - - dom:dom-data-store - - hash-map-data-store - - - - - - + prefix:binding-notification-broker + binding-notification-broker prefix:binding-broker-impl @@ -70,33 +35,30 @@ binding-data-broker + + - prefix:runtime-generated-mapping - runtime-mapping-singleton - - - prefix:binding-notification-broker - binding-notification-broker + prefix:dom-inmemory-data-broker + inmemory-data-broker + + dom:schema-service + yang-schema-service + - - prefix:binding-data-broker - binding-data-broker - - dom:dom-broker-osgi-registry - dom-broker - - - binding:binding-dom-mapping-service - runtime-mapping-singleton - + prefix:dom-broker-impl + inmemory-dom-broker + + dom:dom-async-data-broker + inmemory-data-broker + - - - - - - dom:schema-service - - yang-schema-service - /modules/module[type='schema-service-singleton'][name='yang-schema-service'] - - - - binding:binding-notification-service - - binding-notification-broker - /modules/module[type='binding-notification-broker'][name='binding-notification-broker'] - - - - - dom:dom-data-store - - hash-map-data-store - /modules/module[type='hash-map-data-store'][name='hash-map-data-store'] - - - - - - - - binding:binding-broker-osgi-registry - - binding-osgi-broker - /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] - - - - binding:binding-rpc-registry - - binding-rpc-broker - /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] - - - - binding-impl:binding-dom-mapping-service - - runtime-mapping-singleton - /modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton'] - - - - dom:dom-broker-osgi-registry - - dom-broker - /modules/module[type='dom-broker-impl'][name='dom-broker'] - - + + dom:schema-service + + yang-schema-service + /modules/module[type='schema-service-singleton'][name='yang-schema-service'] + + + + binding-impl:binding-dom-mapping-service + + runtime-mapping-singleton + /modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton'] + + + + binding:binding-notification-service + + binding-notification-broker + /modules/module[type='binding-notification-broker'][name='binding-notification-broker'] + + + + binding:binding-broker-osgi-registry + + binding-osgi-broker + /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] + + + + binding:binding-rpc-registry + + binding-rpc-broker + /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] + + - - binding:binding-data-broker - - binding-data-broker - - /modules/module[type='binding-data-broker'][name='binding-data-broker'] - - - - - - + + dom:dom-broker-osgi-registry + + dom-broker + /modules/module[type='dom-broker-impl'][name='inmemory-dom-broker'] + + + + binding:binding-data-broker + + binding-data-broker + /modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker'] + + + + + dom:dom-async-data-broker + + inmemory-data-broker + /modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker'] + + diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf-connector.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf-connector.xml new file mode 100644 index 0000000000..fcbec19f5f --- /dev/null +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf-connector.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + prefix:netconf-client-dispatcher + global-netconf-dispatcher + + prefix:netty-threadgroup + global-boss-group + + + prefix:netty-threadgroup + global-worker-group + + + prefix:netty-timer + global-timer + + + + + + prefix:sal-netconf-connector + controller-config +
127.0.0.1
+ 1830 + admin + admin + false + + prefix:netty-event-executor + global-event-executor + + + prefix:dom-broker-osgi-registry + dom-broker + + + prefix:netconf-client-dispatcher + global-netconf-dispatcher + +
+
+ + + + prefix:netconf-client-dispatcher + + global-netconf-dispatcher + /modules/module[type='netconf-client-dispatcher'][name='global-netconf-dispatcher'] + + + + +
+
+ + urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf?module=odl-sal-netconf-connector-cfg&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher?module=odl-netconfig-client-cfg&revision=2014-04-08 + +
diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/04-netconf-connector.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/04-netconf-connector.xml deleted file mode 100644 index 8143a38f34..0000000000 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/04-netconf-connector.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - prefix:sal-netconf-connector - controller-config - 1830 - admin - - prefix:netty-threadgroup - global-worker-group - -
127.0.0.1
- false - - prefix:netty-event-executor - global-event-executor - - admin - - prefix:netty-threadgroup - global-boss-group - - - prefix:dom-broker-osgi-registry - dom-broker - -
-
-
-
- - urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf?module=odl-sal-netconf-connector-cfg&revision=2013-10-28 - -
diff --git a/opendaylight/distribution/opendaylight/src/main/resources/run.sh b/opendaylight/distribution/opendaylight/src/main/resources/run.sh index 21245a0259..dba996a994 100755 --- a/opendaylight/distribution/opendaylight/src/main/resources/run.sh +++ b/opendaylight/distribution/opendaylight/src/main/resources/run.sh @@ -161,7 +161,7 @@ fi ######################################## # Now add to classpath the OSGi JAR ######################################## -CLASSPATH="${basedir}"/lib/org.eclipse.osgi-3.8.1.v20120830-144521.jar +CLASSPATH=${CLASSPATH}:${basedir}/lib/org.eclipse.osgi-3.8.1.v20120830-144521.jar FWCLASSPATH=file:"${basedir}"/lib/org.eclipse.osgi-3.8.1.v20120830-144521.jar ######################################## diff --git a/opendaylight/distribution/sanitytest/pom.xml b/opendaylight/distribution/sanitytest/pom.xml index 893776c567..793e835647 100644 --- a/opendaylight/distribution/sanitytest/pom.xml +++ b/opendaylight/distribution/sanitytest/pom.xml @@ -23,7 +23,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/dummy-console/README b/opendaylight/dummy-console/README new file mode 100644 index 0000000000..09974d5e54 --- /dev/null +++ b/opendaylight/dummy-console/README @@ -0,0 +1,2 @@ +This bundle is temporary only and should be removed as soon as possible +it is only for compatibility layer in Karaf. diff --git a/opendaylight/dummy-console/pom.xml b/opendaylight/dummy-console/pom.xml new file mode 100644 index 0000000000..6d90eb39da --- /dev/null +++ b/opendaylight/dummy-console/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.2-SNAPSHOT + ../commons/opendaylight + + dummy-console + 1.1.0-SNAPSHOT + bundle + Dummy Console Interfaces for Equinox-specific CLI + + + + org.apache.felix + maven-bundle-plugin + ${bundle.plugin.version} + true + + + * + org.eclipse.osgi.framework.console + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main + + diff --git a/opendaylight/dummy-console/src/main/java/org/eclipse/osgi/framework/console/CommandInterpreter.java b/opendaylight/dummy-console/src/main/java/org/eclipse/osgi/framework/console/CommandInterpreter.java new file mode 100644 index 0000000000..29e9fc931b --- /dev/null +++ b/opendaylight/dummy-console/src/main/java/org/eclipse/osgi/framework/console/CommandInterpreter.java @@ -0,0 +1,12 @@ +/* + * Copyright(c)2014 Inocybe Technologies, 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.eclipse.osgi.framework.console; + +/** Empty tag interface for Command Interpreter **/ +public interface CommandInterpreter {} diff --git a/opendaylight/dummy-console/src/main/java/org/eclipse/osgi/framework/console/CommandProvider.java b/opendaylight/dummy-console/src/main/java/org/eclipse/osgi/framework/console/CommandProvider.java new file mode 100644 index 0000000000..a781f6f908 --- /dev/null +++ b/opendaylight/dummy-console/src/main/java/org/eclipse/osgi/framework/console/CommandProvider.java @@ -0,0 +1,12 @@ +/* + * Copyright(c)2014 Inocybe Technologies, 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.eclipse.osgi.framework.console; + +/** Empty tag interface for Command Provider **/ +public interface CommandProvider {} diff --git a/opendaylight/forwarding/staticrouting/pom.xml b/opendaylight/forwarding/staticrouting/pom.xml index 6a73a21e73..37c0a3a09d 100644 --- a/opendaylight/forwarding/staticrouting/pom.xml +++ b/opendaylight/forwarding/staticrouting/pom.xml @@ -39,7 +39,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/forwardingrulesmanager/api/pom.xml b/opendaylight/forwardingrulesmanager/api/pom.xml index 82f5f9b9e9..b6e1dd68d1 100644 --- a/opendaylight/forwardingrulesmanager/api/pom.xml +++ b/opendaylight/forwardingrulesmanager/api/pom.xml @@ -35,7 +35,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/forwardingrulesmanager/implementation/pom.xml b/opendaylight/forwardingrulesmanager/implementation/pom.xml index a5a15f685c..f87bed8780 100644 --- a/opendaylight/forwardingrulesmanager/implementation/pom.xml +++ b/opendaylight/forwardingrulesmanager/implementation/pom.xml @@ -55,7 +55,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java index f7b647dd72..46008b24c6 100644 --- a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java +++ b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java @@ -2342,7 +2342,7 @@ public class ForwardingRulesManager implements for (FlowConfig flowConfig : flowConfigForNode) { if (doesFlowContainNodeConnector(flowConfig.getFlow(), nodeConnector)) { if (flowConfig.installInHw() && !flowConfig.getStatus().equals(StatusCode.SUCCESS.toString())) { - Status status = this.installFlowEntry(flowConfig.getFlowEntry()); + Status status = this.installFlowEntryAsync(flowConfig.getFlowEntry()); if (!status.isSuccess()) { flowConfig.setStatus(status.getDescription()); } else { diff --git a/opendaylight/hosttracker/api/pom.xml b/opendaylight/hosttracker/api/pom.xml index d8f31ca65a..b48d7abd72 100644 --- a/opendaylight/hosttracker/api/pom.xml +++ b/opendaylight/hosttracker/api/pom.xml @@ -26,7 +26,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/hosttracker/implementation/pom.xml b/opendaylight/hosttracker/implementation/pom.xml index 9da62bdfe7..cb09322b64 100644 --- a/opendaylight/hosttracker/implementation/pom.xml +++ b/opendaylight/hosttracker/implementation/pom.xml @@ -58,7 +58,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/hosttracker_new/api/pom.xml b/opendaylight/hosttracker_new/api/pom.xml index 1dec4e5574..240976b9c8 100644 --- a/opendaylight/hosttracker_new/api/pom.xml +++ b/opendaylight/hosttracker_new/api/pom.xml @@ -38,7 +38,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/hosttracker_new/implementation/pom.xml b/opendaylight/hosttracker_new/implementation/pom.xml index aaaf3abacf..036dd5dd31 100644 --- a/opendaylight/hosttracker_new/implementation/pom.xml +++ b/opendaylight/hosttracker_new/implementation/pom.xml @@ -62,7 +62,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/logging/bridge/pom.xml b/opendaylight/logging/bridge/pom.xml index 26fd11c5ef..82bc6cd9c1 100644 --- a/opendaylight/logging/bridge/pom.xml +++ b/opendaylight/logging/bridge/pom.xml @@ -43,7 +43,6 @@ org.apache.felix maven-bundle-plugin - ${bundle.plugin.version} true diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml b/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml index 93ce0dd4f7..7770c15349 100644 --- a/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml @@ -14,10 +14,6 @@ com.google.guava guava
- - org.eclipse.xtend - org.eclipse.xtend.lib - org.opendaylight.controller forwardingrulesmanager @@ -67,10 +63,6 @@ - - org.eclipse.xtend - xtend-maven-plugin - diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/ConfigurationReader.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/ConfigurationReader.java new file mode 100644 index 0000000000..411af282bd --- /dev/null +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/ConfigurationReader.java @@ -0,0 +1,62 @@ +/** + * 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.frm.compatibility; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; + +import org.opendaylight.controller.forwardingrulesmanager.FlowConfig; +import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager; +import org.opendaylight.controller.sal.compatibility.NodeMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.FlowsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConfigurationReader implements FlowManagementReader { + + private final static Logger LOG = LoggerFactory.getLogger(ConfigurationReader.class); + + private IForwardingRulesManager manager; + + @Override + public Flows readAllFlows() { + List staticFlows = this.manager.getStaticFlows(); + List flowMap = new ArrayList(staticFlows.size()); + + for (FlowConfig conf : staticFlows) { + flowMap.add(FlowConfigMapping.toConfigurationFlow(conf)); + } + final FlowsBuilder flowsBuilder = new FlowsBuilder(); + return (flowsBuilder.setFlow(flowMap)).build(); + } + + @Override + public Flow readFlow(final FlowKey key) { + try { + final FlowConfig flowConf = + this.manager.getStaticFlow(String.valueOf(key.getId()), NodeMapping.toADNode(key.getNode())); + return FlowConfigMapping.toConfigurationFlow(flowConf); + } catch (Exception e) { + String errMsg = MessageFormat.format("readFlow by key {} fail", key); + LOG.error(errMsg, e); + throw new RuntimeException(errMsg, e); + } + } + + public IForwardingRulesManager getManager() { + return this.manager; + } + + public void setManager(final IForwardingRulesManager manager) { + this.manager = manager; + } +} diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java new file mode 100644 index 0000000000..be3add1042 --- /dev/null +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.java @@ -0,0 +1,122 @@ +/** + * 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.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.md.sal.common.api.data.DataCommitHandler; +import org.opendaylight.controller.md.sal.common.api.data.DataModification; +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.DataObject; +import org.opendaylight.yangtools.yang.binding.Identifier; +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 com.google.common.base.Objects; +import com.google.common.base.Preconditions; + +public class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHandler,DataObject> { + + private final static InstanceIdentifier FLOWS_PATH = InstanceIdentifier. builder(Flows.class).toInstance(); + + private final FlowManagementReader configuration = new ConfigurationReader(); + private DataChangeListener, DataObject> changeListener; + private DataProviderService dataService; + private IForwardingRulesManager manager; + + public Registration, DataObject>> init() { + return this.dataService.registerCommitHandler(FRMRuntimeDataProvider.FLOWS_PATH, this); + } + + @Override + public DataObject readConfigurationData(final InstanceIdentifier path) { + return this.readFrom(this.configuration, path); + } + + @Override + public DataObject readOperationalData(final InstanceIdentifier path) { + return this.readFrom(this.configuration, path); + } + + public DataObject readFrom(final FlowManagementReader store, final InstanceIdentifier path) { + if (Objects.equal(FRMRuntimeDataProvider.FLOWS_PATH, path)) { + return store.readAllFlows(); + } + if (FRMRuntimeDataProvider.FLOWS_PATH.contains(path)) { + return store.readFlow(this.toFlowKey(path)); + } + return null; + } + + @Override + public FlowCommitTransaction requestCommit(final DataModification, DataObject> modification) { + return new FlowCommitTransaction(this, modification); + } + + public FlowKey toFlowKey(final InstanceIdentifier identifier) { + Preconditions.> checkNotNull(identifier); + + Iterable path = identifier.getPathArguments(); + PathArgument get = path.iterator().next(); + final Identifier itemKey = Arguments. checkInstanceOf(get, IdentifiableItem.class).getKey(); + return Arguments. checkInstanceOf(itemKey, FlowKey.class); + } + + public RpcResult finish(final FlowCommitTransaction transaction) { + Iterable toRemove = transaction.getToRemove(); + for (final FlowConfig flow : toRemove) { + this.manager.removeStaticFlow(flow.getName(), flow.getNode()); + } + Iterable toUpdate = transaction.getToUpdate(); + for (final FlowConfig flow : toUpdate) { + this.manager.removeStaticFlow(flow.getName(), flow.getNode()); + this.manager.addStaticFlow(flow); + } + return Rpcs. getRpcResult(true, null, Collections. emptySet()); + } + + public RpcResult rollback(final FlowCommitTransaction transaction) { + return null; + } + + public DataProviderService getDataService() { + return this.dataService; + } + + public void setDataService(final DataProviderService dataService) { + this.dataService = dataService; + } + + public DataChangeListener, DataObject> getChangeListener() { + return this.changeListener; + } + + public void setChangeListener(final DataChangeListener, DataObject> changeListener) { + this.changeListener = changeListener; + } + + public IForwardingRulesManager getManager() { + return this.manager; + } + + public void setManager(final IForwardingRulesManager manager) { + this.manager = manager; + } +} diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend deleted file mode 100644 index 2d4e7d2c60..0000000000 --- a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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.frm.compatibility - -import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler -import org.opendaylight.controller.md.sal.common.api.data.DataModification -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction -import org.opendaylight.controller.sal.binding.api.data.DataProviderService -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows -import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.FlowsBuilder -import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager -import static com.google.common.base.Preconditions.*; -import static extension org.opendaylight.controller.md.frm.compatibility.FlowConfigMapping.*; -import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*; -import org.opendaylight.controller.sal.common.util.Arguments -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem -import org.opendaylight.yangtools.yang.common.RpcResult -import org.opendaylight.controller.forwardingrulesmanager.FlowConfig -import java.util.HashSet -import org.opendaylight.controller.sal.common.util.Rpcs -import java.util.Collections -import org.opendaylight.yangtools.yang.common.RpcError - -class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHandler, DataObject> { - - static val FLOWS_PATH = InstanceIdentifier.builder(Flows).toInstance; - - @Property - var DataProviderService dataService; - - @Property - var DataChangeListener changeListener; - - @Property - var IForwardingRulesManager manager; - - FlowManagementReader configuration = new ConfigurationReader(); - - def init() { - //dataService.registerDataChangeListener(FLOWS_PATH, changeListener); - dataService.registerCommitHandler(FLOWS_PATH, this); - } - - override readConfigurationData(InstanceIdentifier path) { - return readFrom(configuration, path); - } - - override DataObject readOperationalData(InstanceIdentifier path) { - return readFrom(configuration, path); - } - - def DataObject readFrom(FlowManagementReader store, InstanceIdentifier path) { - if (FLOWS_PATH == path) { - return store.readAllFlows(); - } - if (FLOWS_PATH.contains(path)) { - return store.readFlow(path.toFlowKey()); - } - return null; - } - - override FlowCommitTransaction requestCommit( - DataModification modification) { - return new FlowCommitTransaction(this,modification); - } - - def toFlowKey(InstanceIdentifier identifier) { - checkNotNull(identifier) - val item = Arguments.checkInstanceOf(identifier.path.get(1),IdentifiableItem); - val key = Arguments.checkInstanceOf(item.key,FlowKey) - return key; - } - - def RpcResult finish(FlowCommitTransaction transaction) { - for(flw: transaction.toRemove) { - manager.removeStaticFlow(flw.name,flw.node) - } - - for(flw: transaction.toUpdate) { - manager.removeStaticFlow(flw.name,flw.node); - manager.addStaticFlow(flw); - } - - return Rpcs.getRpcResult(true,null,Collections.emptySet()) - } - - def RpcResult rollback(FlowCommitTransaction transaction) { - // NOOP: We did not changed any state. - } - -} - -class ConfigurationReader implements FlowManagementReader { - - @Property - var IForwardingRulesManager manager; - - override Flows readAllFlows() { - val it = new FlowsBuilder(); - flow = manager.staticFlows.map[ - toConfigurationFlow(); - ] - return it.build(); - } - - override readFlow(FlowKey key) { - val flowCfg = manager.getStaticFlow(String.valueOf(key.id), key.node.toADNode()); - return flowCfg.toConfigurationFlow; - } -} - -public static class FlowCommitTransaction implements DataCommitTransaction, DataObject> { - - @Property - val DataModification, DataObject> modification; - - @Property - val FRMRuntimeDataProvider flowManager; - - @Property - val toAdd = new HashSet(); - - @Property - var Iterable toUpdate - - @Property - var Iterable toRemove - - - new(FRMRuntimeDataProvider flowManager,DataModification, DataObject> modification) { - super(); - _flowManager = flowManager; - _modification = modification; - processModification(); - } - - override finish() throws IllegalStateException { - return flowManager.finish(this); - } - - override rollback() throws IllegalStateException -{ - return flowManager.rollback(this); - } - - def processModification() { - val updated = modification.updatedConfigurationData.entrySet; - - val _toUpdate = updated.filter[key.isFlowPath].map[ - return (value as Flow).toFlowConfig - ] - toUpdate = _toUpdate as Iterable - - - val _toRemove = modification.removedConfigurationData.filter[isFlowPath].map[ - toFlowConfig - ] - toRemove = _toRemove as Iterable - - } -} diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowCommitTransaction.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowCommitTransaction.java new file mode 100644 index 0000000000..bf0050d6c0 --- /dev/null +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowCommitTransaction.java @@ -0,0 +1,99 @@ +/** + * 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.frm.compatibility; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +import org.opendaylight.controller.forwardingrulesmanager.FlowConfig; +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction; +import org.opendaylight.controller.md.sal.common.api.data.DataModification; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; + +public class FlowCommitTransaction implements DataCommitTransaction, DataObject> { + + private final DataModification, DataObject> modification; + private final HashSet toAdd = new HashSet(); + private final FRMRuntimeDataProvider flowManager; + private Iterable toUpdate; + private Iterable toRemove; + + public FlowCommitTransaction( + final FRMRuntimeDataProvider flowManager, + final DataModification, DataObject> modification) { + this.flowManager = flowManager; + this.modification = modification; + this.processModification(); + } + + @Override + public RpcResult finish() throws IllegalStateException { + return this.flowManager.finish(this); + } + + @Override + public RpcResult rollback() throws IllegalStateException { + return this.flowManager.rollback(this); + } + + public void processModification() { + final Set, DataObject>> updated = + this.modification.getUpdatedConfigurationData().entrySet(); + final List forUpdate = new ArrayList(updated.size()); + + if (updated != null && !(updated.isEmpty())) { + for (Entry, DataObject> entry : updated) { + if (FlowConfigMapping.isFlowPath(entry.getKey())) { + forUpdate.add(FlowConfigMapping.toFlowConfig((Flow) entry.getValue())); + } + } + } + this.toUpdate = Collections.unmodifiableCollection(forUpdate); + + final Set> removedConfigurationData = + this.modification.getRemovedConfigurationData(); + final List forRemove = new ArrayList(removedConfigurationData.size()); + + if (removedConfigurationData != null && !(removedConfigurationData.isEmpty())) { + for (InstanceIdentifier data : removedConfigurationData) { + if (FlowConfigMapping.isFlowPath(data)) { + forRemove.add(FlowConfigMapping.toFlowConfig(data)); + } + } + } + this.toRemove = Collections.unmodifiableCollection(forRemove); + } + + @Override + public DataModification, DataObject> getModification() { + return this.modification; + } + + public FRMRuntimeDataProvider getFlowManager() { + return this.flowManager; + } + + public HashSet getToAdd() { + return this.toAdd; + } + + public Iterable getToUpdate() { + return this.toUpdate; + } + + public Iterable getToRemove() { + return this.toRemove; + } +} diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.java new file mode 100644 index 0000000000..58c60ec1c5 --- /dev/null +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.java @@ -0,0 +1,109 @@ +/** + * 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.frm.compatibility; + +import java.text.MessageFormat; +import java.util.Iterator; + +import org.opendaylight.controller.forwardingrulesmanager.FlowConfig; +import org.opendaylight.controller.sal.compatibility.MDFlowMapping; +import org.opendaylight.controller.sal.compatibility.NodeMapping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded; +import org.opendaylight.yangtools.yang.binding.Identifiable; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FlowConfigMapping { + + private final static Logger LOG = LoggerFactory.getLogger(FlowConfigMapping.class); + + /* nodes/node/flow -> 0 / 1 / 2 */ + private static final int FLOW_KEY_IDENTIFIER_DEEP = 2; + + public static Flow toConfigurationFlow(final FlowConfig sourceCfg) { + final FlowAdded source = MDFlowMapping.flowAdded(sourceCfg.getFlow()); + final FlowBuilder flowBuilder = new FlowBuilder(); + flowBuilder.setInstructions(source.getInstructions()); + flowBuilder.setCookie(source.getCookie()); + flowBuilder.setHardTimeout(source.getHardTimeout()); + flowBuilder.setIdleTimeout(source.getIdleTimeout()); + flowBuilder.setMatch(source.getMatch()); + flowBuilder.setNode(source.getNode()); + + FlowKey flowKey = + new FlowKey(Long.valueOf(sourceCfg.getName()), flowBuilder.getNode()); + flowBuilder.setKey(flowKey); + return flowBuilder.build(); + } + + public static FlowConfig toFlowConfig(final Flow sourceCfg) { + try { + final FlowConfig flowConfig = new FlowConfig(); + flowConfig.setName(String.valueOf(sourceCfg.getId())); + flowConfig.setNode(NodeMapping.toADNode(sourceCfg.getNode())); + return flowConfig; + } catch (Exception e) { + String errMsg = MessageFormat.format("Convert from Flow {} to FlowConfig fail", sourceCfg); + LOG.error(errMsg, e); + throw new RuntimeException(errMsg, e); + } + } + + public static FlowConfig toFlowConfig(final InstanceIdentifier identifier) { + try { + PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(identifier); + if (pathArg != null) { + final FlowConfig flowConfig = new FlowConfig(); + FlowKey key = ((IdentifiableItem) pathArg).getKey(); + flowConfig.setName(String.valueOf(key.getId())); + flowConfig.setNode(NodeMapping.toADNode(key.getNode())); + return flowConfig; + } + return null; + } catch (Exception e) { + String errMsg = MessageFormat.format("Convert from InstanceIdentifier {} to FlowConfig fail", identifier); + LOG.error(errMsg, e); + throw new RuntimeException(errMsg, e); + } + } + + public static boolean isFlowPath(final InstanceIdentifier path) { + PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(path); + if (pathArg == null) { + return false; + } + if (pathArg instanceof IdentifiableItem) { + final Identifiable key = ((IdentifiableItem>) pathArg).getKey(); + if ((key instanceof FlowKey)) { + return true; + } + } + return false; + } + + private static PathArgument getSecondPathArgumentFromPath(final InstanceIdentifier path) { + if (path != null && path.getPathArguments() != null) { + Iterator iterator = path.getPathArguments().iterator(); + int deep = 0; + while (iterator.hasNext()) { + PathArgument pathArg = iterator.next(); + if (deep == FlowConfigMapping.FLOW_KEY_IDENTIFIER_DEEP) { + return pathArg; + } + deep++; + } + } + return null; + } +} diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend deleted file mode 100644 index e15b3c6c85..0000000000 --- a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.frm.compatibility - -import org.opendaylight.controller.forwardingrulesmanager.FlowConfig -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder - -import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.* -import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.* -import static org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.* - -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem -import org.opendaylight.yangtools.yang.binding.Identifiable - -class FlowConfigMapping { - - static def toConfigurationFlow(FlowConfig sourceCfg) { - val source = flowAdded(sourceCfg.flow); - val it = new FlowBuilder(); - instructions = source.instructions; - cookie = source.cookie; - hardTimeout = source.hardTimeout - idleTimeout = source.idleTimeout - match = source.match - node = source.node - key = new FlowKey(Long.parseLong(sourceCfg.name),node); - return it.build(); - } - - static def toFlowConfig(Flow sourceCfg) { - val it = new FlowConfig; - name = String.valueOf(sourceCfg.id); - node = sourceCfg.node.toADNode(); - - return it - } - - static def toFlowConfig(InstanceIdentifier identifier) { - val it = new FlowConfig() - val FlowKey key = ((identifier.path.get(2) as IdentifiableItem).key) - name = String.valueOf(key.id); - node = key.node.toADNode(); - - return it; - } - - static def boolean isFlowPath(InstanceIdentifier path) { - if(path.path.size < 2) return false; - if (path.path.get(2) instanceof IdentifiableItem) { - val IdentifiableItem> item = path.path.get(2) as IdentifiableItem>; - val Identifiable key = item.key; - if (key instanceof FlowKey) { - return true; - } - } - return false; - } -} diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java index 017263e264..cb61c8a095 100644 --- a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java +++ b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java index fad37ae4f3..c4c1ee9351 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java @@ -1,15 +1,16 @@ /** * 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.compatibility; -import com.google.common.base.Objects; -import com.google.common.base.Preconditions; -import org.eclipse.xtext.xbase.lib.Exceptions; +import java.util.Date; +import java.util.HashSet; +import java.util.List; + import org.opendaylight.controller.sal.common.util.Arguments; import org.opendaylight.controller.sal.core.AdvertisedBandwidth; import org.opendaylight.controller.sal.core.Bandwidth; @@ -58,36 +59,30 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; -import java.util.Date; -import java.util.HashSet; -import java.util.List; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; -@SuppressWarnings("all") -public class NodeMapping { +public final class NodeMapping { public final static String MD_SAL_TYPE = "MD_SAL"; - + private final static Class NODE_CLASS = Node.class; - + private final static Class NODECONNECTOR_CLASS = NodeConnector.class; - + private NodeMapping() { throw new UnsupportedOperationException("Utility class. Instantiation is not allowed."); } - + public static org.opendaylight.controller.sal.core.Node toADNode(final InstanceIdentifier node) throws ConstructionException { NodeId nodeId = NodeMapping.toNodeId(node); return NodeMapping.toADNode(nodeId); } - - public static org.opendaylight.controller.sal.core.Node toADNode(final NodeId id) { - try { + + public static org.opendaylight.controller.sal.core.Node toADNode(final NodeId id) throws ConstructionException { String aDNodeId = NodeMapping.toADNodeId(id); return new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, aDNodeId); - } catch (Throwable e) { - throw Exceptions.sneakyThrow(e); - } } - + public static NodeId toNodeId(final InstanceIdentifier node) { Preconditions.>checkNotNull(node); List path = node.getPath(); @@ -96,16 +91,16 @@ public class NodeMapping { Preconditions.checkArgument(size >= 2); final PathArgument arg = path.get(1); final IdentifiableItem item = Arguments.checkInstanceOf(arg, IdentifiableItem.class); - Identifier key = item.getKey(); + Identifier key = item.getKey(); final NodeKey nodeKey = Arguments.checkInstanceOf(key, NodeKey.class); return nodeKey.getId(); } - + public static String toADNodeId(final NodeId nodeId) { Preconditions.checkNotNull(nodeId); return nodeId.getValue(); } - + public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorRef source) throws ConstructionException { Preconditions.checkNotNull(source); final InstanceIdentifier path = Preconditions.>checkNotNull(source.getValue()); @@ -115,18 +110,14 @@ public class NodeMapping { final NodeConnectorKey connectorKey = Arguments.checkInstanceOf(item.getKey(), NodeConnectorKey.class); return NodeMapping.toADNodeConnector(connectorKey.getId(), NodeMapping.toNodeId(path)); } - - public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorId ncid, final NodeId nid) { - try { - String nodeConnectorType = NodeMapping.toNodeConnectorType(ncid, nid); - Object aDNodeConnectorId = NodeMapping.toADNodeConnectorId(ncid, nid); - org.opendaylight.controller.sal.core.Node aDNode = NodeMapping.toADNode(nid); - return new org.opendaylight.controller.sal.core.NodeConnector(nodeConnectorType, aDNodeConnectorId, aDNode); - } catch (Throwable e) { - throw Exceptions.sneakyThrow(e); - } + + public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorId ncid, final NodeId nid) throws ConstructionException { + String nodeConnectorType = NodeMapping.toNodeConnectorType(ncid, nid); + Object aDNodeConnectorId = NodeMapping.toADNodeConnectorId(ncid, nid); + org.opendaylight.controller.sal.core.Node aDNode = NodeMapping.toADNode(nid); + return new org.opendaylight.controller.sal.core.NodeConnector(nodeConnectorType, aDNodeConnectorId, aDNode); } - + public static String toNodeConnectorType(final NodeConnectorId ncId, final NodeId nodeId) { if (ncId.equals(toLocalNodeConnectorId(nodeId))) { return NodeConnectorIDType.SWSTACK; @@ -146,19 +137,19 @@ public class NodeMapping { } return nodeConnectorId.getValue(); } - + public static NodeConnectorId toControllerNodeConnectorId(final NodeId node) { return new NodeConnectorId(node.getValue() + ":" + 4294967293L); } - + public static NodeConnectorId toLocalNodeConnectorId(final NodeId node) { return new NodeConnectorId(node.getValue() + ":" + 4294967294L); } - + public static NodeConnectorId toNormalNodeConnectorId(final NodeId node) { return new NodeConnectorId(node.getValue() + ":" + 4294967290L); } - + public static NodeRef toNodeRef(final org.opendaylight.controller.sal.core.Node node) { Preconditions.checkArgument(MD_SAL_TYPE.equals(node.getType())); final String nodeId = Arguments.checkInstanceOf(node.getID(), String.class); @@ -166,7 +157,7 @@ public class NodeMapping { final InstanceIdentifier nodePath = InstanceIdentifier.builder(Nodes.class).child(NODE_CLASS, nodeKey).toInstance(); return new NodeRef(nodePath); } - + public static NodeConnectorRef toNodeConnectorRef(final org.opendaylight.controller.sal.core.NodeConnector nodeConnector) { final NodeRef node = NodeMapping.toNodeRef(nodeConnector.getNode()); @@ -187,14 +178,14 @@ public class NodeMapping { nodeConnectorId = new NodeConnectorId(Arguments.checkInstanceOf(nodeConnector.getID(), String.class)); } final NodeConnectorKey connectorKey = new NodeConnectorKey(nodeConnectorId); - final InstanceIdentifier path = InstanceIdentifier.builder(nodePath).child(NODECONNECTOR_CLASS, connectorKey).toInstance(); + final InstanceIdentifier path = nodePath.child(NODECONNECTOR_CLASS, connectorKey); return new NodeConnectorRef(path); } - + public static org.opendaylight.controller.sal.core.Node toADNode(final NodeRef node) throws ConstructionException { return NodeMapping.toADNode(node.getValue()); } - + public static HashSet toADNodeConnectorProperties(final NodeConnectorUpdated nc) { final FlowCapableNodeConnectorUpdated fcncu = nc.getAugmentation(FlowCapableNodeConnectorUpdated.class); if (!Objects.equal(fcncu, null)) { @@ -202,7 +193,7 @@ public class NodeMapping { } return new HashSet(); } - + public static HashSet toADNodeConnectorProperties(final NodeConnector nc) { final FlowCapableNodeConnector fcnc = nc.getAugmentation(FlowCapableNodeConnector.class); if (!Objects.equal(fcnc, null)) { @@ -210,7 +201,7 @@ public class NodeMapping { } return new HashSet(); } - + public static HashSet toADNodeConnectorProperties(final FlowNodeConnector fcncu) { final HashSet props = new HashSet<>(); @@ -239,11 +230,11 @@ public class NodeMapping { } return props; } - + public static Name toAdName(final String name) { return new Name(name); } - + public static Config toAdConfig(final PortConfig pc) { Config config = null; if (pc.isPORTDOWN()) { @@ -253,7 +244,7 @@ public class NodeMapping { } return config; } - + public static org.opendaylight.controller.sal.core.State toAdState(final State s) { org.opendaylight.controller.sal.core.State state = null; @@ -264,7 +255,7 @@ public class NodeMapping { } return state; } - + public static Bandwidth toAdBandwidth(final PortFeatures pf) { Bandwidth bw = null; if (pf.isTenMbHd() || pf.isTenMbFd()) { @@ -286,7 +277,7 @@ public class NodeMapping { } return bw; } - + public static AdvertisedBandwidth toAdAdvertizedBandwidth(final PortFeatures pf) { AdvertisedBandwidth abw = null; final Bandwidth bw = toAdBandwidth(pf); @@ -295,7 +286,7 @@ public class NodeMapping { } return abw; } - + public static SupportedBandwidth toAdSupportedBandwidth(final PortFeatures pf) { SupportedBandwidth sbw = null; final Bandwidth bw = toAdBandwidth(pf); @@ -304,7 +295,7 @@ public class NodeMapping { } return sbw; } - + public static PeerBandwidth toAdPeerBandwidth(final PortFeatures pf) { PeerBandwidth pbw = null; final Bandwidth bw = toAdBandwidth(pf); @@ -313,7 +304,7 @@ public class NodeMapping { } return pbw; } - + public static HashSet toADNodeProperties(final NodeUpdated nu) { final FlowCapableNodeUpdated fcnu = nu.getAugmentation(FlowCapableNodeUpdated.class); if (fcnu != null) { @@ -321,7 +312,7 @@ public class NodeMapping { } return new HashSet(); } - + public static HashSet toADNodeProperties(final FlowNode fcnu, final NodeId id) { final HashSet props = new HashSet<>(); @@ -348,13 +339,13 @@ public class NodeMapping { } return props; } - + public static TimeStamp toADTimestamp() { final Date date = new Date(); final TimeStamp timestamp = new TimeStamp(date.getTime(), "connectedSince"); return timestamp; } - + public static MacAddress toADMacAddress(final NodeId id) { final String nodeId = id.getValue().replaceAll("openflow:", ""); long lNodeId = Long.parseLong(nodeId); @@ -362,11 +353,11 @@ public class NodeMapping { byte[] bytesFromDpid = ToSalConversionsUtils.bytesFromDpid(lNodeId); return new MacAddress(bytesFromDpid); } - + public static Tables toADTables(final Short tables) { return new Tables(tables.byteValue()); } - + public static Capabilities toADCapabiliities(final List> capabilities) { int b = 0; @@ -389,7 +380,7 @@ public class NodeMapping { } return new Capabilities(b); } - + public static Buffers toADBuffers(final Long buffers) { return new Buffers(buffers.intValue()); } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyCommitHandler.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyCommitHandler.java new file mode 100644 index 0000000000..e798b681df --- /dev/null +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyCommitHandler.java @@ -0,0 +1,93 @@ +/* + * 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.compatibility.topology; + +import static org.opendaylight.controller.sal.compatibility.topology.TopologyMapping.toAdEdge; +import static org.opendaylight.controller.sal.compatibility.topology.TopologyMapping.toTopoEdgeUpdate; + +import java.util.Map.Entry; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader; +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.controller.sal.core.UpdateType; +import org.opendaylight.controller.sal.topology.IPluginOutTopologyService; +import org.opendaylight.controller.sal.topology.TopoEdgeUpdate; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TopologyCommitHandler implements DataChangeListener { + private static final Logger LOG = LoggerFactory.getLogger(TopologyCommitHandler.class); + + private IPluginOutTopologyService topologyPublisher; + + private final DataProviderService dataService; + + public TopologyCommitHandler(final DataProviderService dataService, final IPluginOutTopologyService topologyPub) { + this.topologyPublisher = topologyPub; + this.dataService = dataService; + } + + @Override + public void onDataChanged(final DataChangeEvent, DataObject> modification) { + CopyOnWriteArrayList msg = new CopyOnWriteArrayList(); + try { + TypeSafeDataReader reader = TypeSafeDataReader.forReader(dataService); + InstanceIdentifier topologyPath = InstanceIdentifier.builder(NetworkTopology.class) + .child(Topology.class, new TopologyKey(new TopologyId("flow:1"))).build(); + Topology topology = reader.readOperationalData(topologyPath); + + for (Entry, DataObject> entry : modification + .getCreatedOperationalData().entrySet()) { + if (entry.getValue() instanceof Link + && modification.getCreatedOperationalData().containsKey(entry.getKey())) { + msg.add(toTopoEdgeUpdate(toAdEdge((Link) entry.getValue(), topology), UpdateType.ADDED, reader)); + } + } + + for (Entry, DataObject> entry : modification + .getUpdatedOperationalData().entrySet()) { + if (entry.getValue() instanceof Link) { + msg.add(toTopoEdgeUpdate(toAdEdge((Link) entry.getValue(), topology), UpdateType.CHANGED, reader)); + } + } + for (InstanceIdentifier path : modification.getRemovedOperationalData()) { + if (path.getTargetType() == Link.class) { + Link link = (Link) modification.getOriginalOperationalData().get(path); + msg.add(toTopoEdgeUpdate(toAdEdge(link, topology), UpdateType.REMOVED, reader)); + } + + } + + if (topologyPublisher != null && msg != null && !msg.isEmpty()) { + topologyPublisher.edgeUpdate(msg); + } + + } catch (Exception e) { + LOG.error("Exception caught", e); + } + } + + protected IPluginOutTopologyService getTopologyPublisher() { + return topologyPublisher; + } + + protected void setTopologyPublisher(final IPluginOutTopologyService topologyPublisher) { + this.topologyPublisher = topologyPublisher; + } + +} diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyCommitHandler.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyCommitHandler.xtend deleted file mode 100644 index fcf86f236a..0000000000 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyCommitHandler.xtend +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.compatibility.topology - -import com.google.common.collect.FluentIterable -import java.util.concurrent.CopyOnWriteArrayList -import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader -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.binding.api.data.DataProviderService -import org.opendaylight.controller.sal.core.UpdateType -import org.opendaylight.controller.sal.topology.IPluginOutTopologyService -import org.opendaylight.controller.sal.topology.TopoEdgeUpdate -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import static extension org.opendaylight.controller.sal.compatibility.topology.TopologyMapping.* -import org.slf4j.LoggerFactory - -class TopologyCommitHandler implements DataCommitHandler, DataObject> { - static val LOG = LoggerFactory.getLogger(TopologyCommitHandler); - @Property - IPluginOutTopologyService topologyPublisher; - - @Property - DataProviderService dataService; - - new(DataProviderService dataService) { - _topologyPublisher = topologyPublisher - _dataService = dataService - } - - override requestCommit(DataModification, DataObject> modification) { - val msg = new CopyOnWriteArrayList() - try { - val reader = TypeSafeDataReader.forReader(dataService) - val topologyPath = InstanceIdentifier.builder(NetworkTopology).child(Topology, new TopologyKey(new TopologyId("flow:1"))).toInstance - val topology = reader.readOperationalData(topologyPath) - val adds = FluentIterable.from(modification.createdOperationalData.entrySet) - .filter[value instanceof Link] - .transform[(value as Link).toAdEdge(topology).toTopoEdgeUpdate(UpdateType.ADDED,reader)] - .toList - val updates = FluentIterable.from(modification.updatedOperationalData.entrySet) - .filter[!modification.createdOperationalData.containsKey(key) && (value instanceof Link)] - .transform[(value as Link).toAdEdge(topology).toTopoEdgeUpdate(UpdateType.ADDED,reader)] // Evidently the ADSAL does not expect edge 'CHANGED" - .toList - val removes = FluentIterable.from(modification.removedOperationalData) - .transform[reader.readOperationalData(it as InstanceIdentifier)] - .filter[it instanceof Link] - .transform[(it as Link).toAdEdge(topology).toTopoEdgeUpdate(UpdateType.REMOVED,reader)] - .toList - msg.addAll(adds) - msg.addAll(updates) - msg.addAll(removes) - } catch (Exception e) { - LOG.error("Exception caught",e) - } - return new TopologyTransaction(modification,topologyPublisher,dataService,msg) - } -} diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.xtend index 4aef75d991..21f2b35f40 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.xtend +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyProvider.xtend @@ -15,10 +15,10 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey import org.opendaylight.yangtools.yang.binding.DataObject import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yangtools.concepts.Registration -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link import org.slf4j.LoggerFactory +import org.opendaylight.yangtools.concepts.ListenerRegistration +import org.opendaylight.controller.sal.binding.api.data.DataChangeListener class TopologyProvider implements AutoCloseable{ static val LOG = LoggerFactory.getLogger(TopologyProvider); @@ -30,8 +30,9 @@ class TopologyProvider implements AutoCloseable{ @Property DataProviderService dataService; - Registration,DataObject>> commitHandlerRegistration; - + ListenerRegistration listenerRegistration + + def void start() { } @@ -40,18 +41,17 @@ class TopologyProvider implements AutoCloseable{ LOG.error("dataService not set"); return; } - commitHandler = new TopologyCommitHandler(dataService) - commitHandler.setTopologyPublisher(topologyPublisher) + commitHandler = new TopologyCommitHandler(dataService,topologyPublisher); val InstanceIdentifier path = InstanceIdentifier.builder(NetworkTopology) .child(Topology,new TopologyKey(new TopologyId("flow:1"))) .child(Link) .toInstance(); - commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler); + listenerRegistration = dataService.registerDataChangeListener(path,commitHandler); LOG.info("TopologyProvider started") } override close() throws Exception { - commitHandlerRegistration.close + listenerRegistration.close } def setTopologyPublisher(IPluginOutTopologyService topologyPublisher) { diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyTransaction.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyTransaction.xtend deleted file mode 100644 index 4de78cab0d..0000000000 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/topology/TopologyTransaction.xtend +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.compatibility.topology - -import java.util.Collections -import java.util.List -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.binding.api.data.DataProviderService -import org.opendaylight.controller.sal.topology.IPluginOutTopologyService -import org.opendaylight.controller.sal.topology.TopoEdgeUpdate -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yangtools.yang.common.RpcResult -import org.slf4j.LoggerFactory - -class TopologyTransaction implements DataCommitTransaction, DataObject> { - static val LOG = LoggerFactory.getLogger(TopologyTransaction); - @Property - val DataModification, DataObject> modification; - - @Property - IPluginOutTopologyService topologyPublisher; - - @Property - DataProviderService dataService; - @Property - List edgeUpdates; - - new(DataModification, DataObject> modification,IPluginOutTopologyService topologyPublisher, - DataProviderService dataService,List edgeUpdates) { - _modification = modification; - _topologyPublisher = topologyPublisher - _dataService = dataService - _edgeUpdates = edgeUpdates - } - override finish() throws IllegalStateException { - - if(topologyPublisher != null && _edgeUpdates != null && !edgeUpdates.empty) { - topologyPublisher.edgeUpdate(edgeUpdates) - } - - return new RpcResultTo() - } - - override getModification() { - return _modification; - } - - override rollback() throws IllegalStateException { - // NOOP - } -} -class RpcResultTo implements RpcResult { - - override getErrors() { - return Collections.emptySet - } - - override getResult() { - return null; - } - - override isSuccessful() { - return true; - } - -} diff --git a/opendaylight/md-sal/feature/pom.xml b/opendaylight/md-sal/feature/pom.xml new file mode 100644 index 0000000000..c08c3e5606 --- /dev/null +++ b/opendaylight/md-sal/feature/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.1-SNAPSHOT + + mdsal-features + + pom + + + features.xml + + + + + + + + true + src/main/resources + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + + diff --git a/opendaylight/md-sal/feature/src/main/resources/features.xml b/opendaylight/md-sal/feature/src/main/resources/features.xml new file mode 100644 index 0000000000..f816018519 --- /dev/null +++ b/opendaylight/md-sal/feature/src/main/resources/features.xml @@ -0,0 +1,49 @@ + + + + + odl-mdsal-commons + odl-mdsal-broker + odl-mdsal-restconf + + + yangtools-concepts + yangtools-binding + mvn:org.opendaylight.controller/sal-common/${project.version} + mvn:org.opendaylight.controller/sal-common-api/${project.version} + mvn:org.opendaylight.controller/sal-common-impl/${project.version} + mvn:org.opendaylight.controller/sal-common-util/${project.version} + wrap:mvn:com.google.guava/guava/${guava.version} + wrap:mvn:org.eclipse.xtend/org.eclipse.xtend.lib/${xtend.version} + + + yangtools-concepts + yangtools-binding + odl-mdsal-commons + odl-config-subsystem + mvn:org.opendaylight.controller/sal-core-api/${project.version} + mvn:org.opendaylight.controller/sal-core-spi/${project.version} + mvn:org.opendaylight.controller/sal-broker-impl/${project.version} + mvn:org.opendaylight.controller/sal-binding-api/${project.version} + mvn:org.opendaylight.controller/sal-binding-config/${project.version} + mvn:org.opendaylight.controller/sal-binding-broker-impl/${project.version} + mvn:org.opendaylight.controller/sal-binding-util/${project.version} + mvn:org.opendaylight.controller/sal-connector-api/${project.version} + + + odl-mdsal-broker + mvn:org.opendaylight.controller/sal-rest-connector/${project.version} + wrap:mvn:com.google.code.gson/gson/${gson.version} + wrap:mvn:com.sun.jersey/jersey-core/${jersey.version} + wrap:mvn:com.sun.jersey/jersey-server/${jersey.version} + mvn:org.opendaylight.controller.thirdparty/com.sun.jersey.jersey-servlet/${jersey.version} + wrap:mvn:io.netty/netty-buffer/${netty.version} + wrap:mvn:io.netty/netty-codec/${netty.version} + wrap:mvn:io.netty/netty-codec-http/${netty.version} + wrap:mvn:io.netty/netty-common/${netty.version} + wrap:mvn:io.netty/netty-handler/${netty.version} + wrap:mvn:io.netty/netty-transport/${netty.version} + + \ No newline at end of file diff --git a/opendaylight/md-sal/forwardingrules-manager/pom.xml b/opendaylight/md-sal/forwardingrules-manager/pom.xml index 919a53c364..9bd63d3c3b 100644 --- a/opendaylight/md-sal/forwardingrules-manager/pom.xml +++ b/opendaylight/md-sal/forwardingrules-manager/pom.xml @@ -54,10 +54,6 @@ - - org.eclipse.xtend - xtend-maven-plugin - diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java new file mode 100644 index 0000000000..426f4ba2d5 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractChangeListener.java @@ -0,0 +1,94 @@ +/** + * 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.frm; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicLong; + +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * + * @author Vaclav Demcak + * + */ +public abstract class AbstractChangeListener implements DataChangeListener { + + private final AtomicLong txNum = new AtomicLong(); + private String transactionId; + + @Override + public void onDataChanged(DataChangeEvent, DataObject> changeEvent) { + this.transactionId = this.newTransactionIdentifier().toString(); + + final Set, DataObject>> createdEntries = + changeEvent.getCreatedConfigurationData().entrySet(); + final Set, DataObject>> updatedEntries = + new HashSet, DataObject>>(); + + Set, DataObject>> updateConfigEntrySet = + changeEvent.getUpdatedConfigurationData().entrySet(); + updatedEntries.addAll(updateConfigEntrySet); + updatedEntries.removeAll(createdEntries); + + final Set> removeEntriesInstanceIdentifiers = + changeEvent.getRemovedConfigurationData(); + + for (final Entry, DataObject> createdEntry : createdEntries) { + InstanceIdentifier c_key = createdEntry.getKey(); + DataObject c_value = createdEntry.getValue(); + this.add(c_key, c_value); + } + + for (final Entry, DataObject> updatedEntrie : updatedEntries) { + Map, DataObject> origConfigData = + changeEvent.getOriginalConfigurationData(); + + InstanceIdentifier u_key = updatedEntrie.getKey(); + final DataObject originalFlow = origConfigData.get(u_key); + final DataObject updatedFlow = updatedEntrie.getValue(); + this.update(u_key, originalFlow, updatedFlow); + } + + for (final InstanceIdentifier instanceId : removeEntriesInstanceIdentifiers) { + Map, DataObject> origConfigData = + changeEvent.getOriginalConfigurationData(); + + final DataObject removeValue = origConfigData.get(instanceId); + this.remove(instanceId, removeValue); + } + } + + public String getTransactionId() { + return this.transactionId; + } + + private Object newTransactionIdentifier() { + return "DOM-" + txNum.getAndIncrement(); + } + + protected abstract void validate() throws IllegalStateException; + + protected abstract void remove( + final InstanceIdentifier identifier, + final DataObject remove); + + protected abstract void update( + final InstanceIdentifier identifier, + final DataObject original, final DataObject update); + + protected abstract void add( + final InstanceIdentifier identifier, + final DataObject add); +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractTransaction.xtend deleted file mode 100644 index cb1e90d6ba..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/AbstractTransaction.xtend +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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.frm - -import java.util.Collections -import java.util.HashSet -import java.util.Map.Entry -import java.util.Set -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.Rpcs -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yangtools.yang.common.RpcError - -abstract class AbstractTransaction implements DataCommitTransaction, DataObject> { - - @Property - val DataModification, DataObject> modification; - - new(DataModification, DataObject> modification) { - _modification = modification; - } - - def void validate() throws IllegalStateException - - override finish() throws IllegalStateException { - validate() - callRpcs(); - return Rpcs.getRpcResult(true, null, Collections.emptySet()); - } - - override getModification() { - return _modification; - } - - override rollback() throws IllegalStateException { - rollbackRpcs(); - return Rpcs.getRpcResult(true, null, Collections.emptySet()); - } - - def private callRpcs() { - val Set, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet(); - - /* - * This little dance is because updatedEntries contains both created and modified entries - * The reason I created a new HashSet is because the collections we are returned are immutable. - */ - val Set, DataObject>> updatedEntries = new HashSet, DataObject>>(); - updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet()); - updatedEntries.removeAll(createdEntries); - - val Set> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData(); - for (Entry, DataObject> entry : createdEntries) { - add(entry.key,entry.value); - } - for (Entry, DataObject> entry : updatedEntries) { - val originalFlow = _modification.originalConfigurationData.get(entry.key); - val updatedFlow = entry.value - update(entry.key, originalFlow ,updatedFlow); - } - - for (InstanceIdentifier instanceId : removeEntriesInstanceIdentifiers ) { - val removeValue = _modification.getOriginalConfigurationData.get(instanceId); - remove(instanceId,removeValue); - } - } - - def void remove(InstanceIdentifier identifier, DataObject remove) - - def void update(InstanceIdentifier identifier, DataObject original, DataObject update) - - def void add(InstanceIdentifier identifier, DataObject add) - - def private rollbackRpcs() { - val Set, DataObject>> createdEntries = _modification.getCreatedConfigurationData().entrySet(); - - /* - * This little dance is because updatedEntries contains both created and modified entries - * The reason I created a new HashSet is because the collections we are returned are immutable. - */ - val Set, DataObject>> updatedEntries = new HashSet, DataObject>>(); - updatedEntries.addAll(_modification.getUpdatedConfigurationData().entrySet()); - updatedEntries.removeAll(createdEntries); - - val Set> removeEntriesInstanceIdentifiers = _modification.getRemovedConfigurationData(); - for (Entry, DataObject> entry : createdEntries) { - remove(entry.key,entry.value); // because we are rolling back, remove what we would have added. - } - for (Entry, DataObject> entry : updatedEntries) { - val originalFlow = _modification.originalConfigurationData.get(entry.key); - val updatedFlow = entry.value - update(entry.key, updatedFlow ,originalFlow);// because we are rolling back, replace the updated with the original - } - - for (InstanceIdentifier instanceId : removeEntriesInstanceIdentifiers ) { - val removeValue = _modification.getOriginalConfigurationData.get(instanceId); - add(instanceId,removeValue);// because we are rolling back, add what we would have removed. - } - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.java new file mode 100644 index 0000000000..929c489eaf --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.java @@ -0,0 +1,61 @@ +/** + * 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.frm; + +import org.opendaylight.controller.frm.flow.FlowProvider; +import org.opendaylight.controller.frm.group.GroupProvider; +import org.opendaylight.controller.frm.meter.MeterProvider; +import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService; +import org.osgi.framework.BundleContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FRMActivator extends AbstractBindingAwareProvider { + + private final static Logger LOG = LoggerFactory.getLogger(FRMActivator.class); + + private static FlowProvider flowProvider = new FlowProvider(); + private static GroupProvider groupProvider = new GroupProvider(); + private static MeterProvider meterProvider = new MeterProvider(); + + @Override + public void onSessionInitiated(final ProviderContext session) { + DataProviderService flowSalService = session.getSALService(DataProviderService.class); + FRMActivator.flowProvider.setDataService(flowSalService); + SalFlowService rpcFlowSalService = session.getRpcService(SalFlowService.class); + FRMActivator.flowProvider.setSalFlowService(rpcFlowSalService); + FRMActivator.flowProvider.start(); + DataProviderService groupSalService = session.getSALService(DataProviderService.class); + FRMActivator.groupProvider.setDataService(groupSalService); + SalGroupService rpcGroupSalService = session.getRpcService(SalGroupService.class); + FRMActivator.groupProvider.setSalGroupService(rpcGroupSalService); + FRMActivator.groupProvider.start(); + DataProviderService meterSalService = session.getSALService(DataProviderService.class); + FRMActivator.meterProvider.setDataService(meterSalService); + SalMeterService rpcMeterSalService = session.getRpcService(SalMeterService.class); + FRMActivator.meterProvider.setSalMeterService(rpcMeterSalService); + FRMActivator.meterProvider.start(); + } + + @Override + protected void stopImpl(final BundleContext context) { + try { + FRMActivator.flowProvider.close(); + FRMActivator.groupProvider.close(); + FRMActivator.meterProvider.close(); + } catch (Throwable e) { + LOG.error("Unexpected error by stopping FRMActivator", e); + throw new RuntimeException(e); + } + } + } \ No newline at end of file diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.xtend deleted file mode 100644 index 8ec9d79bfc..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/FRMActivator.xtend +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.frm - -import org.opendaylight.controller.frm.flow.FlowProvider -import org.opendaylight.controller.frm.group.GroupProvider -import org.opendaylight.controller.frm.meter.MeterProvider -import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider -import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext -import org.opendaylight.controller.sal.binding.api.data.DataProviderService -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService -import org.osgi.framework.BundleContext -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService - -class FRMActivator extends AbstractBindingAwareProvider { - - static var FlowProvider provider = new FlowProvider(); - static var GroupProvider groupProvider = new GroupProvider(); - static var MeterProvider meterProvider = new MeterProvider(); - - override onSessionInitiated(ProviderContext session) { - provider.dataService = session.getSALService(DataProviderService) - provider.salFlowService = session.getRpcService(SalFlowService); - provider.start(); - - groupProvider.dataService = session.getSALService(DataProviderService) - groupProvider.salGroupService = session.getRpcService(SalGroupService) - groupProvider.start(); - - meterProvider.dataService = session.getSALService(DataProviderService) - meterProvider.salMeterService = session.getRpcService(SalMeterService) - meterProvider.start(); - } - - override protected stopImpl(BundleContext context) { - provider.close(); - groupProvider.close(); - meterProvider.close(); - } - -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java new file mode 100644 index 0000000000..df086c7acc --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowChangeListener.java @@ -0,0 +1,120 @@ +/** + * 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.frm.flow; + +import org.opendaylight.controller.frm.AbstractChangeListener; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Vaclav Demcak + * + */ +public class FlowChangeListener extends AbstractChangeListener { + + private final static Logger LOG = LoggerFactory.getLogger(FlowChangeListener.class); + + private final SalFlowService salFlowService; + + public SalFlowService getSalFlowService() { + return this.salFlowService; + } + + public FlowChangeListener(final SalFlowService manager) { + this.salFlowService = manager; + } + + @Override + protected void validate() throws IllegalStateException { + FlowTransactionValidator.validate(this); + } + + @Override + protected void remove(InstanceIdentifier identifier, DataObject removeDataObj) { + if ((removeDataObj instanceof Flow)) { + + final Flow flow = ((Flow) removeDataObj); + final InstanceIdentifier tableInstanceId = identifier.
firstIdentifierOf(Table.class); + final InstanceIdentifier nodeInstanceId = identifier. firstIdentifierOf(Node.class); + final RemoveFlowInputBuilder builder = new RemoveFlowInputBuilder(flow); + + builder.setFlowRef(new FlowRef(identifier)); + builder.setNode(new NodeRef(nodeInstanceId)); + builder.setFlowTable(new FlowTableRef(tableInstanceId)); + + Uri uri = new Uri(this.getTransactionId()); + builder.setTransactionUri(uri); + this.salFlowService.removeFlow((RemoveFlowInput) builder.build()); + LOG.debug("Transaction {} - Removed Flow has removed flow: {}", new Object[]{uri, removeDataObj}); + } + } + + @Override + protected void update(InstanceIdentifier identifier, DataObject original, DataObject update) { + if (original instanceof Flow && update instanceof Flow) { + + final Flow originalFlow = ((Flow) original); + final Flow updatedFlow = ((Flow) update); + final InstanceIdentifier nodeInstanceId = identifier.firstIdentifierOf(Node.class); + final UpdateFlowInputBuilder builder = new UpdateFlowInputBuilder(); + + builder.setNode(new NodeRef(nodeInstanceId)); + builder.setFlowRef(new FlowRef(identifier)); + + Uri uri = new Uri(this.getTransactionId()); + builder.setTransactionUri(uri); + + builder.setUpdatedFlow((UpdatedFlow) (new UpdatedFlowBuilder(updatedFlow)).build()); + builder.setOriginalFlow((OriginalFlow) (new OriginalFlowBuilder(originalFlow)).build()); + + this.salFlowService.updateFlow((UpdateFlowInput) builder.build()); + LOG.debug("Transaction {} - Update Flow has updated flow {} with {}", new Object[]{uri, original, update}); + } + } + + @Override + protected void add(InstanceIdentifier identifier, DataObject addDataObj) { + if ((addDataObj instanceof Flow)) { + + final Flow flow = ((Flow) addDataObj); + final InstanceIdentifier
tableInstanceId = identifier.
firstIdentifierOf(Table.class); + final InstanceIdentifier nodeInstanceId = identifier. firstIdentifierOf(Node.class); + final AddFlowInputBuilder builder = new AddFlowInputBuilder(flow); + + builder.setNode(new NodeRef(nodeInstanceId)); + builder.setFlowRef(new FlowRef(identifier)); + builder.setFlowTable(new FlowTableRef(tableInstanceId)); + + Uri uri = new Uri(this.getTransactionId()); + builder.setTransactionUri(uri); + this.salFlowService.addFlow((AddFlowInput) builder.build()); + LOG.debug("Transaction {} - Add Flow has added flow: {}", new Object[]{uri, addDataObj}); + } + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowCommitHandler.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowCommitHandler.xtend deleted file mode 100644 index 188bfcd3ef..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowCommitHandler.xtend +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.frm.flow - -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.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService - -class FlowCommitHandler implements DataCommitHandler, DataObject> { - - @Property - val SalFlowService salFlowService; - - new(SalFlowService manager) { - _salFlowService = manager; - } - - override requestCommit(DataModification, DataObject> modification) { - return new FlowTransaction(modification,salFlowService); - } - -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java new file mode 100644 index 0000000000..afdd628bbb --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.java @@ -0,0 +1,70 @@ +/** + * 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.frm.flow; + +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.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FlowProvider implements AutoCloseable { + + private final static Logger LOG = LoggerFactory.getLogger(FlowProvider.class); + + private SalFlowService salFlowService; + private DataProviderService dataService; + + /* DataChangeListener */ + private FlowChangeListener flowDataChangeListener; + ListenerRegistration flowDataChangeListenerRegistration; + + public void start() { + /* Build Path */ + InstanceIdentifierBuilder nodesBuilder = InstanceIdentifier. builder(Nodes.class); + InstanceIdentifierBuilder nodeChild = nodesBuilder. child(Node.class); + InstanceIdentifierBuilder augmentFlowCapNode = nodeChild. augmentation(FlowCapableNode.class); + InstanceIdentifierBuilder
tableChild = augmentFlowCapNode.
child(Table.class); + InstanceIdentifierBuilder flowChild = tableChild. child(Flow.class); + final InstanceIdentifier flowDataObjectPath = flowChild.toInstance(); + + /* DataChangeListener registration */ + this.flowDataChangeListener = new FlowChangeListener(this.salFlowService); + this.flowDataChangeListenerRegistration = this.dataService.registerDataChangeListener(flowDataObjectPath, flowDataChangeListener); + LOG.info("Flow Config Provider started."); + } + + protected DataModificationTransaction startChange() { + return this.dataService.beginTransaction(); + } + + @Override + public void close() throws Exception { + if(flowDataChangeListenerRegistration != null){ + flowDataChangeListenerRegistration.close(); + } + } + + public void setDataService(final DataProviderService dataService) { + this.dataService = dataService; + } + + public void setSalFlowService(final SalFlowService salFlowService) { + this.salFlowService = salFlowService; + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.xtend deleted file mode 100644 index d2ed5410ed..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowProvider.xtend +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.frm.flow - -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler -import org.opendaylight.controller.sal.binding.api.data.DataProviderService -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node -import org.opendaylight.yangtools.concepts.Registration -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.slf4j.LoggerFactory - -class FlowProvider implements AutoCloseable { - - @Property - DataProviderService dataService; - - @Property - SalFlowService salFlowService; - - FlowCommitHandler commitHandler - - Registration,DataObject>> commitHandlerRegistration; - - static val LOG = LoggerFactory.getLogger(FlowProvider); - - def void start() { - commitHandler = new FlowCommitHandler(salFlowService) - val InstanceIdentifier path = InstanceIdentifier.builder(Nodes) - .child(Node) - .augmentation(FlowCapableNode) - .child(Table) - .child(Flow) - .toInstance(); - commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler); - LOG.info("Flow Config Provider started."); - } - - protected def startChange() { - return dataService.beginTransaction; - } - - override close() throws Exception { - throw new UnsupportedOperationException("TODO: auto-generated method stub") - } - -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend deleted file mode 100644 index 26846ad493..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransaction.xtend +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.frm.flow - -import org.opendaylight.controller.frm.AbstractTransaction -import org.opendaylight.controller.md.sal.common.api.data.DataModification -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri - -class FlowTransaction extends AbstractTransaction { - - @Property - val SalFlowService salFlowService; - - - new(DataModification, DataObject> modification,SalFlowService salFlowService) { - super(modification) - _salFlowService = salFlowService; - } - - override remove(InstanceIdentifier instanceId, DataObject obj) { - if(obj instanceof Flow) { - val flow = (obj as Flow) - val tableInstanceId = instanceId.firstIdentifierOf(Table); - val nodeInstanceId = instanceId.firstIdentifierOf(Node); - val builder = new RemoveFlowInputBuilder(flow); - builder.setFlowRef(new FlowRef(instanceId)); - builder.setNode(new NodeRef(nodeInstanceId)); - builder.setFlowTable(new FlowTableRef(tableInstanceId)); - builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); - _salFlowService.removeFlow(builder.build()); - } - } - - override update(InstanceIdentifier instanceId, DataObject originalObj, DataObject updatedObj) { - if(originalObj instanceof Flow && updatedObj instanceof Flow) { - val originalFlow = (originalObj as Flow) - val updatedFlow = (updatedObj as Flow) - val nodeInstanceId = instanceId.firstIdentifierOf(Node); - val builder = new UpdateFlowInputBuilder(); - builder.setNode(new NodeRef(nodeInstanceId)); - builder.setFlowRef(new FlowRef(instanceId)); - val ufb = new UpdatedFlowBuilder(updatedFlow); - builder.setUpdatedFlow((ufb.build())); - builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); - val ofb = new OriginalFlowBuilder(originalFlow); - builder.setOriginalFlow(ofb.build()); - _salFlowService.updateFlow(builder.build()); - - } - } - - override add(InstanceIdentifier instanceId, DataObject obj) { - if(obj instanceof Flow) { - val flow = (obj as Flow) - val tableInstanceId = instanceId.firstIdentifierOf(Table); - val nodeInstanceId = instanceId.firstIdentifierOf(Node); - val builder = new AddFlowInputBuilder(flow); - builder.setNode(new NodeRef(nodeInstanceId)); - builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); - builder.setFlowRef(new FlowRef(instanceId)); - builder.setFlowTable(new FlowTableRef(tableInstanceId)); - _salFlowService.addFlow(builder.build()); - } - } - - override validate() throws IllegalStateException { - FlowTransactionValidator.validate(this) - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransactionValidator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransactionValidator.java index 7c6f1ff1cb..4ef93a55e9 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransactionValidator.java +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/flow/FlowTransactionValidator.java @@ -1,6 +1,6 @@ -/* +/** * 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 @@ -9,8 +9,7 @@ package org.opendaylight.controller.frm.flow; public class FlowTransactionValidator { - public static void validate(FlowTransaction transaction) throws IllegalStateException { + public static void validate(FlowChangeListener transaction) throws IllegalStateException { // NOOP } - } diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java new file mode 100644 index 0000000000..1260f0ec53 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupChangeListener.java @@ -0,0 +1,113 @@ +/** + * 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.frm.group; + +import org.opendaylight.controller.frm.AbstractChangeListener; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroup; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroup; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Vaclav Demcak + * + */ +public class GroupChangeListener extends AbstractChangeListener { + + private final static Logger LOG = LoggerFactory.getLogger(GroupChangeListener.class); + + private final SalGroupService salGroupService; + + public SalGroupService getSalGroupService() { + return this.salGroupService; + } + + public GroupChangeListener(final SalGroupService manager) { + this.salGroupService = manager; + } + + @Override + protected void validate() throws IllegalStateException { + GroupTransactionValidator.validate(this); + } + + @Override + protected void remove(InstanceIdentifier identifier, DataObject removeDataObj) { + if ((removeDataObj instanceof Group)) { + + final Group group = ((Group) removeDataObj); + final InstanceIdentifier nodeInstanceId = identifier. firstIdentifierOf(Node.class); + final RemoveGroupInputBuilder builder = new RemoveGroupInputBuilder(group); + + builder.setNode(new NodeRef(nodeInstanceId)); + builder.setGroupRef(new GroupRef(identifier)); + + Uri uri = new Uri(this.getTransactionId()); + builder.setTransactionUri(uri); + this.salGroupService.removeGroup((RemoveGroupInput) builder.build()); + LOG.debug("Transaction {} - Remove Group has removed group: {}", new Object[]{uri, removeDataObj}); + } + } + + @Override + protected void update(InstanceIdentifier identifier, DataObject original, DataObject update) { + if (original instanceof Group && update instanceof Group) { + + final Group originalGroup = ((Group) original); + final Group updatedGroup = ((Group) update); + final InstanceIdentifier nodeInstanceId = identifier. firstIdentifierOf(Node.class); + final UpdateGroupInputBuilder builder = new UpdateGroupInputBuilder(); + + builder.setNode(new NodeRef(nodeInstanceId)); + builder.setGroupRef(new GroupRef(identifier)); + + Uri uri = new Uri(this.getTransactionId()); + builder.setTransactionUri(uri); + + builder.setUpdatedGroup((UpdatedGroup) (new UpdatedGroupBuilder(updatedGroup)).build()); + builder.setOriginalGroup((OriginalGroup) (new OriginalGroupBuilder(originalGroup)).build()); + + this.salGroupService.updateGroup((UpdateGroupInput) builder.build()); + LOG.debug("Transaction {} - Update Group has updated group {} with group {}", new Object[]{uri, original, update}); + } + } + + @Override + protected void add(InstanceIdentifier identifier, DataObject addDataObj) { + if ((addDataObj instanceof Group)) { + final Group group = ((Group) addDataObj); + final InstanceIdentifier nodeInstanceId = identifier. firstIdentifierOf(Node.class); + final AddGroupInputBuilder builder = new AddGroupInputBuilder(group); + + builder.setNode(new NodeRef(nodeInstanceId)); + builder.setGroupRef(new GroupRef(identifier)); + + Uri uri = new Uri(this.getTransactionId()); + builder.setTransactionUri(uri); + this.salGroupService.addGroup((AddGroupInput) builder.build()); + LOG.debug("Transaction {} - Add Group has added group: {}", new Object[]{uri, addDataObj}); + } + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupCommitHandler.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupCommitHandler.xtend deleted file mode 100644 index b6d385126f..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupCommitHandler.xtend +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.frm.group - -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler -import org.opendaylight.controller.md.sal.common.api.data.DataModification -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier - -class GroupCommitHandler implements DataCommitHandler, DataObject> { - - @Property - val SalGroupService groupService; - - new(SalGroupService groupService) { - _groupService = groupService; - } - - override requestCommit(DataModification, DataObject> modification) { - return new GroupTransaction(modification,groupService); - } - -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java new file mode 100644 index 0000000000..14b1b6f2fd --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.java @@ -0,0 +1,67 @@ +/** + * 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.frm.group; + +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.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GroupProvider implements AutoCloseable { + + private final static Logger LOG = LoggerFactory.getLogger(GroupProvider.class); + + private SalGroupService salGroupService; + private DataProviderService dataService; + + /* DataChangeListener */ + private GroupChangeListener groupDataChangeListener; + ListenerRegistration groupDataChangeListenerRegistration; + + public void start() { + /* Build Path */ + InstanceIdentifierBuilder nodesBuilder = InstanceIdentifier. builder(Nodes.class); + InstanceIdentifierBuilder nodeChild = nodesBuilder. child(Node.class); + InstanceIdentifierBuilder augmentFlowCapNode = nodeChild. augmentation(FlowCapableNode.class); + InstanceIdentifierBuilder groupChild = augmentFlowCapNode. child(Group.class); + final InstanceIdentifier groupDataObjectPath = groupChild.toInstance(); + + /* DataChangeListener registration */ + this.groupDataChangeListener = new GroupChangeListener(this.salGroupService); + this.groupDataChangeListenerRegistration = this.dataService.registerDataChangeListener(groupDataObjectPath, groupDataChangeListener); + LOG.info("Group Config Provider started."); + } + + protected DataModificationTransaction startChange() { + return this.dataService.beginTransaction(); + } + + public void close() throws Exception { + if(groupDataChangeListenerRegistration != null){ + groupDataChangeListenerRegistration.close(); + } + } + + public void setDataService(final DataProviderService dataService) { + this.dataService = dataService; + } + + public void setSalGroupService(final SalGroupService salGroupService) { + this.salGroupService = salGroupService; + } +} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.xtend deleted file mode 100644 index 4ded8b6151..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupProvider.xtend +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.frm.group - -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler -import org.opendaylight.controller.sal.binding.api.data.DataProviderService -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node -import org.opendaylight.yangtools.concepts.Registration -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.slf4j.LoggerFactory - -class GroupProvider implements AutoCloseable { - - @Property - DataProviderService dataService; - - @Property - SalGroupService salGroupService; - - GroupCommitHandler commitHandler - - Registration,DataObject>> commitHandlerRegistration; - - static val LOG = LoggerFactory.getLogger(GroupProvider); - - def void start() { - commitHandler = new GroupCommitHandler(salGroupService) - val InstanceIdentifier path = InstanceIdentifier.builder(Nodes) - .child(Node) - .augmentation(FlowCapableNode) - .child(Group) - .toInstance(); - commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler); - LOG.info("Group Config Provider started."); - } - - protected def startChange() { - return dataService.beginTransaction; - } - - override close() throws Exception { - throw new UnsupportedOperationException("TODO: auto-generated method stub") - } - -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend deleted file mode 100644 index e8d9982bdc..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransaction.xtend +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.frm.group - -import org.opendaylight.controller.frm.AbstractTransaction -import org.opendaylight.controller.md.sal.common.api.data.DataModification -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.OriginalGroupBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri - -class GroupTransaction extends AbstractTransaction { - - @Property - val SalGroupService groupService; - - new(DataModification, DataObject> modification,SalGroupService groupService) { - super(modification) - _groupService = groupService; - } - - override remove(InstanceIdentifier instanceId, DataObject obj) { - if(obj instanceof Group) { - val group = (obj as Group) - val nodeInstanceId = instanceId.firstIdentifierOf(Node); - val builder = new RemoveGroupInputBuilder(group); - builder.setNode(new NodeRef(nodeInstanceId)); - builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); - builder.setGroupRef(new GroupRef(instanceId)); - _groupService.removeGroup(builder.build()); - } - } - - override update(InstanceIdentifier instanceId, DataObject originalObj, DataObject updatedObj) { - if(originalObj instanceof Group && updatedObj instanceof Group) { - val originalGroup = (originalObj as Group) - val updatedGroup = (updatedObj as Group) - val nodeInstanceId = instanceId.firstIdentifierOf(Node); - val builder = new UpdateGroupInputBuilder(); - builder.setNode(new NodeRef(nodeInstanceId)); - builder.setGroupRef(new GroupRef(instanceId)); - val ufb = new UpdatedGroupBuilder(updatedGroup); - builder.setUpdatedGroup((ufb.build())); - builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); - val ofb = new OriginalGroupBuilder(originalGroup); - builder.setOriginalGroup(ofb.build()); - _groupService.updateGroup(builder.build()); - - } - } - - override add(InstanceIdentifier instanceId, DataObject obj) { - if(obj instanceof Group) { - val group = (obj as Group) - val nodeInstanceId = instanceId.firstIdentifierOf(Node); - val builder = new AddGroupInputBuilder(group); - builder.setNode(new NodeRef(nodeInstanceId)); - builder.setGroupRef(new GroupRef(instanceId)); - builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); - _groupService.addGroup(builder.build()); - } - } - - override validate() throws IllegalStateException { - GroupTransactionValidator.validate(this) - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java index 92baf7bdf0..88eea0db34 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/group/GroupTransactionValidator.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the @@ -9,8 +9,7 @@ package org.opendaylight.controller.frm.group; public class GroupTransactionValidator { - public static void validate(GroupTransaction transaction) throws IllegalStateException { + public static void validate(GroupChangeListener transaction) throws IllegalStateException { // NOOP } - } diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java new file mode 100644 index 0000000000..839e556fbc --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterChangeListener.java @@ -0,0 +1,114 @@ +/** + * 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.frm.meter; + +import org.opendaylight.controller.frm.AbstractChangeListener; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Vaclav Demcak + * + */ +public class MeterChangeListener extends AbstractChangeListener { + + private final static Logger LOG = LoggerFactory.getLogger(MeterChangeListener.class); + + private final SalMeterService salMeterService; + + public SalMeterService getSalMeterService() { + return this.salMeterService; + } + + public MeterChangeListener(final SalMeterService manager) { + this.salMeterService = manager; + } + + @Override + protected void validate() throws IllegalStateException { + MeterTransactionValidator.validate(this); + } + + @Override + protected void remove(InstanceIdentifier identifier, DataObject removeDataObj) { + if ((removeDataObj instanceof Meter)) { + + final Meter meter = ((Meter) removeDataObj); + final InstanceIdentifier nodeInstanceId = identifier. firstIdentifierOf(Node.class); + final RemoveMeterInputBuilder builder = new RemoveMeterInputBuilder(meter); + + builder.setNode(new NodeRef(nodeInstanceId)); + builder.setMeterRef(new MeterRef(identifier)); + + Uri uri = new Uri(this.getTransactionId()); + builder.setTransactionUri(uri); + this.salMeterService.removeMeter((RemoveMeterInput) builder.build()); + LOG.debug("Transaction {} - Remove Meter has removed meter: {}", new Object[]{uri, removeDataObj}); + } + } + + @Override + protected void update(InstanceIdentifier identifier, DataObject original, DataObject update) { + if (original instanceof Meter && update instanceof Meter) { + + final Meter originalMeter = ((Meter) original); + final Meter updatedMeter = ((Meter) update); + final InstanceIdentifier nodeInstanceId = identifier. firstIdentifierOf(Node.class); + final UpdateMeterInputBuilder builder = new UpdateMeterInputBuilder(); + + builder.setNode(new NodeRef(nodeInstanceId)); + builder.setMeterRef(new MeterRef(identifier)); + + Uri uri = new Uri(this.getTransactionId()); + builder.setTransactionUri(uri); + + builder.setUpdatedMeter((UpdatedMeter) (new UpdatedMeterBuilder(updatedMeter)).build()); + builder.setOriginalMeter((OriginalMeter) (new OriginalMeterBuilder(originalMeter)).build()); + + this.salMeterService.updateMeter((UpdateMeterInput) builder.build()); + LOG.debug("Transaction {} - Update Meter has updated meter {} with {}", new Object[]{uri, original, update}); + } + } + + @Override + protected void add(InstanceIdentifier identifier, DataObject addDataObj) { + if ((addDataObj instanceof Meter)) { + + final Meter meter = ((Meter) addDataObj); + final InstanceIdentifier nodeInstanceId = identifier. firstIdentifierOf(Node.class); + final AddMeterInputBuilder builder = new AddMeterInputBuilder(meter); + + builder.setNode(new NodeRef(nodeInstanceId)); + builder.setMeterRef(new MeterRef(identifier)); + + Uri uri = new Uri(this.getTransactionId()); + builder.setTransactionUri(uri); + this.salMeterService.addMeter((AddMeterInput) builder.build()); + LOG.debug("Transaction {} - Add Meter has added meter: {}", new Object[]{uri, addDataObj}); + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterCommitHandler.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterCommitHandler.xtend deleted file mode 100644 index d5292f0f8b..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterCommitHandler.xtend +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.frm.meter - -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler -import org.opendaylight.controller.md.sal.common.api.data.DataModification -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier - -class FlowCommitHandler implements DataCommitHandler, DataObject> { - - @Property - val SalMeterService salMeterService; - - new(SalMeterService manager) { - _salMeterService = manager; - } - - override requestCommit(DataModification, DataObject> modification) { - return new MeterTransaction(modification,salMeterService); - } - -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java new file mode 100644 index 0000000000..620801fba5 --- /dev/null +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.java @@ -0,0 +1,67 @@ +/** + * 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.frm.meter; + +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.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MeterProvider implements AutoCloseable { + + private final static Logger LOG = LoggerFactory.getLogger(MeterProvider.class); + + private DataProviderService dataService; + private SalMeterService salMeterService; + + /* DataChangeListener */ + private MeterChangeListener meterDataChangeListener; + ListenerRegistration meterDataChangeListenerRegistration; + + public void start() { + /* Build Path */ + InstanceIdentifierBuilder nodesBuilder = InstanceIdentifier. builder(Nodes.class); + InstanceIdentifierBuilder nodeChild = nodesBuilder. child(Node.class); + InstanceIdentifierBuilder augmentFlowCapNode = nodeChild. augmentation(FlowCapableNode.class); + InstanceIdentifierBuilder meterChild = augmentFlowCapNode. child(Meter.class); + final InstanceIdentifier meterDataObjectPath = meterChild.toInstance(); + + /* DataChangeListener registration */ + this.meterDataChangeListener = new MeterChangeListener(this.salMeterService); + this.meterDataChangeListenerRegistration = this.dataService.registerDataChangeListener(meterDataObjectPath, meterDataChangeListener); + LOG.info("Meter Config Provider started."); + } + + protected DataModificationTransaction startChange() { + return this.dataService.beginTransaction(); + } + + public void close() throws Exception { + if(meterDataChangeListenerRegistration != null){ + meterDataChangeListenerRegistration.close(); + } + } + + public void setDataService(final DataProviderService dataService) { + this.dataService = dataService; + } + + public void setSalMeterService(final SalMeterService salMeterService) { + this.salMeterService = salMeterService; + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.xtend deleted file mode 100644 index 323da57075..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterProvider.xtend +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.frm.meter - -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler -import org.opendaylight.controller.sal.binding.api.data.DataProviderService -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService -import org.opendaylight.yangtools.concepts.Registration -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.slf4j.LoggerFactory - -class MeterProvider implements AutoCloseable { - - @Property - DataProviderService dataService; - - @Property - SalMeterService salMeterService; - - FlowCommitHandler commitHandler - - Registration,DataObject>> commitHandlerRegistration; - - static val LOG = LoggerFactory.getLogger(MeterProvider); - - def void start() { - commitHandler = new FlowCommitHandler(salMeterService) - val InstanceIdentifier path = InstanceIdentifier.builder(Nodes) - .child(Node) - .augmentation(FlowCapableNode) - .child(Meter) - .toInstance(); - commitHandlerRegistration = dataService.registerCommitHandler(path,commitHandler); - LOG.info("Meter Config Provider started."); - } - - protected def startChange() { - return dataService.beginTransaction; - } - - override close() throws Exception { - throw new UnsupportedOperationException("TODO: auto-generated method stub") - } - -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend deleted file mode 100644 index 491fa082a2..0000000000 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransaction.xtend +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.frm.meter - -import org.opendaylight.controller.frm.AbstractTransaction -import org.opendaylight.controller.md.sal.common.api.data.DataModification -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInputBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInputBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.OriginalMeterBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri - -class MeterTransaction extends AbstractTransaction { - - @Property - val SalMeterService salMeterService; - - new(DataModification, DataObject> modification,SalMeterService salMeterService) { - super(modification) - _salMeterService = salMeterService; - } - - override remove(InstanceIdentifier instanceId, DataObject obj) { - if(obj instanceof Meter) { - val meter = (obj as Meter) - val nodeInstanceId = instanceId.firstIdentifierOf(Node); - val builder = new RemoveMeterInputBuilder(meter); - builder.setNode(new NodeRef(nodeInstanceId)); - builder.setMeterRef(new MeterRef(instanceId)); - builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); - _salMeterService.removeMeter(builder.build()); - } - } - - override update(InstanceIdentifier instanceId, DataObject originalObj, DataObject updatedObj) { - if(originalObj instanceof Meter && updatedObj instanceof Meter) { - val originalMeter = (originalObj as Meter) - val updatedMeter = (updatedObj as Meter) - val nodeInstanceId = instanceId.firstIdentifierOf(Node); - val builder = new UpdateMeterInputBuilder(); - builder.setNode(new NodeRef(nodeInstanceId)); - builder.setMeterRef(new MeterRef(instanceId)); - val ufb = new UpdatedMeterBuilder(updatedMeter); - builder.setUpdatedMeter((ufb.build())); - builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); - val ofb = new OriginalMeterBuilder(originalMeter); - builder.setOriginalMeter(ofb.build()); - _salMeterService.updateMeter(builder.build()); - - } - } - - override add(InstanceIdentifier instanceId, DataObject obj) { - if(obj instanceof Meter) { - val meter = (obj as Meter) - val nodeInstanceId = instanceId.firstIdentifierOf(Node); - val builder = new AddMeterInputBuilder(meter); - builder.setNode(new NodeRef(nodeInstanceId)); - builder.setMeterRef(new MeterRef(instanceId)); - builder.setTransactionUri(new Uri(modification.getIdentifier() as String)); - _salMeterService.addMeter(builder.build()); - } - } - - override validate() throws IllegalStateException { - MeterTransactionValidator.validate(this) - } -} diff --git a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java index b16739cc5b..c8fba23b93 100644 --- a/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java +++ b/opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/frm/meter/MeterTransactionValidator.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the @@ -9,8 +9,7 @@ package org.opendaylight.controller.frm.meter; public class MeterTransactionValidator { - public static void validate(MeterTransaction transaction) throws IllegalStateException { + public static void validate(MeterChangeListener transaction) throws IllegalStateException { // NOOP } - } diff --git a/opendaylight/md-sal/inventory-manager/pom.xml b/opendaylight/md-sal/inventory-manager/pom.xml index 40a79033a7..1706996ce4 100644 --- a/opendaylight/md-sal/inventory-manager/pom.xml +++ b/opendaylight/md-sal/inventory-manager/pom.xml @@ -15,10 +15,6 @@ com.google.guava guava - - org.eclipse.xtend - org.eclipse.xtend.lib - org.opendaylight.controller sal-binding-api @@ -50,10 +46,6 @@ - - org.eclipse.xtend - xtend-maven-plugin - diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java new file mode 100644 index 0000000000..7e4190f1df --- /dev/null +++ b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java @@ -0,0 +1,67 @@ +/** + * 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.inventory.manager; + +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.binding.NotificationListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FlowCapableInventoryProvider implements AutoCloseable { + + private final static Logger LOG = LoggerFactory.getLogger(FlowCapableInventoryProvider.class); + + private DataProviderService dataService; + private NotificationProviderService notificationService; + private Registration listenerRegistration; + private final NodeChangeCommiter changeCommiter = new NodeChangeCommiter(FlowCapableInventoryProvider.this); + + public void start() { + this.listenerRegistration = this.notificationService.registerNotificationListener(this.changeCommiter); + LOG.info("Flow Capable Inventory Provider started."); + } + + protected DataModificationTransaction startChange() { + DataProviderService _dataService = this.dataService; + return _dataService.beginTransaction(); + } + + @Override + public void close() { + try { + LOG.info("Flow Capable Inventory Provider stopped."); + if (this.listenerRegistration != null) { + this.listenerRegistration.close(); + } + } catch (Exception e) { + String errMsg = "Error by stop Flow Capable Inventory Provider."; + LOG.error(errMsg, e); + throw new RuntimeException(errMsg, e); + } + } + + public DataProviderService getDataService() { + return this.dataService; + } + + public void setDataService(final DataProviderService dataService) { + this.dataService = dataService; + } + + public NotificationProviderService getNotificationService() { + return this.notificationService; + } + + public void setNotificationService( + final NotificationProviderService notificationService) { + this.notificationService = notificationService; + } +} diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.xtend b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.xtend deleted file mode 100644 index ec8da8693f..0000000000 --- a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.xtend +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.md.inventory.manager - -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated -import org.opendaylight.controller.sal.binding.api.NotificationProviderService -import org.opendaylight.controller.sal.binding.api.data.DataProviderService -import org.opendaylight.yangtools.concepts.Registration -import org.opendaylight.yangtools.yang.binding.NotificationListener -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey -import static extension org.opendaylight.controller.md.inventory.manager.InventoryMapping.* -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey -import org.slf4j.LoggerFactory - -class FlowCapableInventoryProvider implements AutoCloseable { - - - static val LOG = LoggerFactory.getLogger(FlowCapableInventoryProvider); - - @Property - DataProviderService dataService; - - @Property - NotificationProviderService notificationService; - val NodeChangeCommiter changeCommiter = new NodeChangeCommiter(this); - - Registration listenerRegistration - - def void start() { - listenerRegistration = notificationService.registerNotificationListener(changeCommiter); - LOG.info("Flow Capable Inventory Provider started."); - - } - - protected def startChange() { - return dataService.beginTransaction; - } - - override close() { - LOG.info("Flow Capable Inventory Provider stopped."); - listenerRegistration?.close(); - } - -} \ No newline at end of file diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryActivator.java b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryActivator.java new file mode 100644 index 0000000000..6c06088fc4 --- /dev/null +++ b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryActivator.java @@ -0,0 +1,34 @@ +/** + * 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.inventory.manager; + +import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.osgi.framework.BundleContext; + +public class InventoryActivator extends AbstractBindingAwareProvider { + + private static FlowCapableInventoryProvider provider = new FlowCapableInventoryProvider(); + + @Override + public void onSessionInitiated(final ProviderContext session) { + DataProviderService salDataService = session. getSALService(DataProviderService.class); + NotificationProviderService salNotifiService = + session. getSALService(NotificationProviderService.class); + InventoryActivator.provider.setDataService(salDataService); + InventoryActivator.provider.setNotificationService(salNotifiService); + InventoryActivator.provider.start(); + } + + @Override + protected void stopImpl(final BundleContext context) { + InventoryActivator.provider.close(); + } +} diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryActivator.xtend b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryActivator.xtend deleted file mode 100644 index 5d76924be7..0000000000 --- a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryActivator.xtend +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.md.inventory.manager - -import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider -import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext -import org.osgi.framework.BundleContext -import org.opendaylight.controller.sal.binding.api.data.DataProviderService -import org.opendaylight.controller.sal.binding.api.NotificationProviderService - -class InventoryActivator extends AbstractBindingAwareProvider { - - static var FlowCapableInventoryProvider provider = new FlowCapableInventoryProvider(); - - override onSessionInitiated(ProviderContext session) { - provider.dataService = session.getSALService(DataProviderService) - provider.notificationService = session.getSALService(NotificationProviderService) - provider.start(); - } - - override protected stopImpl(BundleContext context) { - provider.close(); - } - -} diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryMapping.java b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryMapping.java new file mode 100644 index 0000000000..928ae761f2 --- /dev/null +++ b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryMapping.java @@ -0,0 +1,44 @@ +/** + * 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.inventory.manager; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNodeConnector; + +public class InventoryMapping { + + public static FlowCapableNodeConnector toInventoryAugment(final FlowNodeConnector updated) { + if ((updated instanceof FlowCapableNodeConnector)) { + return ((FlowCapableNodeConnector) updated); + } + final FlowCapableNodeConnectorBuilder builder = new FlowCapableNodeConnectorBuilder(); + builder.setAdvertisedFeatures(updated.getAdvertisedFeatures()); + builder.setConfiguration(updated.getConfiguration()); + builder.setCurrentFeature(updated.getCurrentFeature()); + builder.setCurrentSpeed(updated.getCurrentSpeed()); + builder.setHardwareAddress(updated.getHardwareAddress()); + builder.setMaximumSpeed(updated.getMaximumSpeed()); + builder.setName(updated.getName()); + builder.setPeerFeatures(updated.getPeerFeatures()); + builder.setPortNumber(updated.getPortNumber()); + builder.setState(updated.getState()); + builder.setSupported(updated.getSupported()); + return builder.build(); + } + + public static FlowCapableNode toInventoryAugment(final FlowNode source) { + if ((source instanceof FlowCapableNode)) { + return ((FlowCapableNode) source); + } + return (new FlowCapableNodeBuilder(source)).build(); + } +} diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryMapping.xtend b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryMapping.xtend deleted file mode 100644 index 6f1ef5e5bb..0000000000 --- a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryMapping.xtend +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.md.inventory.manager - -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNodeConnector -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNode -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder - -class InventoryMapping { - - static def FlowCapableNodeConnector toInventoryAugment(FlowNodeConnector updated) { - if (updated instanceof FlowCapableNodeConnector) { - return updated as FlowCapableNodeConnector; - } - val it = new FlowCapableNodeConnectorBuilder(); - advertisedFeatures = updated.advertisedFeatures - configuration = updated.configuration - currentFeature = updated.currentFeature - currentSpeed = updated.currentSpeed - hardwareAddress = updated.hardwareAddress - maximumSpeed = updated.maximumSpeed - name = updated.name - peerFeatures = updated.peerFeatures - portNumber = updated.portNumber - state = updated.state - supported = updated.supported - return build(); - } - - static def FlowCapableNode toInventoryAugment(FlowNode source) { - if (source instanceof FlowCapableNode) { - return source as FlowCapableNode; - } - val it = new FlowCapableNodeBuilder(source); - return build(); - } - -} diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java index ebb3de7dca..2a3d8fd37e 100644 --- a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java +++ b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java @@ -7,7 +7,6 @@ */ package org.opendaylight.controller.md.inventory.manager; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; @@ -20,7 +19,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeCon import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated; @@ -38,10 +36,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Objects; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.JdkFutureAdapters; -@SuppressWarnings("all") public class NodeChangeCommiter implements OpendaylightInventoryListener { - private final static Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class); + + protected final static Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class); private final FlowCapableInventoryProvider manager; @@ -58,15 +59,10 @@ public class NodeChangeCommiter implements OpendaylightInventoryListener { final NodeConnectorRef ref = connector.getNodeConnectorRef(); final DataModificationTransaction it = this.getManager().startChange(); - NodeChangeCommiter.LOG.debug("removing node connector {} ", ref.getValue()); + LOG.debug("removing node connector {} ", ref.getValue()); it.removeOperationalData(ref.getValue()); Future> commitResult = it.commit(); - try { - commitResult.get(); - } catch (InterruptedException | ExecutionException e) { - LOG.error("Node Connector {} not removed.", ref.getValue(), e); - } - + listenOnTransactionState(it.getIdentifier(), commitResult, "nodeConnector removal", ref.getValue()); } @Override @@ -75,7 +71,7 @@ public class NodeChangeCommiter implements OpendaylightInventoryListener { final NodeConnectorRef ref = connector.getNodeConnectorRef(); final FlowCapableNodeConnectorUpdated flowConnector = connector .getAugmentation(FlowCapableNodeConnectorUpdated.class); - final DataModificationTransaction it = this.getManager().startChange(); + final DataModificationTransaction it = this.manager.startChange(); final NodeConnectorBuilder data = new NodeConnectorBuilder(connector); NodeConnectorId id = connector.getId(); NodeConnectorKey nodeConnectorKey = new NodeConnectorKey(id); @@ -86,39 +82,22 @@ public class NodeChangeCommiter implements OpendaylightInventoryListener { data.addAugmentation(FlowCapableNodeConnector.class, augment); } InstanceIdentifier value = ref.getValue(); - String string = value.toString(); - String plus = ("updating node connector : " + string); - NodeChangeCommiter.LOG.debug(plus); - InstanceIdentifier value1 = ref.getValue(); + LOG.debug("updating node connector : {}.", value); NodeConnector build = data.build(); - it.putOperationalData((value1), build); + it.putOperationalData((value), build); Future> commitResult = it.commit(); - try { - commitResult.get(); - } catch (InterruptedException | ExecutionException e) { - LOG.error("Node Connector {} not updated.", ref.getValue(), e); - } - + listenOnTransactionState(it.getIdentifier(), commitResult, "nodeConnector update", ref.getValue()); } @Override public synchronized void onNodeRemoved(final NodeRemoved node) { final NodeRef ref = node.getNodeRef(); - FlowCapableInventoryProvider manager = this.getManager(); - final DataModificationTransaction it = manager.startChange(); - InstanceIdentifier value = ref.getValue(); - String string = value.toString(); - String plus = ("removing node : " + string); - NodeChangeCommiter.LOG.debug(plus); - InstanceIdentifier value1 = ref.getValue(); - it.removeOperationalData((value1)); + final DataModificationTransaction it = this.manager.startChange(); + LOG.debug("removing node : {}", ref.getValue()); + it.removeOperationalData((ref.getValue())); Future> commitResult = it.commit(); - try { - commitResult.get(); - } catch (InterruptedException | ExecutionException e) { - LOG.error("Node {} not removed.", ref.getValue(), e); - } + listenOnTransactionState(it.getIdentifier(), commitResult, "node removal", ref.getValue()); } @Override @@ -127,33 +106,49 @@ public class NodeChangeCommiter implements OpendaylightInventoryListener { final NodeRef ref = node.getNodeRef(); final FlowCapableNodeUpdated flowNode = node . getAugmentation(FlowCapableNodeUpdated.class); - FlowCapableInventoryProvider manager = this.getManager(); - final DataModificationTransaction it = manager.startChange(); - NodeBuilder nodeBuilder = new NodeBuilder(node); - final NodeBuilder data = nodeBuilder; - NodeId id = node.getId(); - NodeKey nodeKey = new NodeKey(id); - data.setKey(nodeKey); + final DataModificationTransaction it = this.manager.startChange(); + final NodeBuilder nodeBuilder = new NodeBuilder(node); + nodeBuilder.setKey(new NodeKey(node.getId())); boolean equals = Objects.equal(flowNode, null); if (equals) { return; } final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode); - data.addAugmentation(FlowCapableNode.class, augment); + nodeBuilder.addAugmentation(FlowCapableNode.class, augment); InstanceIdentifier value = ref.getValue(); - InstanceIdentifierBuilder builder = InstanceIdentifier. builder(((InstanceIdentifier) value)); + InstanceIdentifierBuilder builder = ((InstanceIdentifier) value).builder(); InstanceIdentifierBuilder augmentation = builder . augmentation(FlowCapableNode.class); final InstanceIdentifier path = augmentation.build(); - NodeChangeCommiter.LOG.debug("updating node :{} ", path); + LOG.debug("updating node :{} ", path); it.putOperationalData(path, augment); Future> commitResult = it.commit(); - try { - commitResult.get(); - } catch (InterruptedException | ExecutionException e) { - LOG.error("Node {} not updated.", ref.getValue(), e); - } - + listenOnTransactionState(it.getIdentifier(), commitResult, "node update", ref.getValue()); + } + + /** + * @param txId transaction identificator + * @param future transaction result + * @param action performed by transaction + * @param nodeConnectorPath target value + */ + private static void listenOnTransactionState(final Object txId, Future> future, + final String action, final InstanceIdentifier nodeConnectorPath) { + Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future),new FutureCallback>() { + + @Override + public void onFailure(Throwable t) { + LOG.error("Action {} [{}] failed for Tx:{}", action, nodeConnectorPath, txId, t); + + } + + @Override + public void onSuccess(RpcResult result) { + if(!result.isSuccessful()) { + LOG.error("Action {} [{}] failed for Tx:{}", action, nodeConnectorPath, txId); + } + } + }); } } diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index 4e933c5bcf..a13d2bb06f 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -59,6 +59,11 @@ sal-remoterpc-connector/implementation + + sal-rest-docgen + + + feature @@ -89,19 +94,6 @@ - - - org.opendaylight.yangtools - yang-maven-plugin - [0,) - - generate-sources - - - - - - net.alchim31.maven @@ -169,7 +161,6 @@ org.opendaylight.yangtools yang-maven-plugin - ${yangtools.version} org.opendaylight.controller diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java index 14006a3fce..750defc0e9 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java @@ -7,11 +7,10 @@ */ package org.opendaylight.controller.config.yang.md.sal.binding.impl; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import java.util.Hashtable; import java.util.Map.Entry; import java.util.Set; + import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder; import org.opendaylight.yangtools.concepts.Delegator; import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl; @@ -28,6 +27,9 @@ import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + /** * */ @@ -61,14 +63,13 @@ public final class RuntimeMappingModule extends @Override public java.lang.AutoCloseable createInstance() { - + RuntimeGeneratedMappingServiceProxy potential = tryToReuseGlobalInstance(); if(potential != null) { return potential; } - RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl(); - service.setPool(SingletonHolder.CLASS_POOL); - service.init(); + + final RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl(SingletonHolder.CLASS_POOL); bundleContext.registerService(SchemaServiceListener.class, service, new Hashtable()); return service; } @@ -98,7 +99,7 @@ public final class RuntimeMappingModule extends BindingIndependentMappingService, // Delegator, // AutoCloseable { - + private BindingIndependentMappingService delegate; private ServiceReference reference; private BundleContext bundleContext; @@ -111,35 +112,42 @@ public final class RuntimeMappingModule extends this.delegate = Preconditions.checkNotNull(delegate); } + @Override public CodecRegistry getCodecRegistry() { return delegate.getCodecRegistry(); } + @Override public CompositeNode toDataDom(DataObject data) { return delegate.toDataDom(data); } + @Override public Entry toDataDom( Entry, DataObject> entry) { return delegate.toDataDom(entry); } + @Override public InstanceIdentifier toDataDom( org.opendaylight.yangtools.yang.binding.InstanceIdentifier path) { return delegate.toDataDom(path); } + @Override public DataObject dataObjectFromDataDom( org.opendaylight.yangtools.yang.binding.InstanceIdentifier path, CompositeNode result) throws DeserializationException { return delegate.dataObjectFromDataDom(path, result); } + @Override public org.opendaylight.yangtools.yang.binding.InstanceIdentifier fromDataDom(InstanceIdentifier entry) throws DeserializationException { return delegate.fromDataDom(entry); } + @Override public Set getRpcQNamesFor(Class service) { return delegate.getRpcQNamesFor(service); } @@ -149,10 +157,11 @@ public final class RuntimeMappingModule extends return delegate.getRpcServiceClassFor(namespace,revision); } + @Override public DataContainer dataObjectFromDataDom(Class inputClass, CompositeNode domInput) { return delegate.dataObjectFromDataDom(inputClass, domInput); } - + @Override public void close() throws Exception { if(delegate != null) { diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java index 685a91979c..2a866a94b3 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java @@ -96,10 +96,14 @@ public abstract class AbstractForwardedDataBroker implements Delegator> entry : normalized .entrySet()) { try { - Entry, DataObject> binding = getCodec().toBinding(entry); - newMap.put(binding.getKey(), binding.getValue()); + Optional, DataObject>> potential = getCodec().toBinding( + entry); + if (potential.isPresent()) { + Entry, DataObject> binding = potential.get(); + newMap.put(binding.getKey(), binding.getValue()); + } } catch (DeserializationException e) { - LOG.debug("Omitting {}", entry, e); + LOG.warn("Failed to transform {}, omitting it", entry, e); } } return newMap; @@ -110,17 +114,20 @@ public abstract class AbstractForwardedDataBroker implements Delegator> hashSet = new HashSet<>(); for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath : normalized) { try { - InstanceIdentifier binding = getCodec().toBinding(normalizedPath); - hashSet.add(binding); + Optional> potential = getCodec().toBinding(normalizedPath); + if (potential.isPresent()) { + InstanceIdentifier binding = potential.get(); + hashSet.add(binding); + } } catch (DeserializationException e) { - LOG.debug("Omitting {}", normalizedPath, e); + LOG.warn("Failed to transform {}, omitting it", normalizedPath, e); } } return hashSet; } protected Optional toBindingData(final InstanceIdentifier path, final NormalizedNode data) { - if(path.isWildcarded()) { + if (path.isWildcarded()) { return Optional.absent(); } @@ -207,7 +214,11 @@ public abstract class AbstractForwardedDataBroker implements Delegator apply(@Nullable final Optional> normalizedNode) { - try { - final DataObject dataObject = normalizedNode.isPresent() ? codec.toBinding(path, - normalizedNode.get()) : null; - if(dataObject != null) { + if (normalizedNode.isPresent()) { + final DataObject dataObject; + try { + dataObject = codec.toBinding(path, normalizedNode.get()); + } catch (DeserializationException e) { + LOG.warn("Failed to create dataobject from node {}", normalizedNode.get(), e); + throw new IllegalStateException("Failed to create dataobject", e); + } + + if (dataObject != null) { updateCache(store, path, dataObject); + return Optional.of(dataObject); } - return Optional.fromNullable(dataObject); - } catch (DeserializationException e) { - Exceptions.sneakyThrow(e); } - return null; + return Optional.absent(); } }); } @@ -108,7 +111,28 @@ public class AbstractForwardedTransaction> normalized = codec .toNormalizedNode(path, data); - org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey(); + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey(); + ensureParentsByMerge(writeTransaction, store, normalizedPath, path); + LOG.debug("Tx: {} : Putting data {}", getDelegate().getIdentifier(), normalizedPath); + writeTransaction.put(store, normalizedPath, normalized.getValue()); + } + + protected void doMergeWithEnsureParents(final DOMDataReadWriteTransaction writeTransaction, + final LogicalDatastoreType store, final InstanceIdentifier path, final DataObject data) { + invalidateCache(store, path); + final Entry> normalized = codec + .toNormalizedNode(path, data); + + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey(); + ensureParentsByMerge(writeTransaction, store, normalizedPath, path); + LOG.debug("Tx: {} : Merge data {}",getDelegate().getIdentifier(),normalizedPath); + writeTransaction.merge(store, normalizedPath, normalized.getValue()); + } + + private void ensureParentsByMerge(final DOMDataReadWriteTransaction writeTransaction, + final LogicalDatastoreType store, + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath, + final InstanceIdentifier path) { List currentArguments = new ArrayList<>(); DataNormalizationOperation currentOp = codec.getDataNormalizer().getRootOperation(); Iterator iterator = normalizedPath.getPath().iterator(); @@ -135,8 +159,6 @@ public class AbstractForwardedTransaction binding) { - final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath = bindingToLegacy.toDataDom(binding); - final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = legacyToNormalized.toNormalized(legacyPath); - LOG.trace("InstanceIdentifier Path {} Serialization: Legacy representation {}, Normalized representation: {}",binding,legacyPath,normalized); - return normalized; + + // Used instance-identifier codec do not support serialization of last + // path + // argument if it is Augmentation (behaviour expected by old datastore) + // in this case, we explicitly check if last argument is augmentation + // to process it separately + if (isAugmentationIdentifier(binding)) { + return toNormalizedAugmented(binding); + } + return toNormalizedImpl(binding); } public Entry> toNormalizedNode( @@ -58,40 +81,122 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener { public Entry> toNormalizedNode( final Entry, DataObject> binding) { - Entry legacyEntry = bindingToLegacy.toDataDom(binding); - Entry> normalizedEntry = legacyToNormalized.toNormalized(legacyEntry); - LOG.trace("Serialization of {}, Legacy Representation: {}, Normalized Representation: {}",binding,legacyEntry,normalizedEntry); - if(Augmentation.class.isAssignableFrom(binding.getKey().getTargetType())) { - - for(DataContainerChild child : ((DataContainerNode) normalizedEntry.getValue()).getValue()) { - if(child instanceof AugmentationNode) { - ImmutableList childArgs = ImmutableList.builder() - .addAll(normalizedEntry.getKey().getPath()) - .add(child.getIdentifier()) - .build(); - org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(childArgs); - return new SimpleEntry>(childPath,child); - } + Entry legacyEntry = bindingToLegacy + .toDataDom(binding); + Entry> normalizedEntry = legacyToNormalized + .toNormalized(legacyEntry); + LOG.trace("Serialization of {}, Legacy Representation: {}, Normalized Representation: {}", binding, + legacyEntry, normalizedEntry); + if (Augmentation.class.isAssignableFrom(binding.getKey().getTargetType())) { + + for (DataContainerChild child : ((DataContainerNode) normalizedEntry + .getValue()).getValue()) { + if (child instanceof AugmentationNode) { + ImmutableList childArgs = ImmutableList. builder() + .addAll(normalizedEntry.getKey().getPath()).add(child.getIdentifier()).build(); + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier( + childArgs); + return new SimpleEntry>( + childPath, child); + } } } return normalizedEntry; + } + /** + * + * Returns a Binding-Aware instance identifier from normalized + * instance-identifier if it is possible to create representation. + * + * Returns Optional.absent for cases where target is mixin node except + * augmentation. + * + */ + public Optional> toBinding( + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) + throws DeserializationException { + + PathArgument lastArgument = Iterables.getLast(normalized.getPath()); + // Used instance-identifier codec do not support serialization of last + // path + // argument if it is AugmentationIdentifier (behaviour expected by old + // datastore) + // in this case, we explicitly check if last argument is augmentation + // to process it separately + if (lastArgument instanceof AugmentationIdentifier) { + return toBindingAugmented(normalized); + } + return toBindingImpl(normalized); } - public InstanceIdentifier toBinding( + private Optional> toBindingAugmented( final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) throws DeserializationException { + Optional> potential = toBindingImpl(normalized); + // Shorthand check, if codec already supports deserialization + // of AugmentationIdentifier we will return + if (potential.isPresent() && isAugmentationIdentifier(potential.get())) { + return potential; + } + + AugmentationIdentifier lastArgument = (AugmentationIdentifier) Iterables.getLast(normalized.getPath()); + // Here we employ small trick - Binding-aware Codec injects an pointer + // to augmentation class + // if child is referenced - so we will reference child and then shorten + // path. + for (QName child : lastArgument.getPossibleChildNames()) { + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier( + ImmutableList. builder().addAll(normalized.getPath()).add(new NodeIdentifier(child)) + .build()); + try { + if (!isChoiceOrCasePath(childPath)) { + InstanceIdentifier potentialPath = shortenToLastAugment(toBindingImpl( + childPath).get()); + return Optional.> of(potentialPath); + } + } catch (Exception e) { + LOG.trace("Unable to deserialize aug. child path for {}", childPath, e); + } + } + return toBindingImpl(normalized); + } + + private Optional> toBindingImpl( + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) + throws DeserializationException { org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath; + try { + if (isChoiceOrCasePath(normalized)) { + return Optional.absent(); + } legacyPath = legacyToNormalized.toLegacy(normalized); } catch (DataNormalizationException e) { - throw new IllegalStateException("Could not denormalize path.",e); + throw new IllegalStateException("Could not denormalize path.", e); } - LOG.trace("InstanceIdentifier Path Deserialization: Legacy representation {}, Normalized representation: {}",legacyPath,normalized); - return bindingToLegacy.fromDataDom(legacyPath); + LOG.trace("InstanceIdentifier Path Deserialization: Legacy representation {}, Normalized representation: {}", + legacyPath, normalized); + return Optional.> of(bindingToLegacy.fromDataDom(legacyPath)); + } + + private boolean isChoiceOrCasePath(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) + throws DataNormalizationException { + DataNormalizationOperation op = findNormalizationOperation(normalized); + return op.isMixin() && op.getIdentifier() instanceof NodeIdentifier; + } + + private DataNormalizationOperation findNormalizationOperation( + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) + throws DataNormalizationException { + DataNormalizationOperation current = legacyToNormalized.getRootOperation(); + for (PathArgument arg : normalized.getPath()) { + current = current.getChild(arg); + } + return current; } private static final Entry, DataObject> toEntry( @@ -103,19 +208,39 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener { public DataObject toBinding(final InstanceIdentifier path, final NormalizedNode normalizedNode) throws DeserializationException { - return bindingToLegacy.dataObjectFromDataDom(path, (CompositeNode) DataNormalizer.toLegacy(normalizedNode)); + CompositeNode legacy = null; + if (isAugmentationIdentifier(path) && normalizedNode instanceof AugmentationNode) { + QName augIdentifier = BindingReflections.findQName(path.getTargetType()); + ContainerNode virtualNode = Builders.containerBuilder() // + .withNodeIdentifier(new NodeIdentifier(augIdentifier)) // + .withChild((DataContainerChild) normalizedNode) // + .build(); + legacy = (CompositeNode) DataNormalizer.toLegacy(virtualNode); + } else { + legacy = (CompositeNode) DataNormalizer.toLegacy(normalizedNode); + } + + return bindingToLegacy.dataObjectFromDataDom(path, legacy); } public DataNormalizer getDataNormalizer() { return legacyToNormalized; } - public Entry, DataObject> toBinding( + public Optional, DataObject>> toBinding( final Entry> normalized) throws DeserializationException { - InstanceIdentifier bindingPath = toBinding(normalized.getKey()); - DataObject bindingData = toBinding(bindingPath, normalized.getValue()); - return toEntry(bindingPath, bindingData); + Optional> potentialPath = toBinding(normalized.getKey()); + if (potentialPath.isPresent()) { + InstanceIdentifier bindingPath = potentialPath.get(); + DataObject bindingData = toBinding(bindingPath, normalized.getValue()); + if (bindingData == null) { + LOG.warn("Failed to deserialize {} to Binding format. Binding path is: {}", normalized, bindingPath); + } + return Optional.of(toEntry(bindingPath, bindingData)); + } else { + return Optional.absent(); + } } @Override @@ -123,4 +248,139 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener { legacyToNormalized = new DataNormalizer(arg0); } + private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalizedAugmented( + final InstanceIdentifier augPath) { + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed = toNormalizedImpl(augPath); + // If used instance identifier codec added supports for deserialization + // of last AugmentationIdentifier we will just reuse it + if (isAugmentationIdentifier(processed)) { + return processed; + } + // Here we employ small trick - DataNormalizer injecst augmentation + // identifier if child is + // also part of the path (since using a child we can safely identify + // augmentation) + // so, we scan augmentation for children add it to path + // and use original algorithm, then shorten it to last augmentation + for (@SuppressWarnings("rawtypes") + Class augChild : getAugmentationChildren(augPath.getTargetType())) { + @SuppressWarnings("unchecked") + InstanceIdentifier childPath = augPath.child(augChild); + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = toNormalizedImpl(childPath); + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier potentialDiscovered = shortenToLastAugmentation(normalized); + if (potentialDiscovered != null) { + return potentialDiscovered; + } + } + return processed; + } + + private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier shortenToLastAugmentation( + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) { + int position = 0; + int foundPosition = -1; + for (PathArgument arg : normalized.getPath()) { + position++; + if (arg instanceof AugmentationIdentifier) { + foundPosition = position; + } + } + if (foundPosition > 0) { + return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(normalized.getPath().subList(0, + foundPosition)); + } + return null; + } + + private InstanceIdentifier shortenToLastAugment( + final InstanceIdentifier binding) { + int position = 0; + int foundPosition = -1; + for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : binding.getPathArguments()) { + position++; + if (isAugmentation(arg.getType())) { + foundPosition = position; + } + } + return InstanceIdentifier.create(Iterables.limit(binding.getPathArguments(), foundPosition)); + } + + private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalizedImpl( + final InstanceIdentifier binding) { + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath = bindingToLegacy + .toDataDom(binding); + final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = legacyToNormalized + .toNormalized(legacyPath); + return normalized; + } + + @SuppressWarnings("unchecked") + private Iterable> getAugmentationChildren(final Class targetType) { + List> ret = new LinkedList<>(); + for (Method method : targetType.getMethods()) { + Class entity = getYangModeledType(method); + if (entity != null) { + ret.add((Class) entity); + } + } + return ret; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private Class getYangModeledType(final Method method) { + if (method.getName().equals("getClass") || !method.getName().startsWith("get") + || method.getParameterTypes().length > 0) { + return null; + } + + Class returnType = method.getReturnType(); + if (DataContainer.class.isAssignableFrom(returnType)) { + return (Class) returnType; + } else if (List.class.isAssignableFrom(returnType)) { + try { + return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(), + new Callable() { + + @SuppressWarnings("rawtypes") + @Override + public Class call() throws Exception { + Type listResult = ClassLoaderUtils.getFirstGenericParameter(method + .getGenericReturnType()); + if (listResult instanceof Class + && DataObject.class.isAssignableFrom((Class) listResult)) { + return (Class) listResult; + } + return null; + } + + }); + } catch (Exception e) { + LOG.debug("Could not get YANG modeled entity for {}", method, e); + return null; + } + + } + return null; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private static InstanceIdentifier toWildcarded(final InstanceIdentifier orig) { + List wildArgs = new LinkedList<>(); + for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : orig.getPathArguments()) { + wildArgs.add(new Item(arg.getType())); + } + return InstanceIdentifier.create(wildArgs); + } + + private static boolean isAugmentation(final Class type) { + return Augmentation.class.isAssignableFrom(type); + } + + private static boolean isAugmentationIdentifier(final InstanceIdentifier potential) { + return Augmentation.class.isAssignableFrom(potential.getTargetType()); + } + + private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed) { + return Iterables.getLast(processed.getPath()) instanceof AugmentationIdentifier; + } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java index ab0dc6e24f..ddc79ae075 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/ForwardedBackwardsCompatibleDataBroker.java @@ -195,6 +195,7 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat private class ForwardedBackwardsCompatibleTransacion extends AbstractForwardedTransaction implements DataModificationTransaction { + private final ListenerRegistry listeners = ListenerRegistry.create(); private final Map, DataObject> updated = new HashMap<>(); private final Map, DataObject> created = new HashMap<>(); private final Set> removed = new HashSet<>(); @@ -218,13 +219,17 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat @Override public void putOperationalData(final InstanceIdentifier path, final DataObject data) { - posponedRemovedOperational.remove(path); - doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data); + boolean previouslyRemoved = posponedRemovedOperational.remove(path); + if(previouslyRemoved) { + doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data); + } else { + doMergeWithEnsureParents(getDelegate(), LogicalDatastoreType.OPERATIONAL, path, data); + } } @Override public void putConfigurationData(final InstanceIdentifier path, final DataObject data) { - posponedRemovedConfiguration.remove(path); + boolean previouslyRemoved = posponedRemovedConfiguration.remove(path); DataObject originalObj = readConfigurationData(path); if (originalObj != null) { original.put(path, originalObj); @@ -233,7 +238,11 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat created.put(path, data); } updated.put(path, data); - doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data); + if(previouslyRemoved) { + doPutWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data); + } else { + doMergeWithEnsureParents(getDelegate(), LogicalDatastoreType.CONFIGURATION, path, data); + } } @Override @@ -314,6 +323,14 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat private void changeStatus(final TransactionStatus status) { LOG.trace("Transaction {} changed status to {}", getIdentifier(), status); this.status = status; + + for(ListenerRegistration listener : listeners) { + try { + listener.getInstance().onStatusUpdated(this, status); + } catch (Exception e) { + LOG.error("Error during invoking transaction listener {}",listener.getInstance(),e); + } + } } @Override @@ -327,10 +344,10 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat doDelete(getDelegate(), LogicalDatastoreType.OPERATIONAL, path); } - final ListenableFuture> f = ForwardedBackwardsCompatibleDataBroker.this.commit(this); - changeStatus(TransactionStatus.SUBMITED); + final ListenableFuture> f = ForwardedBackwardsCompatibleDataBroker.this.commit(this); + Futures.addCallback(f, new FutureCallback>() { @Override public void onSuccess(final RpcResult result) { @@ -349,7 +366,7 @@ public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDat @Override public ListenerRegistration registerListener(final DataTransactionListener listener) { - throw new UnsupportedOperationException(); + return listeners.register(listener); } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.java index ea8b6c0972..ae90a7739e 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.java @@ -7,151 +7,89 @@ */ package org.opendaylight.controller.sal.binding.codegen; -import com.google.common.base.Objects; import java.lang.reflect.Field; import java.util.Map; -import org.eclipse.xtext.xbase.lib.Exceptions; -import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification; + import org.opendaylight.yangtools.yang.binding.BaseIdentity; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.RpcService; -@SuppressWarnings("all") -public class RuntimeCodeHelper { - /** - * Helper method to return delegate from ManagedDirectedProxy with use of reflection. - * - * Note: This method uses reflection, but access to delegate field should be - * avoided and called only if neccessary. - */ - public static T getDelegate(final RpcService proxy) { - try { - Class _class = proxy.getClass(); - final Field field = _class.getField(RuntimeCodeSpecification.DELEGATE_FIELD); - boolean _equals = Objects.equal(field, null); - if (_equals) { - UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Unable to get delegate from proxy"); - throw _unsupportedOperationException; - } - try { - Object _get = field.get(proxy); - return ((T) _get); - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - } catch (Throwable _e_1) { - throw Exceptions.sneakyThrow(_e_1); +public final class RuntimeCodeHelper { + private RuntimeCodeHelper() { + throw new UnsupportedOperationException("Utility class should never be instantiated"); + } + + private static Field getField(final Class cls, final String name) { + try { + return cls.getField(name); + } catch (NoSuchFieldException e) { + throw new IllegalArgumentException( + String.format("Class %s is missing field %s", cls, name), e); + } catch (SecurityException e) { + throw new IllegalStateException(String.format("Failed to examine class %s", cls), e); + } } - } - /** - * Helper method to set delegate to ManagedDirectedProxy with use of reflection. - * - * Note: This method uses reflection, but setting delegate field should not occur too much - * to introduce any significant performance hits. - */ - public static void setDelegate(final RpcService proxy, final RpcService delegate) { - try { - Class _class = proxy.getClass(); - final Field field = _class.getField(RuntimeCodeSpecification.DELEGATE_FIELD); - boolean _equals = Objects.equal(field, null); - if (_equals) { - UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Unable to set delegate to proxy"); - throw _unsupportedOperationException; - } - boolean _or = false; - boolean _equals_1 = Objects.equal(delegate, null); - if (_equals_1) { - _or = true; - } else { - Class _type = field.getType(); - Class _class_1 = delegate.getClass(); - boolean _isAssignableFrom = _type.isAssignableFrom(_class_1); - _or = (_equals_1 || _isAssignableFrom); - } - if (_or) { - field.set(proxy, delegate); - } else { - IllegalArgumentException _illegalArgumentException = new IllegalArgumentException("delegate class is not assignable to proxy"); - throw _illegalArgumentException; - } - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); + private static Field getDelegateField(final Class cls) { + return getField(cls, RuntimeCodeSpecification.DELEGATE_FIELD); } - } - /** - * Helper method to set delegate to ManagedDirectedProxy with use of reflection. - * - * Note: This method uses reflection, but setting delegate field should not occur too much - * to introduce any significant performance hits. - */ - public static void setDelegate(final Object proxy, final Object delegate) { - try { - Class _class = proxy.getClass(); - final Field field = _class.getField(RuntimeCodeSpecification.DELEGATE_FIELD); - boolean _equals = Objects.equal(field, null); - if (_equals) { - UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Unable to set delegate to proxy"); - throw _unsupportedOperationException; - } - boolean _or = false; - boolean _equals_1 = Objects.equal(delegate, null); - if (_equals_1) { - _or = true; - } else { - Class _type = field.getType(); - Class _class_1 = delegate.getClass(); - boolean _isAssignableFrom = _type.isAssignableFrom(_class_1); - _or = (_equals_1 || _isAssignableFrom); - } - if (_or) { - field.set(proxy, delegate); - } else { - IllegalArgumentException _illegalArgumentException = new IllegalArgumentException("delegate class is not assignable to proxy"); - throw _illegalArgumentException; - } - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); + private static Object getFieldValue(final Field field, final Object obj) { + try { + return field.get(obj); + } catch (IllegalAccessException e) { + throw new IllegalStateException(String.format("Failed to get field %s of object %s", field, obj), e); + } + } + + private static void setFieldValue(final Field field, final Object obj, final Object value) { + try { + field.set(obj, value); + } catch (IllegalAccessException e) { + throw new IllegalStateException(String.format("Failed to set field %s to %s", field, value), e); + } + } + + /** + * Helper method to return delegate from ManagedDirectedProxy with use of reflection. + * + * Note: This method uses reflection, but access to delegate field should be + * avoided and called only if necessary. + */ + @SuppressWarnings("unchecked") + public static T getDelegate(final RpcService proxy) { + return (T)getFieldValue(getDelegateField(proxy.getClass()), proxy); + } + + /** + * Helper method to set delegate to ManagedDirectedProxy with use of reflection. + * + * Note: This method uses reflection, but setting delegate field should not occur too much + * to introduce any significant performance hits. + */ + public static void setDelegate(final Object proxy, final Object delegate) { + final Field field = getDelegateField(proxy.getClass()); + + if (delegate != null) { + final Class ft = field.getType(); + if (!ft.isAssignableFrom(delegate.getClass())) { + throw new IllegalArgumentException( + String.format("Field %s type %s is not compatible with delegate type %s", + field, ft, delegate.getClass())); + } + } + + setFieldValue(field, proxy, delegate); } - } - public static Map,? extends RpcService> getRoutingTable(final RpcService target, final Class tableClass) { - try { - Class _class = target.getClass(); - String _routingTableField = RuntimeCodeSpecification.getRoutingTableField(tableClass); - final Field field = _class.getField(_routingTableField); - boolean _equals = Objects.equal(field, null); - if (_equals) { - UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException( - "Unable to get routing table. Table field does not exists"); - throw _unsupportedOperationException; - } - try { - Object _get = field.get(target); - return ((Map,? extends RpcService>) _get); - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); - } - } catch (Throwable _e_1) { - throw Exceptions.sneakyThrow(_e_1); + @SuppressWarnings("unchecked") + public static Map,? extends RpcService> getRoutingTable(final RpcService target, final Class tableClass) { + final Field field = getField(target.getClass(), RuntimeCodeSpecification.getRoutingTableField(tableClass)); + return (Map,? extends RpcService>) getFieldValue(field, target); } - } - public static void setRoutingTable(final RpcService target, final Class tableClass, final Map,? extends RpcService> routingTable) { - try { - Class _class = target.getClass(); - String _routingTableField = RuntimeCodeSpecification.getRoutingTableField(tableClass); - final Field field = _class.getField(_routingTableField); - boolean _equals = Objects.equal(field, null); - if (_equals) { - UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException( - "Unable to set routing table. Table field does not exists"); - throw _unsupportedOperationException; - } - field.set(target, routingTable); - } catch (Throwable _e) { - throw Exceptions.sneakyThrow(_e); + public static void setRoutingTable(final RpcService target, final Class tableClass, final Map,? extends RpcService> routingTable) { + final Field field = getField(target.getClass(), RuntimeCodeSpecification.getRoutingTableField(tableClass)); + setFieldValue(field, target, routingTable); } - } -} \ No newline at end of file +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend index 6723713645..465a1f7d9d 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend @@ -43,13 +43,11 @@ import javassist.LoaderClassPath class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory { val CtClass BROKER_NOTIFICATION_LISTENER; - val ClassPool classPool; val extension JavassistUtils utils; val Map, RuntimeGeneratedInvokerPrototype> invokerClasses; new(ClassPool pool) { - classPool = pool; utils = new JavassistUtils(pool); invokerClasses = new WeakHashMap(); BROKER_NOTIFICATION_LISTENER = org.opendaylight.controller.sal.binding.api.NotificationListener.asCtClass; diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolder.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolder.java index ac26445bf4..8276446766 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolder.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolder.java @@ -7,13 +7,6 @@ */ package org.opendaylight.controller.sal.binding.codegen.impl; -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.MoreExecutors; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import javassist.ClassPool; -import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator; -import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory; - import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -23,7 +16,20 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import javassist.ClassPool; + +import org.apache.commons.lang3.StringUtils; +import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator; +import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.ThreadFactoryBuilder; + public class SingletonHolder { + private static final Logger logger = LoggerFactory.getLogger(SingletonHolder.class); public static final ClassPool CLASS_POOL = ClassPool.getDefault(); public static final org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator RPC_GENERATOR_IMPL = new org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator( @@ -33,7 +39,10 @@ public class SingletonHolder { public static final int CORE_NOTIFICATION_THREADS = 4; public static final int MAX_NOTIFICATION_THREADS = 32; + // block caller thread after MAX_NOTIFICATION_THREADS + MAX_NOTIFICATION_QUEUE_SIZE pending notifications + public static final int MAX_NOTIFICATION_QUEUE_SIZE = 1000; public static final int NOTIFICATION_THREAD_LIFE = 15; + private static final String NOTIFICATION_QUEUE_SIZE_PROPERTY = "mdsal.notificationqueue.size"; private static ListeningExecutorService NOTIFICATION_EXECUTOR = null; private static ListeningExecutorService COMMIT_EXECUTOR = null; @@ -44,22 +53,31 @@ public class SingletonHolder { * should use service injection to make the executor configurable. */ @Deprecated - public static synchronized final ListeningExecutorService getDefaultNotificationExecutor() { + public static synchronized ListeningExecutorService getDefaultNotificationExecutor() { if (NOTIFICATION_EXECUTOR == null) { - // Overriding the queue since we need an unbounded queue - // and threadpoolexecutor would not create new threads if the queue is not full - BlockingQueue queue = new LinkedBlockingQueue() { + int queueSize = MAX_NOTIFICATION_QUEUE_SIZE; + String queueValue = System.getProperty(NOTIFICATION_QUEUE_SIZE_PROPERTY); + if (StringUtils.isNotBlank(queueValue)) { + try { + queueSize = Integer.parseInt(queueValue); + logger.trace("Queue size was set to {}", queueSize); + }catch(NumberFormatException e) { + logger.warn("Cannot parse {} as set by {}, using default {}", queueValue, + NOTIFICATION_QUEUE_SIZE_PROPERTY, queueSize); + } + } + // Overriding the queue: + // ThreadPoolExecutor would not create new threads if the queue is not full, thus adding + // occurs in RejectedExecutionHandler. + // This impl saturates threadpool first, then queue. When both are full caller will get blocked. + BlockingQueue queue = new LinkedBlockingQueue(queueSize) { + private static final long serialVersionUID = 1L; + @Override public boolean offer(Runnable r) { - if (size() <= 1) { - // if the queue is empty (or has just 1), no need to rampup the threads - return super.offer(r); - } else { - // if the queue is not empty, force the queue to return false. - // threadpoolexecutor will spawn a new thread if the queue.offer returns false. - return false; - } + // ThreadPoolExecutor will spawn a new thread after core size is reached only if the queue.offer returns false. + return false; } }; @@ -74,7 +92,8 @@ public class SingletonHolder { try { executor.getQueue().put(r); } catch (InterruptedException e) { - e.printStackTrace(); + Thread.currentThread().interrupt();// set interrupt flag after clearing + throw new IllegalStateException(e); } } }); @@ -90,7 +109,7 @@ public class SingletonHolder { * should use service injection to make the executor configurable. */ @Deprecated - public static synchronized final ListeningExecutorService getDefaultCommitExecutor() { + public static synchronized ListeningExecutorService getDefaultCommitExecutor() { if (COMMIT_EXECUTOR == null) { ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("md-sal-binding-commit-%d").build(); /* diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java index a398abc75a..b27c80d784 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java @@ -98,11 +98,8 @@ public class BindingIndependentConnector implements // Provider, // AutoCloseable { - - private 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(); @@ -200,30 +197,30 @@ public class BindingIndependentConnector implements // private DataModificationTransaction createBindingToDomTransaction( final DataModification, DataObject> source) { DataModificationTransaction target = biDataService.beginTransaction(); - LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(),source.getIdentifier()); + LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(), source.getIdentifier()); for (InstanceIdentifier 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); + LOG.debug("Delete of Binding Configuration Data {} is translated to {}", entry, biEntry); } for (InstanceIdentifier 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); + LOG.debug("Delete of Binding Operational Data {} is translated to {}", entry, biEntry); } for (Entry, DataObject> entry : source.getUpdatedConfigurationData() .entrySet()) { Entry biEntry = mappingService .toDataDom(entry); target.putConfigurationData(biEntry.getKey(), biEntry.getValue()); - LOG.debug("Update of Binding Configuration Data {} is translated to {}",entry,biEntry); + LOG.debug("Update of Binding Configuration Data {} is translated to {}", entry, biEntry); } for (Entry, DataObject> entry : source.getUpdatedOperationalData() .entrySet()) { Entry biEntry = mappingService .toDataDom(entry); target.putOperationalData(biEntry.getKey(), biEntry.getValue()); - LOG.debug("Update of Binding Operational Data {} is translated to {}",entry,biEntry); + LOG.debug("Update of Binding Operational Data {} is translated to {}", entry, biEntry); } return target; @@ -279,7 +276,8 @@ public class BindingIndependentConnector implements // return biDataService; } - protected void setDomDataService(final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) { + protected void setDomDataService( + final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) { this.biDataService = biDataService; } @@ -300,14 +298,14 @@ public class BindingIndependentConnector implements // } public void startDataForwarding() { - if(baDataService instanceof AbstractForwardedDataBroker) { + if (baDataService instanceof AbstractForwardedDataBroker) { dataForwarding = true; return; } final DataProviderService baData; if (baDataService instanceof BindingMountPointImpl) { - baData = ((BindingMountPointImpl)baDataService).getDataBrokerImpl(); + baData = ((BindingMountPointImpl) baDataService).getDataBrokerImpl(); LOG.debug("Extracted BA Data provider {} from mount point {}", baData, baDataService); } else { baData = baDataService; @@ -478,8 +476,8 @@ public class BindingIndependentConnector implements // } DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction); BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction); - LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(), - domTransaction.getIdentifier()); + LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .", + bindingTransaction.getIdentifier(), domTransaction.getIdentifier()); return wrapped; } } @@ -489,7 +487,8 @@ public class BindingIndependentConnector implements // DataCommitHandler { @Override - public void onRegister(final DataCommitHandlerRegistration, DataObject> registration) { + public void onRegister( + final DataCommitHandlerRegistration, DataObject> registration) { org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration .getPath()); @@ -497,7 +496,8 @@ public class BindingIndependentConnector implements // } @Override - public void onUnregister(final DataCommitHandlerRegistration, DataObject> registration) { + public void onUnregister( + final DataCommitHandlerRegistration, DataObject> registration) { // NOOP for now // FIXME: do registration based on only active commit handlers. } @@ -531,8 +531,7 @@ public class BindingIndependentConnector implements // * */ private class DomToBindingRpcForwardingManager implements - RouteChangeListener>, - RouterInstantiationListener, + RouteChangeListener>, RouterInstantiationListener, GlobalRpcRegistrationListener { private final Map, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>(); @@ -615,7 +614,7 @@ public class BindingIndependentConnector implements // } } catch (Exception e) { - LOG.error("Could not forward Rpcs of type {}", service.getName(),e); + LOG.error("Could not forward Rpcs of type {}", service.getName(), e); } registrations = ImmutableSet.of(); } @@ -626,7 +625,8 @@ public class BindingIndependentConnector implements // * @param service * @param context */ - public DomToBindingRpcForwarder(final Class service, final Class context) { + public DomToBindingRpcForwarder(final Class service, + final Class context) { this.rpcServiceType = new WeakReference>(service); this.supportedRpcs = mappingService.getRpcQNamesFor(service); Builder registrationsBuilder = ImmutableSet @@ -645,8 +645,8 @@ public class BindingIndependentConnector implements // registrations = registrationsBuilder.build(); } - public void registerPaths(final Class context, final Class service, - final Set> set) { + public void registerPaths(final Class context, + final Class service, final Set> set) { QName ctx = BindingReflections.findQName(context); for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform( toDOMInstanceIdentifier)) { @@ -656,7 +656,6 @@ public class BindingIndependentConnector implements // } } - @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { if (EQUALS_METHOD.equals(method)) { @@ -700,7 +699,6 @@ public class BindingIndependentConnector implements // } } - @Override public ListenableFuture> invokeRpc(final QName rpc, final CompositeNode domInput) { checkArgument(rpc != null); @@ -748,12 +746,12 @@ public class BindingIndependentConnector implements // strategy = new DefaultInvocationStrategy(rpc, targetMethod, outputClass.get(), inputClass .get()); } else { - strategy = new NoInputNoOutputInvocationStrategy(rpc, targetMethod); + strategy = new NoInputInvocationStrategy(rpc, targetMethod, outputClass.get()); } - } else if(inputClass.isPresent()){ - strategy = new NoOutputInvocationStrategy(rpc,targetMethod, inputClass.get()); + } else if (inputClass.isPresent()) { + strategy = new NoOutputInvocationStrategy(rpc, targetMethod, inputClass.get()); } else { - strategy = new NoInputNoOutputInvocationStrategy(rpc,targetMethod); + strategy = new NoInputNoOutputInvocationStrategy(rpc, targetMethod); } return strategy; } @@ -777,7 +775,8 @@ public class BindingIndependentConnector implements // public abstract RpcResult uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception; - public RpcResult invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception { + public RpcResult invokeOn(final RpcService rpcService, final CompositeNode domInput) + throws Exception { return uncheckedInvoke(rpcService, domInput); } } @@ -800,7 +799,8 @@ public class BindingIndependentConnector implements // @SuppressWarnings("unchecked") @Override - public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception { + public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) + throws Exception { DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput); Future> futureResult = (Future>) targetMethod.invoke(rpcService, bindingInput); if (futureResult == null) { @@ -809,31 +809,84 @@ public class BindingIndependentConnector implements // RpcResult bindingResult = futureResult.get(); final Object resultObj = bindingResult.getResult(); if (resultObj instanceof DataObject) { - final CompositeNode output = mappingService.toDataDom((DataObject)resultObj); - return Rpcs.getRpcResult(true, output, Collections.emptySet()); + final CompositeNode output = mappingService.toDataDom((DataObject) resultObj); + return Rpcs.getRpcResult(true, output, Collections. emptySet()); } return Rpcs.getRpcResult(true); } @Override public ListenableFuture> forwardToDomBroker(final DataObject input) { - if(biRpcRegistry == null) { + if (biRpcRegistry == null) { return Futures.> immediateFuture(Rpcs.getRpcResult(false)); } CompositeNode xml = mappingService.toDataDom(input); CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.> of(xml)); - return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml), new Function, RpcResult>() { - @Override - public RpcResult apply(RpcResult input) { - Object baResultValue = null; - if (input.getResult() != null) { - baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(), input.getResult()); - } - return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors()); - } - }); + return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml), + new Function, RpcResult>() { + @Override + public RpcResult apply(final RpcResult input) { + Object baResultValue = null; + if (input.getResult() != null) { + baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(), + input.getResult()); + } + return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors()); + } + }); + } + } + + private class NoInputInvocationStrategy extends RpcInvocationStrategy { + + @SuppressWarnings("rawtypes") + private final WeakReference outputClass; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public NoInputInvocationStrategy(final QName rpc, final Method targetMethod, final Class outputClass) { + super(rpc, targetMethod); + this.outputClass = new WeakReference(outputClass); + } + + @SuppressWarnings("unchecked") + @Override + public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) + throws Exception { + Future> futureResult = (Future>) targetMethod.invoke(rpcService); + if (futureResult == null) { + return Rpcs.getRpcResult(false); + } + RpcResult bindingResult = futureResult.get(); + final Object resultObj = bindingResult.getResult(); + if (resultObj instanceof DataObject) { + final CompositeNode output = mappingService.toDataDom((DataObject) resultObj); + return Rpcs.getRpcResult(true, output, Collections. emptySet()); + } + return Rpcs.getRpcResult(true); + } + + @Override + public Future> forwardToDomBroker(final DataObject input) { + if (biRpcRegistry != null) { + CompositeNode xml = mappingService.toDataDom(input); + CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.> of(xml)); + return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml), + new Function, RpcResult>() { + @Override + public RpcResult apply(final RpcResult input) { + Object baResultValue = null; + if (input.getResult() != null) { + baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(), + input.getResult()); + } + return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors()); + } + }); + } else { + return Futures.> immediateFuture(Rpcs.getRpcResult(false)); + } } } @@ -844,7 +897,8 @@ public class BindingIndependentConnector implements // } @Override - public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception { + public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) + throws Exception { @SuppressWarnings("unchecked") Future> result = (Future>) targetMethod.invoke(rpcService); RpcResult bindingResult = result.get(); @@ -859,20 +913,19 @@ public class BindingIndependentConnector implements // private class NoOutputInvocationStrategy extends RpcInvocationStrategy { - @SuppressWarnings("rawtypes") private final WeakReference inputClass; @SuppressWarnings({ "rawtypes", "unchecked" }) public NoOutputInvocationStrategy(final QName rpc, final Method targetMethod, final Class inputClass) { - super(rpc,targetMethod); + super(rpc, targetMethod); this.inputClass = new WeakReference(inputClass); } - @Override - public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception { + public RpcResult uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) + throws Exception { DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput); Future> result = (Future>) targetMethod.invoke(rpcService, bindingInput); if (result == null) { @@ -884,19 +937,20 @@ public class BindingIndependentConnector implements // @Override public ListenableFuture> forwardToDomBroker(final DataObject input) { - if(biRpcRegistry == null) { + if (biRpcRegistry == null) { return Futures.> immediateFuture(Rpcs.getRpcResult(false)); } CompositeNode xml = mappingService.toDataDom(input); - CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.>of(xml)); + CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.> of(xml)); - return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml), new Function, RpcResult>() { - @Override - public RpcResult apply(RpcResult input) { - return Rpcs.getRpcResult(input.isSuccessful(), null, input.getErrors()); - } - }); + return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml), + new Function, RpcResult>() { + @Override + public RpcResult apply(final RpcResult input) { + return Rpcs. getRpcResult(input.isSuccessful(), null, input.getErrors()); + } + }); } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolderTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolderTest.java new file mode 100644 index 0000000000..0e4c5ccb84 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolderTest.java @@ -0,0 +1,56 @@ +/* + * 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.codegen.impl; + +import com.google.common.util.concurrent.ListeningExecutorService; +import java.lang.reflect.Field; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Ignore +public class SingletonHolderTest { + private static final Logger logger = LoggerFactory.getLogger(SingletonHolderTest.class); + + @Test + public void testNotificationExecutor() throws Exception { + ListeningExecutorService executor = SingletonHolder.getDefaultNotificationExecutor(); + ThreadPoolExecutor tpExecutor = (ThreadPoolExecutor) setAccessible(executor.getClass().getDeclaredField("delegate")).get(executor); + BlockingQueue queue = tpExecutor.getQueue(); + + for (int idx = 0; idx < 100; idx++) { + final int idx2 = idx; + logger.info("Adding {}\t{}\t{}", idx, queue.size(), tpExecutor.getActiveCount()); + executor.execute(new Runnable() { + + @Override + public void run() { + logger.info("in {}", idx2); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + logger.info("out {}", idx2); + } + }); + } + executor.shutdown(); + executor.awaitTermination(10, TimeUnit.SECONDS); + } + + private static Field setAccessible(Field field) { + field.setAccessible(true); + return field; + } +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java index b147e03d56..6b2568aba7 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/MultipleAugmentationPuts.java @@ -61,9 +61,8 @@ public class MultipleAugmentationPuts extends AbstractDataServiceTest implements private static final InstanceIdentifier NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // .toInstance(); - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier - .builder(NODES_INSTANCE_ID_BA) // - .child(Node.class, NODE_KEY).toInstance(); + private static final InstanceIdentifier NODE_INSTANCE_ID_BA = + NODES_INSTANCE_ID_BA.child(Node.class, NODE_KEY); private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = // org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() // @@ -74,7 +73,7 @@ public class MultipleAugmentationPuts extends AbstractDataServiceTest implements /** * Test for Bug 148 - * + * * @throws Exception */ @Test @@ -111,12 +110,12 @@ public class MultipleAugmentationPuts extends AbstractDataServiceTest implements // Node meterStatsNodeWithDuration = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics(5, true)); // commitNodeAndVerifyTransaction(meterStatsNodeWithDuration); // -// +// // Node nodeWithUpdatedList = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA); // AugmentationVerifier.from(nodeWithUpdatedList) // // .assertHasAugmentation(FlowCapableNode.class) // // .assertHasAugmentation(NodeMeterStatistics.class); -// +// // List meterStats = nodeWithUpdatedList.getAugmentation(NodeMeterStatistics.class).getMeterStatistics().getMeterStats(); // assertNotNull(meterStats); // assertFalse(meterStats.isEmpty()); diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java index 9cdf70322c..ae65c8889a 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java @@ -267,9 +267,7 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider public void startBindingToDomMappingService() { checkState(classPool != null, "ClassPool needs to be present"); - mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(); - mappingServiceImpl.setPool(classPool); - mappingServiceImpl.init(); + mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool); } public void updateYangSchema(final String[] files) { diff --git a/opendaylight/md-sal/sal-binding-dom-it/pom.xml b/opendaylight/md-sal/sal-binding-dom-it/pom.xml index 21fa207d78..d1354f897f 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/pom.xml +++ b/opendaylight/md-sal/sal-binding-dom-it/pom.xml @@ -14,6 +14,10 @@ junit junit + + org.opendaylight.yangtools + yang-binding + org.opendaylight.controller sal-binding-broker-impl @@ -25,10 +29,6 @@ test-jar test - - org.opendaylight.yangtools - yang-binding - org.opendaylight.controller.model model-flow-management @@ -54,26 +54,6 @@ - - org.opendaylight.yangtools - yang-maven-plugin - - - - generate-sources - - - - - org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl - ${salGeneratorPath} - - - true - - - - org.jacoco jacoco-maven-plugin @@ -98,6 +78,26 @@ + + org.opendaylight.yangtools + yang-maven-plugin + + + + generate-sources + + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + ${salGeneratorPath} + + + true + + + + diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ConcurrentImplicitCreateTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ConcurrentImplicitCreateTest.java index 61a73d63f4..c5dbdcecae 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ConcurrentImplicitCreateTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ConcurrentImplicitCreateTest.java @@ -30,10 +30,8 @@ public class ConcurrentImplicitCreateTest extends AbstractDataServiceTest { private static final NodeKey NODE_FOO_KEY = new NodeKey(new NodeId("foo")); private static final NodeKey NODE_BAR_KEY = new NodeKey(new NodeId("foo")); private static InstanceIdentifier NODES_PATH = InstanceIdentifier.builder(Nodes.class).build(); - private static InstanceIdentifier NODE_FOO_PATH = InstanceIdentifier.builder(NODES_PATH) - .child(Node.class, NODE_FOO_KEY).build(); - private static InstanceIdentifier NODE_BAR_PATH = InstanceIdentifier.builder(NODES_PATH) - .child(Node.class, NODE_FOO_KEY).build(); + private static InstanceIdentifier NODE_FOO_PATH = NODES_PATH.child(Node.class, NODE_FOO_KEY); + private static InstanceIdentifier NODE_BAR_PATH = NODES_PATH.child(Node.class, NODE_FOO_KEY); @Test public void testConcurrentCreate() throws InterruptedException, ExecutionException { diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ListProcessingAndOrderingTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ListProcessingAndOrderingTest.java index 0925e9bff4..800c1b4cc4 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ListProcessingAndOrderingTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ListProcessingAndOrderingTest.java @@ -75,13 +75,13 @@ public class ListProcessingAndOrderingTest extends AbstractDataServiceTest { private static final UnorderedListKey UNORDERED_FOO_KEY = new UnorderedListKey("foo"); private static final UnorderedListKey UNORDERED_BAR_KEY = new UnorderedListKey("bar"); - private static final InstanceIdentifier UNORDERED_FOO_PATH = InstanceIdentifier.builder(UNORDERED_CONTAINER_PATH).child(UnorderedList.class,UNORDERED_FOO_KEY).build(); - private static final InstanceIdentifier UNORDERED_BAR_PATH = InstanceIdentifier.builder(UNORDERED_CONTAINER_PATH).child(UnorderedList.class,UNORDERED_BAR_KEY).build(); + private static final InstanceIdentifier UNORDERED_FOO_PATH = UNORDERED_CONTAINER_PATH.child(UnorderedList.class,UNORDERED_FOO_KEY); + private static final InstanceIdentifier UNORDERED_BAR_PATH = UNORDERED_CONTAINER_PATH.child(UnorderedList.class,UNORDERED_BAR_KEY); private static final OrderedListKey ORDERED_FOO_KEY = new OrderedListKey("foo"); private static final OrderedListKey ORDERED_BAR_KEY = new OrderedListKey("bar"); - private static final InstanceIdentifier ORDERED_FOO_PATH = InstanceIdentifier.builder(ORDERED_CONTAINER_PATH).child(OrderedList.class,ORDERED_FOO_KEY).build(); - private static final InstanceIdentifier ORDERED_BAR_PATH = InstanceIdentifier.builder(ORDERED_CONTAINER_PATH).child(OrderedList.class,ORDERED_BAR_KEY).build(); + private static final InstanceIdentifier ORDERED_FOO_PATH = ORDERED_CONTAINER_PATH.child(OrderedList.class,ORDERED_FOO_KEY); + private static final InstanceIdentifier ORDERED_BAR_PATH = ORDERED_CONTAINER_PATH.child(OrderedList.class,ORDERED_BAR_KEY); @Test diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java index 450ca1cb3b..6b4cc57798 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java @@ -78,14 +78,12 @@ public class WildcardedDataChangeListenerTest extends AbstractDataServiceTest { private static final FlowKey FLOW_KEY = new FlowKey(new FlowId("test")); - private static final InstanceIdentifier NODE_0_FLOW_PATH = InstanceIdentifier.builder(NODE_0_TABLE_PATH) - .child(Flow.class, FLOW_KEY).build(); + private static final InstanceIdentifier NODE_0_FLOW_PATH = NODE_0_TABLE_PATH.child(Flow.class, FLOW_KEY); - private static final InstanceIdentifier NODE_1_FLOW_PATH = InstanceIdentifier.builder(NODE_1_TABLE_PATH) - .child(Flow.class, FLOW_KEY).build(); + private static final InstanceIdentifier NODE_1_FLOW_PATH = NODE_1_TABLE_PATH.child(Flow.class, FLOW_KEY); - private static final InstanceIdentifier NODE_0_TABLE_FEATURES_PATH = InstanceIdentifier - .builder(NODE_0_TABLE_PATH).child(TableFeatures.class, TABLE_FEATURES_KEY).build(); + private static final InstanceIdentifier NODE_0_TABLE_FEATURES_PATH = + NODE_0_TABLE_PATH.child(TableFeatures.class, TABLE_FEATURES_KEY); private static final TableFeatures TABLE_FEATURES = new TableFeaturesBuilder()// .setKey(TABLE_FEATURES_KEY) // diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java index e89371337e..ccbd52fc77 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java @@ -60,13 +60,11 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh .toInstance(); - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier// - .builder(NODES_INSTANCE_ID_BA) // - .child(Node.class, NODE_KEY).toInstance(); + private static final InstanceIdentifier NODE_INSTANCE_ID_BA = NODES_INSTANCE_ID_BA.child(Node.class, NODE_KEY); - private static final InstanceIdentifier SUPPORTED_ACTIONS_INSTANCE_ID_BA = InstanceIdentifier// - .builder(NODES_INSTANCE_ID_BA) // + private static final InstanceIdentifier SUPPORTED_ACTIONS_INSTANCE_ID_BA = // + NODES_INSTANCE_ID_BA.builder() // .child(Node.class, NODE_KEY) // .augmentation(FlowCapableNode.class) // .child(SupportedActions.class) @@ -163,7 +161,7 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh NodeConnectorId ncId = new NodeConnectorId("openflow:1:bar"); NodeConnectorKey nodeKey = new NodeConnectorKey(ncId ); - InstanceIdentifier ncInstanceId = InstanceIdentifier.builder(NODE_INSTANCE_ID_BA).child(NodeConnector.class, nodeKey).toInstance(); + InstanceIdentifier ncInstanceId = NODE_INSTANCE_ID_BA.child(NodeConnector.class, nodeKey); NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder(); ncBuilder.setId(ncId); ncBuilder.setKey(nodeKey); diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java index 023bd795af..30c7af705f 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java @@ -7,7 +7,15 @@ */ package org.opendaylight.controller.sal.binding.test.bugfix; -import com.google.common.collect.ImmutableSet; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; @@ -44,14 +52,7 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import com.google.common.collect.ImmutableSet; public class FlagsSerializationTest extends AbstractDataServiceTest { @@ -65,7 +66,7 @@ public class FlagsSerializationTest extends AbstractDataServiceTest { private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); private static final FlowKey FLOW_KEY = new FlowKey(new FlowId(FLOW_ID)); private static final TableKey TABLE_KEY = new TableKey(TABLE_ID); - + private static final Map NODE_KEY_BI = Collections. singletonMap(NODE_ID_QNAME, NODE_ID); @@ -83,12 +84,12 @@ public class FlagsSerializationTest extends AbstractDataServiceTest { // private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier FLOW_INSTANCE_ID_BI = // // org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() // -// +// // .node(Flows.QNAME) // // .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) // // .toInstance(); private static final InstanceIdentifier FLOW_INSTANCE_ID_BA = // - InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) // + NODE_INSTANCE_ID_BA.builder() // .augmentation(FlowCapableNode.class) .child(Table.class,TABLE_KEY) .child(Flow.class, FLOW_KEY) // @@ -101,34 +102,34 @@ public class FlagsSerializationTest extends AbstractDataServiceTest { FlowModFlags checkOverlapFlags = new FlowModFlags(true,false,false,false,false); ImmutableSet domCheckOverlapFlags = ImmutableSet.of("CHECK_OVERLAP"); testFlags(checkOverlapFlags,domCheckOverlapFlags); - - - + + + FlowModFlags allFalseFlags = new FlowModFlags(false,false,false,false,false); ImmutableSet domAllFalseFlags = ImmutableSet.of(); testFlags(allFalseFlags,domAllFalseFlags); - + FlowModFlags allTrueFlags = new FlowModFlags(true,true,true,true,true); ImmutableSet domAllTrueFlags = ImmutableSet.of("CHECK_OVERLAP","NO_BYT_COUNTS", "NO_PKT_COUNTS", "RESET_COUNTS", "SEND_FLOW_REM"); testFlags(allTrueFlags,domAllTrueFlags); - + FlowModFlags nullFlags = null; ImmutableSet domNullFlags = null; testFlags(null,null); - - + + } private void testFlags(FlowModFlags flagsToTest, ImmutableSet domFlags) throws Exception { Flow flow = createFlow(flagsToTest); assertNotNull(flow); - + CompositeNode domFlow = biDataService.readConfigurationData(mappingService.toDataDom(FLOW_INSTANCE_ID_BA)); - + assertNotNull(domFlow); org.opendaylight.yangtools.yang.data.api.Node readedFlags = domFlow.getFirstSimpleByName(FLOW_FLAGS_QNAME); - + if(domFlags != null) { assertNotNull(readedFlags); assertEquals(domFlags,readedFlags.getValue()); @@ -136,12 +137,12 @@ public class FlagsSerializationTest extends AbstractDataServiceTest { assertNull(readedFlags); } assertEquals(flagsToTest, flow.getFlags()); - + DataModificationTransaction transaction = baDataService.beginTransaction(); transaction.removeConfigurationData(FLOW_INSTANCE_ID_BA); RpcResult result = transaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - + } private Flow createFlow(FlowModFlags flagsToTest) throws Exception { @@ -158,12 +159,12 @@ public class FlagsSerializationTest extends AbstractDataServiceTest { flow.setKey(FLOW_KEY); flow.setMatch(match.build()); - + flow.setFlags(flagsToTest); - + InstructionsBuilder instructions = new InstructionsBuilder(); InstructionBuilder instruction = new InstructionBuilder(); - + instruction.setOrder(10); ApplyActionsBuilder applyActions = new ApplyActionsBuilder(); List actionList = new ArrayList<>(); diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java index 027a8eeb9f..7f16320814 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java @@ -58,18 +58,18 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data private static final InstanceIdentifier NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // .toInstance(); - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier// - .builder(NODES_INSTANCE_ID_BA) // + private static final InstanceIdentifier NODE_INSTANCE_ID_BA = // + NODES_INSTANCE_ID_BA.builder() // .child(Node.class, NODE_KEY).toInstance(); - private static final InstanceIdentifier SUPPORTED_ACTIONS_INSTANCE_ID_BA = InstanceIdentifier// - .builder(NODES_INSTANCE_ID_BA) // + private static final InstanceIdentifier SUPPORTED_ACTIONS_INSTANCE_ID_BA = // + NODES_INSTANCE_ID_BA.builder() // .child(Node.class, NODE_KEY) // .augmentation(FlowCapableNode.class) // .child(SupportedActions.class).toInstance(); - private static final InstanceIdentifier ALL_FLOW_CAPABLE_NODES = InstanceIdentifier // - .builder(NODES_INSTANCE_ID_BA) // + private static final InstanceIdentifier ALL_FLOW_CAPABLE_NODES = // + NODES_INSTANCE_ID_BA.builder() // .child(Node.class) // .augmentation(FlowCapableNode.class) // .build(); @@ -88,8 +88,8 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data .nodeWithKey(Node.QNAME, NODE_KEY_BI) // .node(SUPPORTED_ACTIONS_QNAME) // .toInstance(); - private static final InstanceIdentifier FLOW_AUGMENTATION_PATH = InstanceIdentifier // - .builder(NODE_INSTANCE_ID_BA) // + private static final InstanceIdentifier FLOW_AUGMENTATION_PATH = + NODE_INSTANCE_ID_BA.builder() // .augmentation(FlowCapableNode.class) // .build(); @@ -126,8 +126,8 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data fnub.setDescription("Description Foo"); fnub.setSoftware("JUnit emulated"); FlowCapableNode fnu = fnub.build(); - InstanceIdentifier augmentIdentifier = InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) - .augmentation(FlowCapableNode.class).toInstance(); + InstanceIdentifier augmentIdentifier = NODE_INSTANCE_ID_BA + .augmentation(FlowCapableNode.class); DataModificationTransaction augmentedTransaction = baDataService.beginTransaction(); augmentedTransaction.putOperationalData(augmentIdentifier, fnu); @@ -183,8 +183,8 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data lastReceivedChangeEvent = SettableFuture.create(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - FlowCapableNode readedAugmentation = (FlowCapableNode) baDataService.readOperationalData(InstanceIdentifier - .builder(NODE_INSTANCE_ID_BA).augmentation(FlowCapableNode.class).toInstance()); + FlowCapableNode readedAugmentation = (FlowCapableNode) baDataService.readOperationalData( + NODE_INSTANCE_ID_BA.augmentation(FlowCapableNode.class)); assertNotNull(readedAugmentation); assertEquals(fnu.getHardware(), readedAugmentation.getHardware()); @@ -198,10 +198,10 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data private void testPutNodeConnectorWithAugmentation() throws Exception { NodeConnectorKey ncKey = new NodeConnectorKey(new NodeConnectorId("test:0:0")); - InstanceIdentifier ncPath = InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) - .child(NodeConnector.class, ncKey).toInstance(); - InstanceIdentifier ncAugmentPath = InstanceIdentifier.builder(ncPath) - .augmentation(FlowCapableNodeConnector.class).toInstance(); + InstanceIdentifier ncPath = NODE_INSTANCE_ID_BA + .child(NodeConnector.class, ncKey); + InstanceIdentifier ncAugmentPath = ncPath + .augmentation(FlowCapableNodeConnector.class); NodeConnectorBuilder nc = new NodeConnectorBuilder(); nc.setKey(ncKey); diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java new file mode 100644 index 0000000000..cb31885f02 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java @@ -0,0 +1,89 @@ +/* + * 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.test.bugfix; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; +import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; +import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; +import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import com.google.common.util.concurrent.SettableFuture; + +public class WriteParentListenAugmentTest extends AbstractDataServiceTest { + + private static final String NODE_ID = "node:1"; + + private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); + private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // + .child(Node.class, NODE_KEY).toInstance(); + + private static final InstanceIdentifier AUGMENT_WILDCARDED_PATH = InstanceIdentifier + .builder(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class).toInstance(); + + private static final InstanceIdentifier AUGMENT_NODE_PATH = InstanceIdentifier + .builder(Nodes.class).child(Node.class, NODE_KEY).augmentation(FlowCapableNode.class).toInstance(); + + @Test + public void writeNodeListenAugment() throws Exception { + + final SettableFuture, DataObject>> event = SettableFuture.create(); + + ListenerRegistration dclRegistration = baDataService.registerDataChangeListener( + AUGMENT_WILDCARDED_PATH, new DataChangeListener() { + + @Override + public void onDataChanged(final DataChangeEvent, DataObject> change) { + event.set(change); + } + }); + + DataModificationTransaction modification = baDataService.beginTransaction(); + + Node node = new NodeBuilder() // + .setKey(NODE_KEY) // + .addAugmentation(FlowCapableNode.class, flowCapableNode("one")).build(); + modification.putOperationalData(NODE_INSTANCE_ID_BA, node); + modification.commit().get(); + + DataChangeEvent, DataObject> receivedEvent = event.get(1000, TimeUnit.MILLISECONDS); + assertTrue(receivedEvent.getCreatedOperationalData().containsKey(AUGMENT_NODE_PATH)); + + dclRegistration.close(); + + DataModificationTransaction mod2 = baDataService.beginTransaction(); + mod2.putOperationalData(AUGMENT_NODE_PATH, flowCapableNode("two")); + mod2.commit().get(); + + FlowCapableNode readedAug = (FlowCapableNode) baDataService.readOperationalData(AUGMENT_NODE_PATH); + assertEquals("two", readedAug.getDescription()); + + } + + private FlowCapableNode flowCapableNode(final String description) { + return new FlowCapableNodeBuilder() // + .setDescription(description) // + .build(); + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java index 35b4e92db4..f7b81a44e9 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java @@ -54,13 +54,11 @@ public class WriteParentReadChildTest extends AbstractDataServiceTest { .child(Node.class, NODE_KEY).toInstance(); private static final InstanceIdentifier
TABLE_INSTANCE_ID_BA = // - InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) // + NODE_INSTANCE_ID_BA.builder() // .augmentation(FlowCapableNode.class).child(Table.class, TABLE_KEY).build(); private static final InstanceIdentifier FLOW_INSTANCE_ID_BA = // - InstanceIdentifier.builder(TABLE_INSTANCE_ID_BA) // - .child(Flow.class, FLOW_KEY) // - .toInstance(); + TABLE_INSTANCE_ID_BA.child(Flow.class, FLOW_KEY); /** * * The scenario tests writing parent node, which also contains child items @@ -103,11 +101,11 @@ public class WriteParentReadChildTest extends AbstractDataServiceTest { DataObject readedTable = baDataService.readConfigurationData(TABLE_INSTANCE_ID_BA); assertNotNull("Readed table should not be nul.", readedTable); assertTrue(readedTable instanceof Table); - + DataObject readedFlow = baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA); assertNotNull("Readed flow should not be null.",readedFlow); assertTrue(readedFlow instanceof Flow); assertEquals(flow, readedFlow); } -} \ No newline at end of file +} diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java index 1661ff230d..422b9ccee5 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java @@ -110,16 +110,14 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { private static final TableKey TABLE_KEY_BA = new TableKey((short) 0); private static final InstanceIdentifier FLOWS_PATH_BA = // - InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) // + NODE_INSTANCE_ID_BA.builder() // .augmentation(FlowCapableNode.class) // .child(Table.class, TABLE_KEY_BA) // .child(Flow.class) // .toInstance(); private static final InstanceIdentifier FLOW_INSTANCE_ID_BA = // - InstanceIdentifier.builder(FLOWS_PATH_BA.firstIdentifierOf(Table.class)) // - .child(Flow.class, FLOW_KEY) // - .toInstance(); + FLOWS_PATH_BA.firstIdentifierOf(Table.class).child(Flow.class, FLOW_KEY); @Test public void simpleModifyOperation() throws Exception { diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerMountPointTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerMountPointTest.java index 63094ef3cb..94570510ab 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerMountPointTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerMountPointTest.java @@ -61,8 +61,8 @@ public class CrossBrokerMountPointTest { .child(Node.class, NODE_KEY).toInstance(); private static GroupKey GROUP_KEY = new GroupKey(new GroupId(0L)); - private static final InstanceIdentifier GROUP_STATISTICS_ID_BA = InstanceIdentifier - .builder(NODE_INSTANCE_ID_BA).augmentation(FlowCapableNode.class) // + private static final InstanceIdentifier GROUP_STATISTICS_ID_BA = NODE_INSTANCE_ID_BA + .builder().augmentation(FlowCapableNode.class) // .child(Group.class, GROUP_KEY) // .augmentation(NodeGroupStatistics.class) // .child(GroupStatistics.class) // diff --git a/opendaylight/md-sal/sal-binding-it/pom.xml b/opendaylight/md-sal/sal-binding-it/pom.xml index 0d20a07ad5..70847aabea 100644 --- a/opendaylight/md-sal/sal-binding-it/pom.xml +++ b/opendaylight/md-sal/sal-binding-it/pom.xml @@ -77,14 +77,6 @@ org.opendaylight.controller sal-binding-broker-impl - - org.opendaylight.controller.thirdparty - nagasena - - - org.opendaylight.controller.thirdparty - nagasena-rta - org.opendaylight.yangtools.thirdparty antlr4-runtime-osgi-nohead @@ -100,6 +92,14 @@ xtend-lib-osgi 2.4.3 + + org.openexi + nagasena + + + org.openexi + nagasena-rta + org.ops4j.pax.exam pax-exam diff --git a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java index 166216b226..734733a19c 100644 --- a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java +++ b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java @@ -68,8 +68,8 @@ public class TestHelper { mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), // mavenBundle(CONTROLLER, "netconf-util").versionAsInProject(), // - mavenBundle(CONTROLLER + ".thirdparty", "nagasena").versionAsInProject(), // - mavenBundle(CONTROLLER + ".thirdparty", "nagasena-rta").versionAsInProject(), // + mavenBundle("org.openexi", "nagasena").versionAsInProject(), // + mavenBundle("org.openexi", "nagasena-rta").versionAsInProject(), // mavenBundle(CONTROLLER + ".thirdparty", "ganymed").versionAsInProject(), // mavenBundle(CONTROLLER, "netconf-mapping-api").versionAsInProject(), // diff --git a/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java b/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java index 3d78f94861..b2f89cf779 100644 --- a/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java +++ b/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java @@ -70,8 +70,8 @@ public abstract class AbstractTest { mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), // mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), // mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), - mavenBundle("org.opendaylight.controller.thirdparty", "nagasena").versionAsInProject(), - mavenBundle("org.opendaylight.controller.thirdparty", "nagasena-rta").versionAsInProject(), + mavenBundle("org.openexi", "nagasena").versionAsInProject(), + mavenBundle("org.openexi", "nagasena-rta").versionAsInProject(), // systemProperty("osgi.bundles.defaultStartLevel").value("4"), systemPackages("sun.nio.ch"), diff --git a/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/NoficationTest.java b/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/NotificationTest.java similarity index 99% rename from opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/NoficationTest.java rename to opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/NotificationTest.java index 9519a2a732..e6bbaab2d9 100644 --- a/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/NoficationTest.java +++ b/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/NotificationTest.java @@ -16,6 +16,7 @@ import java.util.Collection; import java.util.List; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; @@ -36,7 +37,8 @@ import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.binding.NotificationListener; import org.opendaylight.yangtools.yang.binding.RpcService; -public class NoficationTest extends AbstractTest { +@Ignore +public class NotificationTest extends AbstractTest { private final FlowListener listener1 = new FlowListener(); private final FlowListener listener2 = new FlowListener(); diff --git a/opendaylight/md-sal/sal-binding-it/src/test/resources/controller.xml b/opendaylight/md-sal/sal-binding-it/src/test/resources/controller.xml index 08d22b96d6..37ef257224 100644 --- a/opendaylight/md-sal/sal-binding-it/src/test/resources/controller.xml +++ b/opendaylight/md-sal/sal-binding-it/src/test/resources/controller.xml @@ -147,6 +147,7 @@ + binding:binding-broker-osgi-registry @@ -158,6 +159,13 @@ + + binding:binding-rpc-registry + + binding-rpc-broker + /modules/module[type='binding-broker-impl'][name='binding-broker-impl'] + + binding-impl:binding-dom-mapping-service diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RoutedRegistration.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RoutedRegistration.java index 5200c90561..6ce7b5a5c7 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RoutedRegistration.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RoutedRegistration.java @@ -15,4 +15,6 @@ public interface RoutedRegistration, S> extends Registratio void registerPath(C context, P path); void unregisterPath(C context, P path); + @Override + void close(); } diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.java index 82ce44c5e9..d8bde3d41a 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.java @@ -14,14 +14,12 @@ import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import org.eclipse.xtext.xbase.lib.Exceptions; 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.DataChangeEvent; @@ -46,6 +44,7 @@ import org.slf4j.LoggerFactory; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; +import com.google.common.base.Supplier; import com.google.common.collect.FluentIterable; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; @@ -120,9 +119,9 @@ public abstract class AbstractDataBroker

, D extends Object, DC } protected ImmutableList> affectedCommitHandlers(final Set

paths) { - final Callable>> _function = new Callable>>() { + final Supplier>> _function = new Supplier>>() { @Override - public ImmutableList> call() throws Exception { + public ImmutableList> get() { Map>> _asMap = commitHandlers.asMap(); Set>>> _entrySet = _asMap.entrySet(); FluentIterable>>> _from = FluentIterable @@ -163,9 +162,9 @@ public abstract class AbstractDataBroker

, D extends Object, DC } protected ImmutableList> probablyAffectedCommitHandlers(final HashSet

paths) { - final Callable>> _function = new Callable>>() { + final Supplier>> _function = new Supplier>>() { @Override - public ImmutableList> call() throws Exception { + public ImmutableList> get() { Map>> _asMap = commitHandlers.asMap(); Set>>> _entrySet = _asMap.entrySet(); FluentIterable>>> _from = FluentIterable @@ -221,12 +220,10 @@ public abstract class AbstractDataBroker

, D extends Object, DC return _dataReadRouter.readOperationalData(path); } - private static T withLock(final Lock lock, final Callable method) { + private static T withLock(final Lock lock, final Supplier method) { lock.lock(); try { - return method.call(); - } catch (Exception e) { - throw Exceptions.sneakyThrow(e); + return method.get(); } finally { lock.unlock(); } diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/ImmutableDataChangeEvent.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/ImmutableDataChangeEvent.java index a91799d458..19235d2ddf 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/ImmutableDataChangeEvent.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/ImmutableDataChangeEvent.java @@ -11,6 +11,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; public final class ImmutableDataChangeEvent

, D> implements DataChangeEvent { @@ -127,6 +128,8 @@ public final class ImmutableDataChangeEvent

, D> implements Dat originalOperational.putAll(Maps.filterKeys(data.getOriginalOperationalData(), keyFilter)); createdOperational.putAll(Maps.filterKeys(data.getCreatedOperationalData(), keyFilter)); createdConfiguration.putAll(Maps.filterKeys(data.getCreatedConfigurationData(), keyFilter)); + removedOperational.addAll(Sets.filter(data.getRemovedOperationalData(), keyFilter)); + removedConfiguration.addAll(Sets.filter(data.getRemovedConfigurationData(), keyFilter)); return this; } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java index a7952ac824..375376f383 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ChangeListenerNotifyTask.java @@ -1,3 +1,10 @@ +/* + * 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.store.impl; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DOMImmutableDataChangeEvent.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DOMImmutableDataChangeEvent.java index 3dfca40b40..af479743aa 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DOMImmutableDataChangeEvent.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DOMImmutableDataChangeEvent.java @@ -1,3 +1,10 @@ +/* + * 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.store.impl; import java.util.Collections; diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java index 9961fcce8d..11028dc842 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataAndMetadataSnapshot.java @@ -16,7 +16,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import com.google.common.base.Optional; -import com.google.common.primitives.UnsignedLong; class DataAndMetadataSnapshot { @@ -39,22 +38,14 @@ class DataAndMetadataSnapshot { public static DataAndMetadataSnapshot createEmpty(final NodeIdentifier rootNode) { NormalizedNode data = Builders.containerBuilder().withNodeIdentifier(rootNode).build(); - StoreMetadataNode metadata = StoreMetadataNode.builder() - .setNodeVersion(UnsignedLong.ZERO) - .setSubtreeVersion(UnsignedLong.ZERO) - .setData(data) - .build(); + StoreMetadataNode metadata = StoreMetadataNode.createEmpty(data); return new DataAndMetadataSnapshot(metadata,Optional.absent()); } public static DataAndMetadataSnapshot createEmpty(final SchemaContext ctx) { NodeIdentifier rootNodeIdentifier = new NodeIdentifier(ctx.getQName()); NormalizedNode data = Builders.containerBuilder().withNodeIdentifier(rootNodeIdentifier).build(); - StoreMetadataNode metadata = StoreMetadataNode.builder() - .setData(data) - .setNodeVersion(UnsignedLong.ZERO) - .setSubtreeVersion(UnsignedLong.ZERO) - .build(); + StoreMetadataNode metadata = StoreMetadataNode.createEmpty(data); return new DataAndMetadataSnapshot(metadata, Optional.of(ctx)); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataChangeListenerRegistration.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataChangeListenerRegistration.java index d3a892a2cd..d8f024017f 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataChangeListenerRegistration.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataChangeListenerRegistration.java @@ -1,3 +1,10 @@ +/* + * 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.store.impl; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; @@ -6,17 +13,11 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -public interface DataChangeListenerRegistration>> -extends ListenerRegistration { - - +public interface DataChangeListenerRegistration>> extends ListenerRegistration { @Override - public L getInstance(); + L getInstance(); InstanceIdentifier getPath(); DataChangeScope getScope(); - - - } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataPreconditionFailedException.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataPreconditionFailedException.java new file mode 100644 index 0000000000..6baf7647bd --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataPreconditionFailedException.java @@ -0,0 +1,50 @@ +/* + * 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.store.impl; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +public class DataPreconditionFailedException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 596430355175413427L; + private final InstanceIdentifier path; + + public DataPreconditionFailedException(final InstanceIdentifier path) { + this.path = path; + } + + public DataPreconditionFailedException(final InstanceIdentifier path,final String message) { + super(message); + this.path = path; + } + + + public DataPreconditionFailedException(final InstanceIdentifier path,final Throwable cause) { + super(cause); + this.path = path; + } + + public DataPreconditionFailedException(final InstanceIdentifier path,final String message, final Throwable cause) { + super(message, cause); + this.path = path; + } + + public DataPreconditionFailedException(final InstanceIdentifier path,final String message, final Throwable cause, final boolean enableSuppression, + final boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + this.path = path; + } + + public InstanceIdentifier getPath() { + return path; + } + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java index 9bbba1e24d..005e3b772d 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java @@ -54,7 +54,6 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class); private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build(); - private final ListeningExecutorService executor; private final String name; private final AtomicLong txCounter = new AtomicLong(0); @@ -90,7 +89,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public DOMStoreWriteTransaction newWriteOnlyTransaction() { - return new SnaphostBackedWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree); + return new SnapshotBackedWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree); } @Override @@ -104,15 +103,15 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch final InstanceIdentifier path, final L listener, final DataChangeScope scope) { /* - * Make sure commit is not occurring right now. Listener has to be registered and its - * state capture enqueued at a consistent point. + * Make sure commit is not occurring right now. Listener has to be + * registered and its state capture enqueued at a consistent point. * - * FIXME: improve this to read-write lock, such that multiple listener registrations - * can occur simultaneously + * FIXME: improve this to read-write lock, such that multiple listener + * registrations can occur simultaneously */ final DataChangeListenerRegistration reg; synchronized (this) { - LOG.debug("{}: Registering data change listener {} for {}",name,listener,path); + LOG.debug("{}: Registering data change listener {} for {}", name, listener, path); reg = listenerTree.registerDataChangeListener(path, listener, scope); @@ -138,9 +137,8 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch }; } - private synchronized DOMStoreThreePhaseCommitCohort submit( - final SnaphostBackedWriteTransaction writeTx) { - LOG.debug("Tx: {} is submitted. Modifications: {}",writeTx.getIdentifier(),writeTx.getMutatedView()); + private synchronized DOMStoreThreePhaseCommitCohort submit(final SnapshotBackedWriteTransaction writeTx) { + LOG.debug("Tx: {} is submitted. Modifications: {}", writeTx.getIdentifier(), writeTx.getMutatedView()); return new ThreePhaseCommitImpl(writeTx); } @@ -148,12 +146,13 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch return name + "-" + txCounter.getAndIncrement(); } - private void commit(final DataAndMetadataSnapshot currentSnapshot, - final StoreMetadataNode newDataTree, final ResolveDataChangeEventsTask listenerResolver) { - LOG.debug("Updating Store snaphot version: {} with version:{}",currentSnapshot.getMetadataTree().getSubtreeVersion(),newDataTree.getSubtreeVersion()); + private void commit(final DataAndMetadataSnapshot currentSnapshot, final StoreMetadataNode newDataTree, + final ResolveDataChangeEventsTask listenerResolver) { + LOG.debug("Updating Store snaphot version: {} with version:{}", currentSnapshot.getMetadataTree() + .getSubtreeVersion(), newDataTree.getSubtreeVersion()); - if(LOG.isTraceEnabled()) { - LOG.trace("Data Tree is {}",StoreUtils.toStringTree(newDataTree)); + if (LOG.isTraceEnabled()) { + LOG.trace("Data Tree is {}", StoreUtils.toStringTree(newDataTree)); } final DataAndMetadataSnapshot newSnapshot = DataAndMetadataSnapshot.builder() // @@ -162,14 +161,15 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch .build(); /* - * The commit has to occur atomically with regard to listener registrations. + * The commit has to occur atomically with regard to listener + * registrations. */ synchronized (this) { final boolean success = snapshot.compareAndSet(currentSnapshot, newSnapshot); checkState(success, "Store snapshot and transaction snapshot differ. This should never happen."); for (ChangeListenerNotifyTask task : listenerResolver.call()) { - LOG.trace("Scheduling invocation of listeners: {}",task); + LOG.trace("Scheduling invocation of listeners: {}", task); executor.submit(task); } } @@ -195,7 +195,8 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch /** * Add class-specific toString attributes. * - * @param toStringHelper ToStringHelper instance + * @param toStringHelper + * ToStringHelper instance * @return ToStringHelper instance which was passed in */ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { @@ -203,13 +204,15 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch } } - private static class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements DOMStoreReadTransaction { + private static class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements + DOMStoreReadTransaction { private DataAndMetadataSnapshot stableSnapshot; public SnapshotBackedReadTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot) { super(identifier); this.stableSnapshot = Preconditions.checkNotNull(snapshot); - LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree().getSubtreeVersion()); + LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree() + .getSubtreeVersion()); } @Override @@ -226,17 +229,19 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch } } - private static class SnaphostBackedWriteTransaction extends AbstractDOMStoreTransaction implements DOMStoreWriteTransaction { + private static class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements + DOMStoreWriteTransaction { private MutableDataTree mutableTree; private InMemoryDOMDataStore store; private boolean ready = false; - public SnaphostBackedWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot, + public SnapshotBackedWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot, final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) { super(identifier); mutableTree = MutableDataTree.from(snapshot, applyOper); this.store = store; - LOG.debug("Write Tx: {} allocated with snapshot {}",identifier,snapshot.getMetadataTree().getSubtreeVersion()); + LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree() + .getSubtreeVersion()); } @Override @@ -250,11 +255,11 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch public void write(final InstanceIdentifier path, final NormalizedNode data) { checkNotReady(); try { - LOG.trace("Tx: {} Write: {}:{}",getIdentifier(),path,data); + LOG.trace("Tx: {} Write: {}:{}", getIdentifier(), path, data); mutableTree.write(path, data); - // FIXME: Add checked exception + // FIXME: Add checked exception } catch (Exception e) { - LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e); + LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, mutableTree, e); } } @@ -262,11 +267,11 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch public void merge(final InstanceIdentifier path, final NormalizedNode data) { checkNotReady(); try { - LOG.trace("Tx: {} Merge: {}:{}",getIdentifier(),path,data); + LOG.trace("Tx: {} Merge: {}:{}", getIdentifier(), path, data); mutableTree.merge(path, data); - // FIXME: Add checked exception + // FIXME: Add checked exception } catch (Exception e) { - LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e); + LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, mutableTree, e); } } @@ -274,11 +279,11 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch public void delete(final InstanceIdentifier path) { checkNotReady(); try { - LOG.trace("Tx: {} Delete: {}",getIdentifier(),path); + LOG.trace("Tx: {} Delete: {}", getIdentifier(), path); mutableTree.delete(path); - // FIXME: Add checked exception + // FIXME: Add checked exception } catch (Exception e) { - LOG.error("Tx: {}, failed to delete {} in {}",getIdentifier(),path,mutableTree,e); + LOG.error("Tx: {}, failed to delete {} in {}", getIdentifier(), path, mutableTree, e); } } @@ -310,7 +315,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch } } - private static class SnapshotBackedReadWriteTransaction extends SnaphostBackedWriteTransaction implements + private static class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction implements DOMStoreReadWriteTransaction { protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot, @@ -320,11 +325,11 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public ListenableFuture>> read(final InstanceIdentifier path) { - LOG.trace("Tx: {} Read: {}",getIdentifier(),path); + LOG.trace("Tx: {} Read: {}", getIdentifier(), path); try { return Futures.immediateFuture(getMutatedView().read(path)); } catch (Exception e) { - LOG.error("Tx: {} Failed Read of {}",getIdentifier(),path,e); + LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e); throw e; } } @@ -332,14 +337,14 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch private class ThreePhaseCommitImpl implements DOMStoreThreePhaseCommitCohort { - private final SnaphostBackedWriteTransaction transaction; + private final SnapshotBackedWriteTransaction transaction; private final NodeModification modification; private DataAndMetadataSnapshot storeSnapshot; private Optional proposedSubtree; private ResolveDataChangeEventsTask listenerResolver; - public ThreePhaseCommitImpl(final SnaphostBackedWriteTransaction writeTransaction) { + public ThreePhaseCommitImpl(final SnapshotBackedWriteTransaction writeTransaction) { this.transaction = writeTransaction; this.modification = transaction.getMutatedView().getRootModification(); } @@ -353,9 +358,16 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public Boolean call() throws Exception { - boolean applicable = snapshotOperation.isApplicable(modification, + Boolean applicable = false; + try { + snapshotOperation.checkApplicable(PUBLIC_ROOT_PATH, modification, Optional.of(snapshotCapture.getMetadataTree())); - LOG.debug("Store Transcation: {} : canCommit : {}", transaction.getIdentifier(), applicable); + applicable = true; + } catch (DataPreconditionFailedException e) { + LOG.warn("Store Tx: {} Data Precondition failed for {}.",transaction.getIdentifier(),e.getPath(),e); + applicable = false; + } + LOG.debug("Store Transaction: {} : canCommit : {}", transaction.getIdentifier(), applicable); return applicable; } }); @@ -364,13 +376,11 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public ListenableFuture preCommit() { storeSnapshot = snapshot.get(); - if(modification.getModificationType() == ModificationType.UNMODIFIED) { + if (modification.getModificationType() == ModificationType.UNMODIFIED) { return Futures.immediateFuture(null); } return executor.submit(new Callable() { - - @Override public Void call() throws Exception { StoreMetadataNode metadataTree = storeSnapshot.getMetadataTree(); @@ -399,14 +409,14 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch @Override public ListenableFuture commit() { - if(modification.getModificationType() == ModificationType.UNMODIFIED) { + if (modification.getModificationType() == ModificationType.UNMODIFIED) { return Futures.immediateFuture(null); } - checkState(proposedSubtree != null,"Proposed subtree must be computed"); - checkState(storeSnapshot != null,"Proposed subtree must be computed"); + checkState(proposedSubtree != null, "Proposed subtree must be computed"); + checkState(storeSnapshot != null, "Proposed subtree must be computed"); // return ImmediateFuture<>; - InMemoryDOMDataStore.this.commit(storeSnapshot, proposedSubtree.get(),listenerResolver); + InMemoryDOMDataStore.this.commit(storeSnapshot, proposedSubtree.get(), listenerResolver); return Futures. immediateFuture(null); } @@ -421,7 +431,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable, Sch } @Override - public boolean isApplicable(final NodeModification modification, final Optional storeMetadata) { + public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional storeMetadata) { throw new IllegalStateException("Schema Context is not available."); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationApplyOperation.java index d02f1109d7..361be6800c 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationApplyOperation.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ModificationApplyOperation.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl; import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import com.google.common.base.Optional; @@ -59,17 +60,6 @@ public interface ModificationApplyOperation extends StoreTreeNode apply(NodeModification modification, Optional storeMeta, UnsignedLong subtreeVersion); - /** - * - * Checks if provided node modification could be applied to current metadata node. - * - * @param modification Modification - * @param current Metadata Node to which modification should be applied - * @return true if modification is applicable - * false if modification is no applicable - */ - boolean isApplicable(NodeModification modification, Optional current); - /** * * Performs structural verification of NodeModification, such as writen values / types @@ -87,8 +77,17 @@ public interface ModificationApplyOperation extends StoreTreeNode getChild(PathArgument child); - - + Optional getChild(PathArgument child); + /** + * + * Checks if provided node modification could be applied to current metadata node. + * + * @param modification Modification + * @param current Metadata Node to which modification should be applied + * @return true if modification is applicable + * false if modification is no applicable + * @throws DataPreconditionFailedException + */ + void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional current) throws DataPreconditionFailedException; } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/OperationWithModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/OperationWithModification.java index 35864b6bc2..780291e70f 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/OperationWithModification.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/OperationWithModification.java @@ -1,3 +1,10 @@ +/* + * 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.store.impl; import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification; @@ -38,10 +45,6 @@ public class OperationWithModification { return applyOperation; } - public boolean isApplicable(final Optional data) { - return applyOperation.isApplicable(modification, data); - } - public Optional apply(final Optional data, final UnsignedLong subtreeVersion) { return applyOperation.apply(modification, data, subtreeVersion); } @@ -63,4 +66,4 @@ public class OperationWithModification { Optional childOp = applyOperation.getChild(childId); return from(childOp.get(),childMod); } -} \ No newline at end of file +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java index c62c27dea8..44d50166af 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java @@ -327,12 +327,12 @@ public class ResolveDataChangeEventsTask implements Callable listeners, final NormalizedNode beforeData, final NormalizedNode afterData) { - if (beforeData instanceof NormalizedNodeContainer && !listeners.isEmpty()) { + if (beforeData instanceof NormalizedNodeContainer) { // Node is container (contains child) and we have interested // listeners registered for it, that means we need to do // resolution of changes on children level and can not // shortcut resolution. - + LOG.trace("Resolving subtree replace event for {} before {}, after {}",path,beforeData,afterData); @SuppressWarnings("unchecked") NormalizedNodeContainer> beforeCont = (NormalizedNodeContainer>) beforeData; @SuppressWarnings("unchecked") @@ -342,7 +342,7 @@ public class ResolveDataChangeEventsTask implements Callable listeners, final NormalizedNode node, final SimpleEventFactory eventFactory) { + final DOMImmutableDataChangeEvent event = eventFactory.create(path, node); + DOMImmutableDataChangeEvent propagateEvent = event; + // We have listeners for this node or it's children, so we will try + // to do additional processing + if (node instanceof NormalizedNodeContainer) { + LOG.trace("Resolving subtree recursive event for {}, type {}", path, eventFactory); - DOMImmutableDataChangeEvent event = eventFactory.create(path, node); + Builder eventBuilder = builder(DataChangeScope.BASE); + eventBuilder.merge(event); + eventBuilder.setBefore(event.getOriginalSubtree()); + eventBuilder.setAfter(event.getUpdatedSubtree()); - if (!listeners.isEmpty()) { - // We have listeners for this node or it's children, so we will try - // to do additional processing - if (node instanceof NormalizedNodeContainer) { - // Node has children, so we will try to resolve it's children - // changes. - @SuppressWarnings("unchecked") - NormalizedNodeContainer> container = (NormalizedNodeContainer>) node; - for (NormalizedNode child : container.getValue()) { - PathArgument childId = child.getIdentifier(); - Collection childListeners = getListenerChildrenWildcarded(listeners, childId); - if (!childListeners.isEmpty()) { - resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory); - } - } + // Node has children, so we will try to resolve it's children + // changes. + @SuppressWarnings("unchecked") + NormalizedNodeContainer> container = (NormalizedNodeContainer>) node; + for (NormalizedNode child : container.getValue()) { + PathArgument childId = child.getIdentifier(); + LOG.trace("Resolving event for child {}", childId); + Collection childListeners = getListenerChildrenWildcarded(listeners, childId); + eventBuilder.merge(resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory)); } - addPartialTask(listeners, event); + propagateEvent = eventBuilder.build(); + } else { + // We do not dispatch leaf events since Binding Aware components do not support them. + propagateEvent = builder(DataChangeScope.BASE).build(); } - return event; + if (!listeners.isEmpty()) { + addPartialTask(listeners, propagateEvent); + } + return propagateEvent; } private DOMImmutableDataChangeEvent resolveSubtreeChangeEvent(final InstanceIdentifier path, @@ -476,7 +486,7 @@ public class ResolveDataChangeEventsTask implements Callable listeners, final DOMImmutableDataChangeEvent event) { - for (ListenerTree.Node listenerNode : listeners) { if (!listenerNode.getListeners().isEmpty()) { + LOG.trace("Adding event {} for listeners {}",event,listenerNode); events.put(listenerNode, event); } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java index a5c9b7983a..2af522ea86 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperation.java @@ -1,7 +1,15 @@ +/* + * 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.store.impl; import static com.google.common.base.Preconditions.checkArgument; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -12,6 +20,7 @@ import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; @@ -26,18 +35,21 @@ import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode; import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; -import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; @@ -56,8 +68,6 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSet.Builder; import com.google.common.primitives.UnsignedLong; public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { @@ -70,7 +80,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } else if (schemaNode instanceof ChoiceNode) { return new ChoiceModificationStrategy((ChoiceNode) schemaNode); } else if (schemaNode instanceof LeafListSchemaNode) { - return new LeafSetEntryModificationStrategy((LeafListSchemaNode) schemaNode); + return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode); } else if (schemaNode instanceof LeafSchemaNode) { return new LeafModificationStrategy((LeafSchemaNode) schemaNode); } @@ -89,6 +99,15 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper return new UnorderedMapModificationStrategy(schemaNode); } + private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) { + if(schemaNode.isUserOrdered()) { + return new OrderedLeafSetModificationStrategy(schemaNode); + } else { + return new UnorderedLeafSetModificationStrategy(schemaNode); + } + } + + public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree, final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) { AugmentationSchema augSchema = null; @@ -123,55 +142,52 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper protected abstract void verifyWritenStructure(NormalizedNode writenValue); @Override - public boolean isApplicable(final NodeModification modification, final Optional current) { + public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { switch (modification.getModificationType()) { case DELETE: - return isDeleteApplicable(modification, current); + checkDeleteApplicable(modification, current); case SUBTREE_MODIFIED: - return isSubtreeModificationApplicable(modification, current); + checkSubtreeModificationApplicable(path,modification, current); + return; case WRITE: - return isWriteApplicable(modification, current); + checkWriteApplicable(path,modification, current); + return; case MERGE: - return isMergeApplicable(modification,current); + checkMergeApplicable(path,modification,current); + return; case UNMODIFIED: - return true; + return; default: - return false; + throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported."); } + } - private boolean isMergeApplicable(final NodeModification modification, final Optional current) { + protected void checkMergeApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { Optional original = modification.getOriginal(); if (original.isPresent() && current.isPresent()) { - return isNotConflicting(original.get(), current.get()); - } else if (current.isPresent()) { - return true; + checkNotConflicting(path,original.get(), current.get()); } - return true; } - protected boolean isWriteApplicable(final NodeModification modification, final Optional current) { + protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { Optional original = modification.getOriginal(); if (original.isPresent() && current.isPresent()) { - return isNotConflicting(original.get(), current.get()); - } else if (current.isPresent()) { - return false; + checkNotConflicting(path,original.get(), current.get()); + } else if(original.isPresent()) { + throw new DataPreconditionFailedException(path,"Node was deleted by other transaction."); } - return true; - } - protected final boolean isNotConflicting(final StoreMetadataNode original, final StoreMetadataNode current) { - return original.getNodeVersion().equals(current.getNodeVersion()) - && original.getSubtreeVersion().equals(current.getSubtreeVersion()); + protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException { + checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction."); + checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction"); } - protected abstract boolean isSubtreeModificationApplicable(final NodeModification modification, - final Optional current); + protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException; - private boolean isDeleteApplicable(final NodeModification modification, final Optional current) { - // FiXME: Add delete conflict detection. - return true; + private void checkDeleteApplicable(final NodeModification modification, final Optional current) { } @Override @@ -253,9 +269,9 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } @Override - protected boolean isSubtreeModificationApplicable(final NodeModification modification, - final Optional current) { - return false; + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); } } @@ -294,6 +310,14 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } } + @Override + protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + // FIXME: Implement proper write check for replacement of node container + // prerequisite is to have transaction chain available for clients + // otherwise this will break chained writes to same node. + } + @SuppressWarnings("rawtypes") @Override protected void verifyWritenStructure(final NormalizedNode writenValue) { @@ -309,30 +333,28 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @Override protected StoreMetadataNode applyWrite(final NodeModification modification, final Optional currentMeta, final UnsignedLong subtreeVersion) { - // + NormalizedNode newValue = modification.getWritenValue(); - UnsignedLong nodeVersion = subtreeVersion; + final UnsignedLong nodeVersion; if (currentMeta.isPresent()) { nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion()); + } else { + nodeVersion = subtreeVersion; } - StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion); + final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion); if (!modification.hasAdditionalModifications()) { return newValueMeta; } + @SuppressWarnings("rawtypes") - NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier()); + NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue); StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) // .setNodeVersion(nodeVersion) // .setSubtreeVersion(subtreeVersion); - Set processedPreexisting = applyPreexistingChildren(modification, newValueMeta.getChildren(), - builder, nodeVersion); - applyNewChildren(modification, processedPreexisting, builder, nodeVersion); - - return builder.build(); - + return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion); } @Override @@ -345,75 +367,64 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @Override public StoreMetadataNode applySubtreeChange(final NodeModification modification, final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { + // Bump subtree version to its new target + final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion()); - UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion()); @SuppressWarnings("rawtypes") - NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier()); - StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) + NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData()); + StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder, currentMeta) .setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion()) .setSubtreeVersion(updatedSubtreeVersion); - // We process preexisting nodes - Set processedPreexisting = applyPreexistingChildren(modification, currentMeta.getChildren(), - builder, updatedSubtreeVersion); - applyNewChildren(modification, processedPreexisting, builder, updatedSubtreeVersion); - return builder.build(); + + return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion); } - private void applyNewChildren(final NodeModification modification, final Set ignore, - final StoreNodeCompositeBuilder builder, final UnsignedLong subtreeVersion) { - for (NodeModification childModification : modification.getModifications()) { - PathArgument childIdentifier = childModification.getIdentifier(); - // We skip allready processed modifications - if (ignore.contains(childIdentifier)) { - continue; - } + private StoreMetadataNode mutateChildren(final Iterable modifications, final StoreMetadataNode meta, + final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) { - builder.addIfPresent(resolveChildOperation(childIdentifier) // - .apply(childModification, Optional. absent(), subtreeVersion)); - } - } + for (NodeModification mod : modifications) { + final PathArgument id = mod.getIdentifier(); + final Optional cm = meta.getChild(id); - private Set applyPreexistingChildren(final NodeModification modification, - final Iterable children, final StoreNodeCompositeBuilder nodeBuilder, - final UnsignedLong subtreeVersion) { - Builder processedModifications = ImmutableSet. builder(); - for (StoreMetadataNode childMeta : children) { - PathArgument childIdentifier = childMeta.getIdentifier(); - // We retrieve Child modification metadata - Optional childModification = modification.getChild(childIdentifier); - // Node is modified - if (childModification.isPresent()) { - processedModifications.add(childIdentifier); - Optional result = resolveChildOperation(childIdentifier) // - .apply(childModification.get(), Optional.of(childMeta), subtreeVersion); - nodeBuilder.addIfPresent(result); + Optional result = resolveChildOperation(id).apply(mod, cm, nodeVersion); + if (result.isPresent()) { + builder.add(result.get()); } else { - // Child is unmodified - reuse existing metadata and data - // snapshot - nodeBuilder.add(childMeta); + builder.remove(id); } } - return processedModifications.build(); + + return builder.build(); } @Override - protected boolean isSubtreeModificationApplicable(final NodeModification modification, - final Optional current) { - if (false == current.isPresent()) { - return false; - } - boolean result = true; + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction."); + checkChildPreconditions(path,modification,current); + + } + + private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional current) throws DataPreconditionFailedException { StoreMetadataNode currentMeta = current.get(); for (NodeModification childMod : modification.getModifications()) { PathArgument childId = childMod.getIdentifier(); Optional childMeta = currentMeta.getChild(childId); - result &= resolveChildOperation(childId).isApplicable(childMod, childMeta); + InstanceIdentifier childPath = StoreUtils.append(path, childId); + resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta); + } + } + + @Override + protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + if(current.isPresent()) { + checkChildPreconditions(path,modification,current); } - return result; } @SuppressWarnings("rawtypes") - protected abstract NormalizedNodeContainerBuilder createBuilder(PathArgument identifier); + protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode original); } public static abstract class DataNodeContainerModificationStrategy extends @@ -458,7 +469,7 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @Override @SuppressWarnings("rawtypes") - protected abstract DataContainerNodeBuilder createBuilder(PathArgument identifier); + protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode original); @Override public String toString() { @@ -476,12 +487,10 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @Override @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) { - // TODO Auto-generated method stub - checkArgument(identifier instanceof NodeIdentifier); - return ImmutableContainerNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier); + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof ContainerNode); + return ImmutableContainerNodeBuilder.create((ContainerNode) original); } - } public static class UnkeyedListItemModificationStrategy extends @@ -493,27 +502,25 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @Override @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) { - checkArgument(identifier instanceof NodeIdentifier); - return ImmutableUnkeyedListEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier); + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof UnkeyedListEntryNode); + return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original); } - } public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy { protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) { - super(schema, AugmentationNode.class); - // FIXME: Use resolved children instead of unresolved. - + super(createAugmentProxy(schema,resolved), AugmentationNode.class); } @Override - protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) { - return Builders.augmentationBuilder().withNodeIdentifier((AugmentationIdentifier) identifier); + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof AugmentationNode); + return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original); } - } public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy { @@ -542,11 +549,10 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @Override @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) { - checkArgument(identifier instanceof NodeIdentifier); - return ImmutableChoiceNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier); + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode); + return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original); } - } public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy { @@ -557,26 +563,27 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @Override @SuppressWarnings("rawtypes") - protected final DataContainerNodeBuilder createBuilder(final PathArgument identifier) { - return ImmutableMapEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifierWithPredicates) identifier); + protected final DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof MapEntryNode); + return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original); } - } - public static class LeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { + public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { private final Optional entryStrategy; @SuppressWarnings({ "unchecked", "rawtypes" }) - protected LeafSetModificationStrategy(final LeafListSchemaNode schema) { + protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { super((Class) LeafSetNode.class); entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); } @SuppressWarnings("rawtypes") @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) { - return ImmutableLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier); + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof LeafSetNode); + return ImmutableLeafSetNodeBuilder.create((LeafSetNode) original); } @Override @@ -586,7 +593,32 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } return Optional.absent(); } + } + + public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { + super((Class) LeafSetNode.class); + entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); + } + + @SuppressWarnings("rawtypes") + @Override + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof OrderedLeafSetNode); + return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode) original); + } + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeWithValue) { + return entryStrategy; + } + return Optional.absent(); + } } public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation { @@ -629,9 +661,9 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } @Override - protected boolean isSubtreeModificationApplicable(final NodeModification modification, - final Optional current) { - return false; + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); } } @@ -647,8 +679,9 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @SuppressWarnings("rawtypes") @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) { - return ImmutableMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier); + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof MapNode); + return ImmutableMapNodeBuilder.create((MapNode) original); } @Override @@ -676,8 +709,9 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper @SuppressWarnings("rawtypes") @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) { - return ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier); + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof OrderedMapNode); + return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original); } @Override @@ -698,4 +732,19 @@ public abstract class SchemaAwareApplyOperation implements ModificationApplyOper } + public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) { + Set realChildSchemas = new HashSet<>(); + for(DataSchemaNode augChild : schema.getChildNodes()) { + realChildSchemas.add(resolved.getDataChildByName(augChild.getQName())); + } + return new AugmentationSchemaProxy(schema, realChildSchemas); + } + + public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException { + if(!condition) { + throw new DataPreconditionFailedException(path, message); + } + return condition; + } + } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperationRoot.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperationRoot.java index e7265dedb5..8a539ff36e 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperationRoot.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SchemaAwareApplyOperationRoot.java @@ -7,16 +7,14 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; public class SchemaAwareApplyOperationRoot extends SchemaAwareApplyOperation.DataNodeContainerModificationStrategy { - private final SchemaContext context; public SchemaAwareApplyOperationRoot(final SchemaContext context) { @@ -24,11 +22,6 @@ public class SchemaAwareApplyOperationRoot extends SchemaAwareApplyOperation.Dat this.context = context; } - @Override - protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) { - return ImmutableContainerNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier); - } - public SchemaContext getContext() { return context; } @@ -38,4 +31,9 @@ public class SchemaAwareApplyOperationRoot extends SchemaAwareApplyOperation.Dat return "SchemaAwareApplyOperationRoot [context=" + context + "]"; } + @Override + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(NormalizedNode original) { + return ImmutableContainerNodeBuilder.create((ContainerNode) original); + } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/StoreUtils.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/StoreUtils.java index 830d7e3dc4..0f77ac504a 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/StoreUtils.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/StoreUtils.java @@ -1,3 +1,10 @@ +/* + * 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.store.impl; import java.util.Collections; diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreMetadataNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreMetadataNode.java index d42f36fb90..455777b7fb 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreMetadataNode.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreMetadataNode.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree; import static com.google.common.base.Preconditions.checkState; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; @@ -46,10 +47,24 @@ public class StoreMetadataNode implements Immutable, Identifiable, this.children = Preconditions.checkNotNull(children); } + public static StoreMetadataNode createEmpty(final NormalizedNode data) { + return new StoreMetadataNode(data, UnsignedLong.ZERO, UnsignedLong.ZERO, + Collections.emptyMap()); + } + + public StoreMetadataNode(final NormalizedNode data, final UnsignedLong nodeVersion, + final UnsignedLong subtreeVersion) { + this(data, nodeVersion, subtreeVersion, Collections.emptyMap()); + } + public static Builder builder() { return new Builder(); } + public static Builder builder(StoreMetadataNode node) { + return new Builder(node); + } + public UnsignedLong getNodeVersion() { return this.nodeVersion; } @@ -118,11 +133,16 @@ public class StoreMetadataNode implements Immutable, Identifiable, private UnsignedLong nodeVersion; private UnsignedLong subtreeVersion; private NormalizedNode data; - private Map children = new LinkedHashMap<>(); + private Map children; private boolean dirty = false; - private Builder() {} + private Builder() { + children = new LinkedHashMap<>(); + } + public Builder(StoreMetadataNode node) { + children = new LinkedHashMap<>(node.children); + } public UnsignedLong getVersion() { return nodeVersion; @@ -153,6 +173,15 @@ public class StoreMetadataNode implements Immutable, Identifiable, return this; } + public Builder remove(final PathArgument id) { + if (dirty) { + children = new LinkedHashMap<>(children); + dirty = false; + } + children.remove(id); + return this; + } + public StoreMetadataNode build() { checkState(data != null, "Data node should not be null."); checkState(subtreeVersion.compareTo(nodeVersion) >= 0, @@ -165,5 +194,4 @@ public class StoreMetadataNode implements Immutable, Identifiable, public static StoreMetadataNode createRecursively(final NormalizedNode node, final UnsignedLong version) { return createRecursively(node, version, version); } - } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreNodeCompositeBuilder.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreNodeCompositeBuilder.java index 41fc8239fb..a66a1d5b1c 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreNodeCompositeBuilder.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/StoreNodeCompositeBuilder.java @@ -10,7 +10,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; -import com.google.common.base.Optional; +import com.google.common.base.Preconditions; import com.google.common.primitives.UnsignedLong; /** @@ -28,7 +28,12 @@ public class StoreNodeCompositeBuilder { private StoreNodeCompositeBuilder(final NormalizedNodeContainerBuilder nodeBuilder) { this.metadata = StoreMetadataNode.builder(); - this.data = nodeBuilder; + this.data = Preconditions.checkNotNull(nodeBuilder); + } + + public StoreNodeCompositeBuilder(NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) { + this.metadata = StoreMetadataNode.builder(currentMeta); + this.data = Preconditions.checkNotNull(nodeBuilder); } @SuppressWarnings("unchecked") @@ -39,12 +44,9 @@ public class StoreNodeCompositeBuilder { } @SuppressWarnings("unchecked") - public StoreNodeCompositeBuilder addIfPresent(final Optional potential) { - if (potential.isPresent()) { - StoreMetadataNode node = potential.get(); - metadata.add(node); - data.addChild(node.getData()); - } + public StoreNodeCompositeBuilder remove(PathArgument id) { + metadata.remove(id); + data.removeChild(id); return this; } @@ -56,6 +58,10 @@ public class StoreNodeCompositeBuilder { return new StoreNodeCompositeBuilder(nodeBuilder); } + public static StoreNodeCompositeBuilder from(final NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) { + return new StoreNodeCompositeBuilder(nodeBuilder, currentMeta); + } + @SuppressWarnings("unchecked") public StoreNodeCompositeBuilder setIdentifier(final PathArgument identifier) { data.withNodeIdentifier(identifier); @@ -71,5 +77,4 @@ public class StoreNodeCompositeBuilder { metadata.setSubtreeVersion(updatedSubtreeVersion); return this; } - } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/TreeNodeUtils.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/TreeNodeUtils.java index 339d9cb44e..732352dd34 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/TreeNodeUtils.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/TreeNodeUtils.java @@ -21,7 +21,10 @@ import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.base.Predicates; -public class TreeNodeUtils { +public final class TreeNodeUtils { + private TreeNodeUtils() { + throw new UnsupportedOperationException("Utility class should not be instantiated"); + } /** * Finds a node in tree @@ -40,7 +43,6 @@ public class TreeNodeUtils { return current; } - public static > T findNodeChecked(final T tree, final InstanceIdentifier path) { T current = tree; List nested = new ArrayList<>(path.getPath().size()); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java index 3e7b115f11..f47e1efc3f 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java @@ -457,7 +457,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro try { listener.onRouteChange(initial); } catch (Exception e) { - LOG.error("Unhandled exception during sending initial route change event {} to {}",initial,listener); + LOG.error("Unhandled exception during sending initial route change event {} to {}",initial,listener, e); } return reg; } diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DataNormalizerTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DataNormalizerTest.java index 9aa558b5ac..ac7b87a9f5 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DataNormalizerTest.java +++ b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DataNormalizerTest.java @@ -49,12 +49,8 @@ public class DataNormalizerTest { InstanceIdentifier normalizedPath = normalizer.toNormalized(LEAF_TWO_PATH_LEGACY); - Node outerListLegacy = normalizer.toLegacy(OUTER_LIST_WITH_CHOICE); + Node outerListLegacy = DataNormalizer.toLegacy(OUTER_LIST_WITH_CHOICE); assertNotNull(outerListLegacy); - - - - } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java index 5a43c7b218..c0f0a35565 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java +++ b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java @@ -7,6 +7,7 @@ import static org.junit.Assert.assertTrue; import java.util.concurrent.ExecutionException; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction; import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction; @@ -119,6 +120,7 @@ public class InMemoryDataStoreTest { } @Test + @Ignore public void testTransactionConflict() throws InterruptedException, ExecutionException { DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction(); DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction(); diff --git a/opendaylight/md-sal/sal-netconf-connector/pom.xml b/opendaylight/md-sal/sal-netconf-connector/pom.xml index 27d320f03e..9ad95c18d9 100644 --- a/opendaylight/md-sal/sal-netconf-connector/pom.xml +++ b/opendaylight/md-sal/sal-netconf-connector/pom.xml @@ -13,10 +13,15 @@ + ${project.groupId} netconf-client ${netconf.version} + + ${project.groupId} + netconf-config-dispatcher + ${project.groupId} sal-common-util @@ -33,7 +38,6 @@ org.opendaylight.controller netconf-client - ${netconf.version} org.opendaylight.controller @@ -43,10 +47,18 @@ org.opendaylight.controller netty-threadgroup-config + + org.opendaylight.controller + sal-binding-api + org.opendaylight.controller threadpool-config-api + + org.opendaylight.controller.model + model-inventory + org.opendaylight.yangtools yang-data-impl diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java index ddaf6ea6c3..7bf8ee860d 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java @@ -9,33 +9,39 @@ package org.opendaylight.controller.config.yang.md.sal.connector.netconf; import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkCondition; import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkNotNull; -import io.netty.channel.EventLoopGroup; -import io.netty.util.concurrent.GlobalEventExecutor; +import com.google.common.net.InetAddresses; +import io.netty.util.HashedWheelTimer; +import io.netty.util.concurrent.GlobalEventExecutor; import java.io.File; import java.io.InputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; - import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; -import org.opendaylight.controller.netconf.client.NetconfSshClientDispatcher; -import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler; +import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; import org.opendaylight.controller.netconf.util.handler.ssh.authentication.LoginPassword; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; import org.opendaylight.controller.sal.connect.netconf.NetconfDevice; +import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceListener; import org.opendaylight.protocol.framework.ReconnectStrategy; import org.opendaylight.protocol.framework.TimedReconnectStrategy; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider; import org.opendaylight.yangtools.yang.model.util.repo.FilesystemSchemaCachingProvider; import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider; import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProviders; import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.net.InetAddresses; - /** * */ @@ -69,63 +75,45 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co checkNotNull(getBetweenAttemptsTimeoutMillis(), betweenAttemptsTimeoutMillisJmxAttribute); checkCondition(getBetweenAttemptsTimeoutMillis() > 0, "must be > 0", betweenAttemptsTimeoutMillisJmxAttribute); + // FIXME BUG-944 remove backwards compatibility + if(getClientDispatcher() == null) { + checkCondition(getBossThreadGroup() != null, "Client dispatcher was not set, thread groups have to be set instead", bossThreadGroupJmxAttribute); + checkCondition(getWorkerThreadGroup() != null, "Client dispatcher was not set, thread groups have to be set instead", workerThreadGroupJmxAttribute); + } + + // Check username + password in case of ssh + if(getTcpOnly() == false) { + checkNotNull(getUsername(), usernameJmxAttribute); + checkNotNull(getPassword(), passwordJmxAttribute); + } + } @Override public java.lang.AutoCloseable createInstance() { + ServiceReference serviceReference = bundleContext.getServiceReference(DataProviderService.class); + + DataProviderService dataProviderService = + bundleContext.getService(serviceReference); getDomRegistryDependency(); NetconfDevice device = new NetconfDevice(getIdentifier().getInstanceName()); - String addressValue = getAddress(); - - Long connectionAttempts; - if (getMaxConnectionAttempts() != null && getMaxConnectionAttempts() > 0) { - connectionAttempts = getMaxConnectionAttempts(); - } else { - logger.trace("Setting {} on {} to infinity", maxConnectionAttemptsJmxAttribute, this); - connectionAttempts = null; - } - long clientConnectionTimeoutMillis = getConnectionTimeoutMillis(); - /* - * Uncomment after Switch to IP Address - if(getAddress().getIpv4Address() != null) { - addressValue = getAddress().getIpv4Address().getValue(); - } else { - addressValue = getAddress().getIpv6Address().getValue(); - } - */ - double sleepFactor = 1.0; - int minSleep = 1000; - Long maxSleep = null; - Long deadline = null; - ReconnectStrategy strategy = new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, getBetweenAttemptsTimeoutMillis(), - minSleep, sleepFactor, maxSleep, connectionAttempts, deadline); - - device.setReconnectStrategy(strategy); - - InetAddress addr = InetAddresses.forString(addressValue); - InetSocketAddress socketAddress = new InetSocketAddress(addr , getPort().intValue()); + device.setClientConfig(getClientConfig(device)); device.setProcessingExecutor(getGlobalProcessingExecutor()); - device.setSocketAddress(socketAddress); device.setEventExecutor(getEventExecutorDependency()); - device.setDispatcher(createDispatcher(clientConnectionTimeoutMillis)); + device.setDispatcher(getClientDispatcher() == null ? createDispatcher() : getClientDispatcherDependency()); device.setSchemaSourceProvider(getGlobalNetconfSchemaProvider(bundleContext)); - + device.setDataProviderService(dataProviderService); getDomRegistryDependency().registerProvider(device, bundleContext); device.start(); return device; } private ExecutorService getGlobalProcessingExecutor() { - if(GLOBAL_PROCESSING_EXECUTOR == null) { - - GLOBAL_PROCESSING_EXECUTOR = Executors.newCachedThreadPool(); - - } - return GLOBAL_PROCESSING_EXECUTOR; + return GLOBAL_PROCESSING_EXECUTOR == null ? Executors.newCachedThreadPool() : GLOBAL_PROCESSING_EXECUTOR; } private synchronized AbstractCachingSchemaSourceProvider getGlobalNetconfSchemaProvider(BundleContext bundleContext) { @@ -139,18 +127,64 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co return GLOBAL_NETCONF_SOURCE_PROVIDER; } - private NetconfClientDispatcher createDispatcher(long clientConnectionTimeoutMillis) { - EventLoopGroup bossGroup = getBossThreadGroupDependency(); - EventLoopGroup workerGroup = getWorkerThreadGroupDependency(); - if(getTcpOnly()) { - return new NetconfClientDispatcher( bossGroup, workerGroup, clientConnectionTimeoutMillis); - } else { - AuthenticationHandler authHandler = new LoginPassword(getUsername(),getPassword()); - return new NetconfSshClientDispatcher(authHandler , bossGroup, workerGroup, clientConnectionTimeoutMillis); - } + // FIXME BUG-944 remove backwards compatibility + /** + * @deprecated Use getClientDispatcherDependency method instead to retrieve injected dispatcher. + * This one creates new instance of NetconfClientDispatcher and will be removed in near future. + */ + @Deprecated + private NetconfClientDispatcher createDispatcher() { + return new NetconfClientDispatcherImpl(getBossThreadGroupDependency(), getWorkerThreadGroupDependency(), new HashedWheelTimer()); } public void setBundleContext(BundleContext bundleContext) { this.bundleContext = bundleContext; } + + public NetconfClientConfiguration getClientConfig(final NetconfDevice device) { + InetSocketAddress socketAddress = getSocketAddress(); + ReconnectStrategy strategy = getReconnectStrategy(); + long clientConnectionTimeoutMillis = getConnectionTimeoutMillis(); + + return NetconfClientConfigurationBuilder.create() + .withAddress(socketAddress) + .withConnectionTimeoutMillis(clientConnectionTimeoutMillis) + .withReconnectStrategy(strategy) + .withSessionListener(new NetconfDeviceListener(device)) + .withAuthHandler(new LoginPassword(getUsername(),getPassword())) + .withProtocol(getTcpOnly() ? + NetconfClientConfiguration.NetconfClientProtocol.TCP : + NetconfClientConfiguration.NetconfClientProtocol.SSH) + .build(); + } + + private ReconnectStrategy getReconnectStrategy() { + Long connectionAttempts; + if (getMaxConnectionAttempts() != null && getMaxConnectionAttempts() > 0) { + connectionAttempts = getMaxConnectionAttempts(); + } else { + logger.trace("Setting {} on {} to infinity", maxConnectionAttemptsJmxAttribute, this); + connectionAttempts = null; + } + double sleepFactor = 1.0; + int minSleep = 1000; + Long maxSleep = null; + Long deadline = null; + + return new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, getBetweenAttemptsTimeoutMillis(), + minSleep, sleepFactor, maxSleep, connectionAttempts, deadline); + } + + private InetSocketAddress getSocketAddress() { + /* + * Uncomment after Switch to IP Address + if(getAddress().getIpv4Address() != null) { + addressValue = getAddress().getIpv4Address().getValue(); + } else { + addressValue = getAddress().getIpv6Address().getValue(); + } + */ + InetAddress inetAddress = InetAddresses.forString(getAddress()); + return new InetSocketAddress(inetAddress, getPort().intValue()); + } } diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java index 8d52950a29..54242cf26d 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java @@ -21,6 +21,7 @@ import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.toF import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.toRpcMessage; import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.wrap; +import com.google.common.base.Preconditions; import java.io.InputStream; import java.net.InetSocketAddress; import java.net.URI; @@ -38,6 +39,8 @@ import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler; import org.opendaylight.controller.md.sal.common.api.data.DataModification; import org.opendaylight.controller.md.sal.common.api.data.DataReader; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; import org.opendaylight.controller.sal.core.api.Provider; @@ -47,6 +50,8 @@ import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance; import org.opendaylight.controller.sal.core.api.mount.MountProvisionService; import org.opendaylight.protocol.framework.ReconnectStrategy; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode; import org.opendaylight.yangtools.concepts.Registration; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; @@ -115,12 +120,14 @@ public class NetconfDevice implements Provider, // SchemaSourceProvider remoteSourceProvider; - DataBrokerService dataBroker; + private volatile DataBrokerService dataBroker; NetconfDeviceListener listener; private boolean rollbackSupported; + private NetconfClientConfiguration clientConfig; + private volatile DataProviderService dataProviderService; public NetconfDevice(String name) { this.name = name; @@ -134,11 +141,12 @@ public class NetconfDevice implements Provider, // checkState(schemaSourceProvider != null, "Schema Source Provider must be set."); checkState(eventExecutor != null, "Event executor must be set."); - listener = new NetconfDeviceListener(this); + Preconditions.checkArgument(clientConfig.getSessionListener() instanceof NetconfDeviceListener); + listener = (NetconfDeviceListener) clientConfig.getSessionListener(); logger.info("Starting NETCONF Client {} for address {}", name, socketAddress); - dispatcher.createClient(socketAddress, listener, reconnectStrategy); + dispatcher.createClient(clientConfig); } Optional getSchemaContext() { @@ -213,6 +221,8 @@ public class NetconfDevice implements Provider, // } private void updateDeviceState(boolean up, Set capabilities) { + checkDataStoreState(); + DataModificationTransaction transaction = dataBroker.beginTransaction(); CompositeNodeBuilder it = ImmutableCompositeNode.builder(); @@ -222,7 +232,7 @@ public class NetconfDevice implements Provider, // logger.debug("Client capabilities {}", capabilities); for (QName capability : capabilities) { - it.addLeaf(NETCONF_INVENTORY_INITIAL_CAPABILITY, capability); + it.addLeaf(NETCONF_INVENTORY_INITIAL_CAPABILITY, capability.toString()); } logger.debug("Update device state transaction " + transaction.getIdentifier() @@ -289,7 +299,7 @@ public class NetconfDevice implements Provider, // @Override public ListenableFuture> invokeRpc(QName rpc, CompositeNode input) { - return listener.sendRequest(toRpcMessage(rpc, input, getSchemaContext())); + return listener.sendRequest(toRpcMessage(rpc, input, getSchemaContext()), rpc); } @Override @@ -301,6 +311,22 @@ public class NetconfDevice implements Provider, // public void onSessionInitiated(ProviderSession session) { dataBroker = session.getService(DataBrokerService.class); + processingExecutor.submit(new Runnable() { + @Override + public void run() { + updateInitialState(); + } + }); + + mountService = session.getService(MountProvisionService.class); + if (mountService != null) { + mountInstance = mountService.createOrGetMountPoint(path); + } + } + + private void updateInitialState() { + checkDataStoreState(); + DataModificationTransaction transaction = dataBroker.beginTransaction(); if (operationalNodeNotExisting(transaction)) { transaction.putOperationalData(path, getNodeWithId()); @@ -316,13 +342,13 @@ public class NetconfDevice implements Provider, // } catch (ExecutionException e) { throw new RuntimeException("Read configuration data " + path + " failed", e); } - - mountService = session.getService(MountProvisionService.class); - if (mountService != null) { - mountInstance = mountService.createOrGetMountPoint(path); - } } + private void checkDataStoreState() { + // read data from Nodes/Node in order to wait with write until schema for Nodes/Node is present in datastore + dataProviderService.readOperationalData(org.opendaylight.yangtools.yang.binding.InstanceIdentifier.builder( + Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class).augmentation(NetconfNode.class).build()); } + CompositeNode getNodeWithId() { SimpleNodeTOImpl id = new SimpleNodeTOImpl(INVENTORY_ID, null, name); return new CompositeNodeTOImpl(INVENTORY_NODE, null, Collections.> singletonList(id)); @@ -464,6 +490,14 @@ public class NetconfDevice implements Provider, // public void setDispatcher(final NetconfClientDispatcher dispatcher) { this.dispatcher = dispatcher; } + + public void setClientConfig(final NetconfClientConfiguration clientConfig) { + this.clientConfig = clientConfig; + } + + public void setDataProviderService(final DataProviderService dataProviderService) { + this.dataProviderService = dataProviderService; + } } class NetconfDeviceSchemaContextProvider { diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java index 94f5e166a1..68667f0143 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java @@ -25,6 +25,7 @@ import org.opendaylight.controller.netconf.client.NetconfClientSession; import org.opendaylight.controller.netconf.client.NetconfClientSessionListener; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.opendaylight.controller.sal.common.util.Rpcs; import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance; import org.opendaylight.yangtools.yang.common.QName; @@ -40,15 +41,16 @@ import com.google.common.base.Preconditions; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -class NetconfDeviceListener implements NetconfClientSessionListener { - +public class NetconfDeviceListener implements NetconfClientSessionListener { private static final class Request { final UncancellableFuture> future; final NetconfMessage request; + final QName rpc; - private Request(UncancellableFuture> future, NetconfMessage request) { + private Request(UncancellableFuture> future, NetconfMessage request, final QName rpc) { this.future = future; this.request = request; + this.rpc = rpc; } } @@ -163,14 +165,13 @@ class NetconfDeviceListener implements NetconfClientSessionListener { return; } - r.future.set(Rpcs.getRpcResult(true, NetconfMapping.toNotificationNode(message, device.getSchemaContext()), - Collections.emptyList())); + r.future.set(NetconfMapping.toRpcResult(message, r.rpc, device.getSchemaContext())); } else { LOG.warn("Ignoring unsolicited message", message); } } - synchronized ListenableFuture> sendRequest(final NetconfMessage message) { + synchronized ListenableFuture> sendRequest(final NetconfMessage message, final QName rpc) { if (session == null) { LOG.debug("Session to {} is disconnected, failing RPC request {}", device.getName(), message); return Futures.>immediateFuture(new RpcResult() { @@ -192,7 +193,7 @@ class NetconfDeviceListener implements NetconfClientSessionListener { }); } - final Request req = new Request(new UncancellableFuture>(true), message); + final Request req = new Request(new UncancellableFuture>(true), message, rpc); requests.add(req); session.sendMessage(req.request).addListener(new FutureListener() { @@ -200,7 +201,7 @@ class NetconfDeviceListener implements NetconfClientSessionListener { public void operationComplete(final Future future) throws Exception { if (!future.isSuccess()) { // We expect that a session down will occur at this point - LOG.debug("Failed to send request {}", req.request, future.cause()); + LOG.debug("Failed to send request {}", XmlUtil.toString(req.request.getDocument()), future.cause()); req.future.setException(future.cause()); } else { LOG.trace("Finished sending request {}", req.request); diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java index a6e6b3dfdf..f76ec28624 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java @@ -99,7 +99,11 @@ public class NetconfMapping { for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument component : Lists .reverse(identifier.getPath())) { - previous = toNode(component, previous); + if (component instanceof NodeIdentifierWithPredicates) { + previous = toNode((NodeIdentifierWithPredicates)component, previous); + } else { + previous = toNode(component, previous); + } } return filter("subtree", previous); } @@ -135,7 +139,7 @@ public class NetconfMapping { SchemaContext schemaContext = ctx.get(); Set notifications = schemaContext.getNotifications(); Document document = message.getDocument(); - return XmlDocumentUtils.notificationToDomNodes(document, Optional.fromNullable(notifications)); + return XmlDocumentUtils.notificationToDomNodes(document, Optional.fromNullable(notifications), ctx.get()); } return null; } @@ -192,13 +196,7 @@ public class NetconfMapping { rawRpc = it.toInstance(); // sys(xmlData) } else { - RpcDefinition rpcSchema = Iterables.find(context.get().getOperations(), new Predicate() { - @Override - public boolean apply(final RpcDefinition input) { - return rpc == input.getQName(); - } - }); - rawRpc = (CompositeNode) toCompositeNode(message.getDocument()); + rawRpc = (CompositeNode) toCompositeNode(message, context); } else { rawRpc = (CompositeNode) toCompositeNode(message.getDocument()); diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfRemoteSchemaSourceProvider.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfRemoteSchemaSourceProvider.java index c734e80d9a..31c6bd0138 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfRemoteSchemaSourceProvider.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfRemoteSchemaSourceProvider.java @@ -20,6 +20,8 @@ import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider { @@ -30,8 +32,11 @@ class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider private final NetconfDevice device; + private final Logger logger; + public NetconfRemoteSchemaSourceProvider(NetconfDevice device) { this.device = Preconditions.checkNotNull(device); + logger = LoggerFactory.getLogger(NetconfDevice.class + "#" + device.getName()); } @Override @@ -44,7 +49,7 @@ class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider request.addLeaf("version", revision.get()); } - device.logger.trace("Loading YANG schema source for {}:{}", moduleName, revision); + logger.trace("Loading YANG schema source for {}:{}", moduleName, revision); try { RpcResult schemaReply = device.invokeRpc(GET_SCHEMA_QNAME, request.toInstance()).get(); if (schemaReply.isSuccessful()) { @@ -54,9 +59,9 @@ class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider return Optional.of(schemaBody); } } - device.logger.warn("YANG shcema was not successfully retrieved."); + logger.warn("YANG shcema was not successfully retrieved. Errors: {}", schemaReply.getErrors()); } catch (InterruptedException | ExecutionException e) { - device.logger.warn("YANG shcema was not successfully retrieved.", e); + logger.warn("YANG shcema was not successfully retrieved.", e); } return Optional.absent(); } diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang b/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang index f0fa452dc5..d4dad11ec3 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang @@ -7,10 +7,11 @@ module odl-sal-netconf-connector-cfg { import threadpool {prefix th;} import netty {prefix netty;} import opendaylight-md-sal-dom {prefix dom;} + import odl-netconf-cfg { prefix cfg-net; revision-date 2014-04-08; } description "Service definition for Binding Aware MD-SAL."; - + revision "2013-10-28" { description "Initial revision"; @@ -26,7 +27,7 @@ module odl-sal-netconf-connector-cfg { leaf address { type string; } - + leaf port { type uint32; } @@ -36,7 +37,7 @@ module odl-sal-netconf-connector-cfg { augment "/config:modules/config:module/config:configuration" { case sal-netconf-connector { when "/config:modules/config:module/config:type = 'sal-netconf-connector'"; - + leaf address { type string; } @@ -44,7 +45,7 @@ module odl-sal-netconf-connector-cfg { leaf port { type uint32; } - + leaf tcp-only { type boolean; } @@ -52,10 +53,11 @@ module odl-sal-netconf-connector-cfg { leaf username { type string; } - + leaf password { type string; } + container dom-registry { uses config:service-ref { refine type { @@ -65,17 +67,25 @@ module odl-sal-netconf-connector-cfg { } } + // FIXME BUG-944 remove backwards compatibility + // Deprecated, replaced by client dispatcher. + // This dependency will be removed in near future and all configurations of netconf-connector need to be changed to use dispatcher dependency. container boss-thread-group { uses config:service-ref { refine type { + mandatory false; config:required-identity netty:netty-threadgroup; } } } + // FIXME BUG-944 remove backwards compatibility + // Deprecated, replaced by client dispatcher. + // This dependency will be removed in near future and all configurations of netconf-connector need to be changed to use dispatcher dependency. container worker-thread-group { uses config:service-ref { refine type { + mandatory false; config:required-identity netty:netty-threadgroup; } } @@ -89,6 +99,16 @@ module odl-sal-netconf-connector-cfg { } } + // Replaces thread group dependencies + container client-dispatcher { + uses config:service-ref { + refine type { + mandatory false; + config:required-identity cfg-net:netconf-client-dispatcher; + } + } + } + leaf connection-timeout-millis { description "Specifies timeout in milliseconds after which connection must be established."; type uint32; @@ -101,7 +121,6 @@ module odl-sal-netconf-connector-cfg { default 0; // retry forever } - leaf between-attempts-timeout-millis { description "Timeout in milliseconds to wait between connection attempts."; type uint16; diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java index edcef83574..53fbb929bb 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java @@ -8,7 +8,7 @@ package org.opendaylight.controller.sal.connector.remoterpc; -import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; import java.util.Collection; import java.util.Collections; @@ -174,7 +174,7 @@ public class RemoteRpcProvider implements Optional> routingTable = routingTableProvider.getRoutingTable(); - checkNotNull(routingTable.isPresent(), "Routing table is null"); + checkState(routingTable.isPresent(), "Routing table is null"); return routingTable.get(); } diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java index 519791a195..21d02be7d7 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/Message.java @@ -8,11 +8,17 @@ package org.opendaylight.controller.sal.connector.remoterpc.dto; -import org.opendaylight.controller.sal.connector.api.RpcRouter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; -import java.io.*; +import org.opendaylight.controller.sal.connector.api.RpcRouter; public class Message implements Serializable { + private static final long serialVersionUID = 1L; public static enum MessageType { PING((byte) 0), @@ -118,12 +124,13 @@ public class Message implements Serializable { } public static class Response extends Message implements RpcRouter.RpcReply { + private static final long serialVersionUID = 1L; private ResponseCode code; // response code public static enum ResponseCode { SUCCESS(200), BADREQUEST(400), TIMEOUT(408), GONE(410), SERVERERROR(500), SERVICEUNAVAILABLE(503); - private int code; + private final int code; ResponseCode(int code) { this.code = code; @@ -144,7 +151,7 @@ public class Message implements Serializable { */ public static class MessageBuilder{ - private Message message; + private final Message message; public MessageBuilder(){ message = new Message(); diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java index 4ffcf3e099..53c7cc0b8d 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/dto/RouteIdentifierImpl.java @@ -7,13 +7,14 @@ */ package org.opendaylight.controller.sal.connector.remoterpc.dto; +import java.io.Serializable; + import org.opendaylight.controller.sal.connector.api.RpcRouter; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; -import java.io.Serializable; - public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier,Serializable { + private static final long serialVersionUID = 1L; private QName context; private QName type; diff --git a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandlerTest.java b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandlerTest.java index a5c4d85fed..1edd004d37 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandlerTest.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientRequestHandlerTest.java @@ -7,7 +7,14 @@ */ package org.opendaylight.controller.sal.connector.remoterpc; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + import junit.framework.Assert; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -17,9 +24,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeromq.ZMQ; -import java.io.IOException; -import java.util.concurrent.*; - /** * */ @@ -69,7 +73,7 @@ public class ClientRequestHandlerTest { serverThread.execute(MessagingUtil.startReplyServer(context, serverAddress, 1)); threadPool.execute(createEmptyMessageTaskAndHandle(handler, serverAddress)); } - Thread.currentThread().sleep(5000);//wait for all messages to get processed + Thread.sleep(5000);//wait for all messages to get processed //should be connected to 5 remote server Assert.assertEquals(5, handler.getWorkerCount()); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java index e19f9f5805..4d9958ee6b 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java @@ -122,7 +122,7 @@ class JsonReader { // it could be identityref Built-In Type URI namespace = getNamespaceFor(value); if (namespace != null) { - return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null); + return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null,value); } // it is not "prefix:value" but just "value" return value; diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestUtil.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestUtil.java index 225eb7de6a..ba3e315e72 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestUtil.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestUtil.java @@ -42,7 +42,7 @@ public final class RestUtil { if (xPathParts.length < 2) { // must be at least "/pr:node" return null; } - IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO(); + IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO(value); for (int i = 1; i < xPathParts.length; i++) { String xPathPartTrimmed = xPathParts[i].trim(); diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java index d807070dbd..a75f6b4a85 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java @@ -205,7 +205,7 @@ public class XmlReader { if (namespaceAndValue.length == 2) { String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]); if (namespace != null && !namespace.isEmpty()) { - return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0]); + return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0],value); } } // it is not "prefix:value" but just "value" diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/IdentityValuesDTO.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/IdentityValuesDTO.java index 4fb75141d5..14a558967d 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/IdentityValuesDTO.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/IdentityValuesDTO.java @@ -14,13 +14,19 @@ import java.util.List; public final class IdentityValuesDTO { private final List elementData = new ArrayList<>(); + private final String originValue; - public IdentityValuesDTO(String namespace, String value, String prefix) { + public IdentityValuesDTO(String namespace, String value, String prefix,String originValue) { elementData.add(new IdentityValue(namespace, value, prefix)); + this.originValue = originValue; + } + + public IdentityValuesDTO(String originValue) { + this.originValue = originValue; } public IdentityValuesDTO() { - + originValue = null; } public void add(String namespace, String value, String prefix) { @@ -40,6 +46,10 @@ public final class IdentityValuesDTO { public String toString() { return elementData.toString(); } + + public String getOriginValue() { + return originValue; + } public static final class IdentityValue { diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java index d6b530039e..42658d79f1 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java @@ -89,6 +89,9 @@ public class RestCodec { input == null ? "null" : input.getClass(), String.valueOf(input)); return null; } else if (type instanceof LeafrefTypeDefinition) { + if (input instanceof IdentityValuesDTO) { + return LEAFREF_DEFAULT_CODEC.deserialize(((IdentityValuesDTO)input).getOriginValue()); + } return LEAFREF_DEFAULT_CODEC.deserialize(input); } else if (type instanceof InstanceIdentifierTypeDefinition) { if (input instanceof IdentityValuesDTO) { @@ -102,6 +105,9 @@ public class RestCodec { TypeDefinitionAwareCodec> typeAwarecodec = TypeDefinitionAwareCodec .from(type); if (typeAwarecodec != null) { + if (input instanceof IdentityValuesDTO) { + return typeAwarecodec.deserialize(((IdentityValuesDTO)input).getOriginValue()); + } return typeAwarecodec.deserialize(String.valueOf(input)); } else { logger.debug("Codec for type \"" + type.getQName().getLocalName() @@ -162,7 +168,7 @@ public class RestCodec { @Override public IdentityValuesDTO serialize(QName data) { - return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix()); + return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix(),null); } @Override diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend index fa478ac72e..f1901d7112 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend @@ -588,7 +588,11 @@ class RestconfImpl implements RestconfService { } if (node instanceof CompositeNodeWrapper) { if ((node as CompositeNodeWrapper).changeAllowed) { - normalizeNode(node as CompositeNodeWrapper, schema, null, mountPoint) + try { + normalizeNode(node as CompositeNodeWrapper, schema, null, mountPoint) + } catch (NumberFormatException e) { + throw new ResponseException(BAD_REQUEST,e.message) + } } return (node as CompositeNodeWrapper).unwrap() } @@ -669,7 +673,7 @@ class RestconfImpl implements RestconfService { if (schema.typeDefinition instanceof IdentityrefTypeDefinition) { if (value instanceof String) { - inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null) + inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null,value as String); } // else value is already instance of IdentityValuesDTO } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/CodecsExceptionsCatchingTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/CodecsExceptionsCatchingTest.java new file mode 100644 index 0000000000..767aaf36c1 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/CodecsExceptionsCatchingTest.java @@ -0,0 +1,59 @@ +package org.opendaylight.controller.sal.restconf.impl.test; + +import static org.junit.Assert.assertTrue; + +import java.io.FileNotFoundException; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider; +import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider; +import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider; +import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider; +import org.opendaylight.controller.sal.restconf.impl.ControllerContext; +import org.opendaylight.controller.sal.restconf.impl.RestconfImpl; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +public class CodecsExceptionsCatchingTest extends JerseyTest { + + private static RestconfImpl restConf; + private static ControllerContext controllerContext = ControllerContext.getInstance(); + + @BeforeClass + public static void init() throws FileNotFoundException { + restConf = RestconfImpl.getInstance(); + controllerContext = ControllerContext.getInstance(); + SchemaContext schemaContext = TestUtils.loadSchemaContext("/decoding-exception/yang"); + controllerContext.setGlobalSchema(schemaContext); + restConf.setControllerContext(controllerContext); + } + + @Override + protected Application configure() { + /* enable/disable Jersey logs to console */ + // enable(TestProperties.LOG_TRAFFIC); + // enable(TestProperties.DUMP_ENTITY); + // enable(TestProperties.RECORD_LOG_LEVEL); + // set(TestProperties.RECORD_LOG_LEVEL, Level.ALL.intValue()); + ResourceConfig resourceConfig = new ResourceConfig(); + resourceConfig = resourceConfig.registerInstances(restConf, StructuredDataToXmlProvider.INSTANCE, + StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE, + JsonToCompositeNodeProvider.INSTANCE); + return resourceConfig; + } + + @Test + public void StringToNumberConversionError() { + Response response = target("/config/number:cont").request(MediaType.APPLICATION_XML).put( + Entity.entity("3f", MediaType.APPLICATION_XML)); + String exceptionMessage = response.readEntity(String.class); + assertTrue(exceptionMessage.contains("Incorrect lexical representation of Integer value: 3f")); + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlAndJsonToCnSnLeafRefTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlAndJsonToCnSnLeafRefTest.java new file mode 100644 index 0000000000..e5a737e6d5 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlAndJsonToCnSnLeafRefTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.restconf.impl.test; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.net.URISyntaxException; + +import javax.ws.rs.WebApplicationException; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider; +import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.Node; +import org.opendaylight.yangtools.yang.data.api.SimpleNode; + +public class XmlAndJsonToCnSnLeafRefTest extends YangAndXmlAndDataSchemaLoader { + + @BeforeClass + public static void initialize() { + dataLoad("/leafref/yang", 2, "leafref-module", "cont"); + } + + @Test + public void loadXmlToCnSn() throws WebApplicationException, IOException, URISyntaxException { + CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/xml/xmldata.xml", XmlToCompositeNodeProvider.INSTANCE); + TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath); + verifyContPredicate(cnSn, "/ns:cont/ns:lf1", "/cont/lf1", "/ns:cont/ns:lf1", "../lf1"); + } + + @Test + public void loadJsonToCnSn() throws WebApplicationException, IOException, URISyntaxException { + CompositeNode cnSn = TestUtils.readInputToCnSn("/leafref/json/jsondata.json", + JsonToCompositeNodeProvider.INSTANCE); + TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath); + verifyContPredicate(cnSn, "/leafref-module:cont/leafref-module:lf1", "/leafref-module:cont/leafref-module:lf1", + "/referenced-module:cont/referenced-module:lf1", "/leafref-module:cont/leafref-module:lf1"); + } + + private void verifyContPredicate(CompositeNode cnSn, String... values) throws URISyntaxException { + Object lf2Value = null; + Object lf3Value = null; + Object lf4Value = null; + Object lf5Value = null; + + for (Node node : cnSn.getValue()) { + if (node.getNodeType().getLocalName().equals("lf2")) { + lf2Value = ((SimpleNode) node).getValue(); + } else if (node.getNodeType().getLocalName().equals("lf3")) { + lf3Value = ((SimpleNode) node).getValue(); + } else if (node.getNodeType().getLocalName().equals("lf4")) { + lf4Value = ((SimpleNode) node).getValue(); + } else if (node.getNodeType().getLocalName().equals("lf5")) { + lf5Value = ((SimpleNode) node).getValue(); + } + } + assertEquals(values[0], lf2Value); + assertEquals(values[1], lf3Value); + assertEquals(values[2], lf4Value); + assertEquals(values[3], lf5Value); + } + +} diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/decoding-exception/yang/number.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/decoding-exception/yang/number.yang new file mode 100644 index 0000000000..c4638827ef --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/decoding-exception/yang/number.yang @@ -0,0 +1,17 @@ + module number { + + namespace "number"; + prefix "number"; + + revision 2014-04-24 { + } + + + + container cont { + leaf lf { + type uint8; + } + + } + } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/json/jsondata.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/json/jsondata.json new file mode 100644 index 0000000000..cbe455b33b --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/json/jsondata.json @@ -0,0 +1,8 @@ +{ + "leafref-module:cont" : { + "lf4" : "/referenced-module:cont/referenced-module:lf1", + "lf2" : "/leafref-module:cont/leafref-module:lf1", + "lf3" : "/leafref-module:cont/leafref-module:lf1", + "lf5" : "/leafref-module:cont/leafref-module:lf1" + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/xml/xmldata.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/xml/xmldata.xml new file mode 100644 index 0000000000..01bf092d27 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/xml/xmldata.xml @@ -0,0 +1,6 @@ + + /ns:cont/ns:lf1 + /ns:cont/ns:lf1 + /cont/lf1 + ../lf1 + diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/leafref-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/leafref-module.yang new file mode 100644 index 0000000000..00df290691 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/leafref-module.yang @@ -0,0 +1,44 @@ +module leafref-module { + namespace "leafref:module"; + + + prefix "lfrfmodule"; + + import referenced-module { prefix refmod; revision-date 2014-04-17;} + + + revision 2014-04-17 { + } + + + container cont { + leaf lf1 { + type instance-identifier; + } + + leaf lf2 { + type leafref { + path "../lf1"; + } + } + + leaf lf3 { + type leafref { + path "/refmod:cont/refmod:lf1"; + } + } + + leaf lf4 { + type leafref { + path "/cont/lf1"; + } + } + + leaf lf5 { + type leafref { + path "../lf1"; + } + } + + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/referenced-module.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/referenced-module.yang new file mode 100644 index 0000000000..b6de719e4d --- /dev/null +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/leafref/yang/referenced-module.yang @@ -0,0 +1,13 @@ +module referenced-module { + namespace "referenced:module"; + + prefix "refmodule"; + revision 2014-04-17 { + } + + container cont { + leaf lf1 { + type instance-identifier; + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-rest-docgen/pom.xml b/opendaylight/md-sal/sal-rest-docgen/pom.xml new file mode 100644 index 0000000000..423d2e48ce --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/pom.xml @@ -0,0 +1,113 @@ + + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.1-SNAPSHOT + + + org.opendaylight.controller + sal-rest-docgen + bundle + + + 3.0.4.Final + + + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.datatype + jackson-datatype-json-org + + + + com.google.guava + guava + + + + + org.jboss.resteasy + jaxrs-api + ${jaxrs-api.version} + + + + org.json + json + + + + org.opendaylight.controller + sal-core-api + + + org.opendaylight.yangtools + yang-common + + + + org.opendaylight.yangtools + yang-model-api + + + org.opendaylight.yangtools + yang-model-util + + + org.opendaylight.yangtools + yang-parser-api + + + + org.opendaylight.yangtools + yang-parser-impl + + + + org.osgi + org.osgi.core + + + + org.slf4j + slf4j-api + + + junit + junit + test + + + + + + + org.apache.felix + maven-bundle-plugin + 2.4.0 + true + + + + MD SAL Rest Api Doc Generator + *, + com.sun.jersey.spi.container.servlet + org.opendaylight.controller.sal.rest.doc.DocProvider + /apidoc + + + + + + + diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/DocProvider.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/DocProvider.java new file mode 100644 index 0000000000..9c180014d7 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/DocProvider.java @@ -0,0 +1,93 @@ +/* + * 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.rest.doc; + +import org.opendaylight.controller.sal.core.api.Broker; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.controller.sal.rest.doc.impl.ApiDocGenerator; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Collections; + + +public class DocProvider implements BundleActivator, + ServiceTrackerCustomizer, + Provider, + AutoCloseable { + + private Logger _logger = LoggerFactory.getLogger(DocProvider.class); + + private ServiceTracker brokerServiceTracker; + private BundleContext bundleContext; + private Broker.ProviderSession session; + + @Override + public void close() throws Exception { + stop(bundleContext); + } + + @Override + public void onSessionInitiated(Broker.ProviderSession providerSession) { + SchemaService schemaService = providerSession.getService(SchemaService.class); + ApiDocGenerator.getInstance().setSchemaService(schemaService); + + _logger.debug("Restconf API Explorer started"); + + } + + @Override + public Collection getProviderFunctionality() { + return Collections.emptySet(); + } + + @Override + public void start(BundleContext context) throws Exception { + bundleContext = context; + brokerServiceTracker = new ServiceTracker(context, Broker.class, this); + brokerServiceTracker.open(); + } + + @Override + public void stop(BundleContext context) throws Exception { + if (brokerServiceTracker != null) + brokerServiceTracker.close(); + + if (session != null) + session.close(); + } + + @Override + public Broker addingService(ServiceReference reference) { + Broker broker = bundleContext.getService(reference); + session = broker.registerProvider(this, bundleContext); + return broker; + } + + @Override + public void modifiedService(ServiceReference reference, Broker service) { + if (session != null) + session.close(); + + Broker broker = bundleContext.getService(reference); + session = broker.registerProvider(this, bundleContext); + } + + @Override + public void removedService(ServiceReference reference, Broker service) { + bundleContext.ungetService(reference); + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/api/ApiDocService.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/api/ApiDocService.java new file mode 100644 index 0000000000..3542d6aadc --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/api/ApiDocService.java @@ -0,0 +1,62 @@ +/* + * 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.rest.doc.api; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * This service generates swagger + * (See https://helloreverb.com/developers/swagger) + * compliant documentation for RESTCONF APIs. The output of this is used by embedded Swagger UI. + */ +@Path("/") +public interface ApiDocService { + + /** + * Generates index document for Swagger UI. This document lists out all modules with link to get APIs for + * each module. The API for each module is served by getDocByModule() method. + * + * @param uriInfo + * @return + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getRootDoc(@Context javax.ws.rs.core.UriInfo uriInfo); + + /** + * Generates Swagger compliant document listing APIs for module. + * + * @param module + * @param revision + * @param uriInfo + * @return + */ + @GET + @Path("/{module},{revision}") + @Produces(MediaType.APPLICATION_JSON) + public Response getDocByModule(@PathParam("module") String module, + @PathParam("revision") String revision, + @Context javax.ws.rs.core.UriInfo uriInfo); + + /** + * Redirects to embedded swagger ui. + * + * @param uriInfo + * @return + */ + @GET + @Path("/ui") + @Produces(MediaType.TEXT_HTML) + public Response getApiExplorer(@Context javax.ws.rs.core.UriInfo uriInfo); +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGenerator.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGenerator.java new file mode 100644 index 0000000000..3662090b87 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGenerator.java @@ -0,0 +1,306 @@ +/* + * 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.rest.doc.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule; +import com.google.common.base.Preconditions; +import org.json.JSONException; +import org.json.JSONObject; +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.controller.sal.rest.doc.model.builder.OperationBuilder; +import org.opendaylight.controller.sal.rest.doc.swagger.*; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.core.UriInfo; +import java.io.IOException; +import java.net.URI; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * This class gathers all yang defined {@link Module}s and generates Swagger compliant documentation. + */ +public class ApiDocGenerator { + + private static Logger _logger = LoggerFactory.getLogger(ApiDocGenerator.class); + + private static final ApiDocGenerator INSTANCE = new ApiDocGenerator(); + private ObjectMapper mapper = new ObjectMapper(); + private final ModelGenerator jsonConverter = new ModelGenerator(); + + private SchemaService schemaService; + + private final String API_VERSION = "1.0.0"; + private final String SWAGGER_VERSION = "1.2"; + private final String RESTCONF_CONTEXT_ROOT = "restconf"; + private final DateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); + + //For now its {@link HashMap}. It will be changed to thread-safe Map when schema change listener is implemented. + private final Map MODULE_DOC_CACHE = new HashMap(); + + private ApiDocGenerator(){ + mapper.registerModule(new JsonOrgModule()); + mapper.configure(SerializationFeature.INDENT_OUTPUT, true); + } + + /** + * Returns singleton instance + * @return + */ + public static ApiDocGenerator getInstance() { + return INSTANCE; + } + + /** + * + * @param schemaService + */ + public void setSchemaService(SchemaService schemaService) { + this.schemaService = schemaService; + } + /** + * + * @param uriInfo + * @return list of modules converted to swagger compliant resource list. + */ + public ResourceList getResourceListing(UriInfo uriInfo) { + + Preconditions.checkState(schemaService != null); + SchemaContext schemaContext = schemaService.getGlobalContext(); + Preconditions.checkState(schemaContext != null); + + Set modules = schemaContext.getModules(); + + ResourceList resourceList = new ResourceList(); + resourceList.setApiVersion(API_VERSION); + resourceList.setSwaggerVersion(SWAGGER_VERSION); + + List resources = new ArrayList<>(modules.size()); + _logger.info("Modules found [{}]", modules.size()); + + for (Module module : modules) { + Resource resource = new Resource(); + String revisionString = SIMPLE_DATE_FORMAT.format(module.getRevision()); + + _logger.debug("Working on [{},{}]...", module.getName(), revisionString); + ApiDeclaration doc = getApiDeclaration(module.getName(), revisionString, uriInfo); + + if (doc != null) { + URI uri = uriInfo.getRequestUriBuilder(). + path(generateCacheKey(module.getName(), revisionString)). + build(); + + resource.setPath(uri.toASCIIString()); + resources.add(resource); + } else { + _logger.debug("Could not generate doc for {},{}", module.getName(), revisionString); + } + } + + resourceList.setApis(resources); + + return resourceList; + } + + public ApiDeclaration getApiDeclaration(String module, String revision, UriInfo uriInfo) { + + //Lookup cache + String cacheKey = generateCacheKey(module, revision); + + if (MODULE_DOC_CACHE.containsKey(cacheKey)) { + _logger.debug("Serving from cache for {}", cacheKey); + return MODULE_DOC_CACHE.get(cacheKey); + } + + Date rev = null; + try { + rev = SIMPLE_DATE_FORMAT.parse(revision); + } catch (ParseException e) { + throw new IllegalArgumentException(e); + } + + SchemaContext schemaContext = schemaService.getGlobalContext(); + Preconditions.checkState(schemaContext != null); + + Module m = schemaContext.findModuleByName(module, rev); + Preconditions.checkArgument(m != null, "Could not find module by name,revision: " + module + "," + revision); + + String basePath = new StringBuilder(uriInfo.getBaseUri().getScheme()) + .append("://") + .append(uriInfo.getBaseUri().getHost()) + .append(":") + .append(uriInfo.getBaseUri().getPort()) + .append("/") + .append(RESTCONF_CONTEXT_ROOT) + .toString(); + + ApiDeclaration doc = getSwaggerDocSpec(m, basePath); + MODULE_DOC_CACHE.put(cacheKey, doc); + return doc; + } + + public ApiDeclaration getSwaggerDocSpec(Module m, String basePath) { + ApiDeclaration doc = new ApiDeclaration(); + doc.setApiVersion(API_VERSION); + doc.setSwaggerVersion(SWAGGER_VERSION); + doc.setBasePath(basePath); + doc.setProduces(Arrays.asList("application/json", "application/xml")); + + List apis = new ArrayList(); + + Set dataSchemaNodes = m.getChildNodes(); + _logger.debug("child nodes size [{}]", dataSchemaNodes.size()); + for (DataSchemaNode node : dataSchemaNodes) { + if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) { + + _logger.debug("Is Configuration node [{}] [{}]", node.isConfiguration(), node.getQName().getLocalName()); + + List pathParams = null; + if (node.isConfiguration()) { + pathParams = new ArrayList(); + String resourcePath = "/config/" + m.getName() + ":"; + addApis(node, apis, resourcePath, pathParams, true); + + } + + pathParams = new ArrayList(); + String resourcePath = "/operational/" + m.getName() + ":"; + addApis(node, apis, resourcePath, pathParams, false); + } + } + + Set rpcs = m.getRpcs(); + for (RpcDefinition rpcDefinition : rpcs) { + String resourcePath = "/operations/" + m.getName() + ":"; + addRpcs(rpcDefinition, apis, resourcePath); + + } + _logger.debug("Number of APIs found [{}]", apis.size()); + doc.setApis(apis); + JSONObject models = null; + + try { + models = jsonConverter.convertToJsonSchema(m); + doc.setModels(models); + _logger.debug(mapper.writeValueAsString(doc)); + } catch (IOException | JSONException e) { + e.printStackTrace(); + } + + return doc; + } + + private String generateCacheKey(Module m) { + return generateCacheKey(m.getName(), SIMPLE_DATE_FORMAT.format(m.getRevision())); + } + + private String generateCacheKey(String module, String revision) { + return module + "," + revision; + } + + private void addApis(DataSchemaNode node, + List apis, + String parentPath, + List parentPathParams, + boolean addConfigApi) { + + Api api = new Api(); + List pathParams = new ArrayList(parentPathParams); + + String resourcePath = parentPath + createPath(node, pathParams) + "/"; + _logger.debug("Adding path: [{}]", resourcePath); + api.setPath(resourcePath); + api.setOperations(operations(node, pathParams, addConfigApi)); + apis.add(api); + if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) { + DataNodeContainer schemaNode = (DataNodeContainer) node; + Set dataSchemaNodes = schemaNode.getChildNodes(); + + for (DataSchemaNode childNode : dataSchemaNodes) { + addApis(childNode, apis, resourcePath, pathParams, addConfigApi); + } + } + + } + + private void addRpcs(RpcDefinition rpcDefn, List apis, String parentPath) { + Api rpc = new Api(); + String resourcePath = parentPath + rpcDefn.getQName().getLocalName(); + rpc.setPath(resourcePath); + + Operation operationSpec = new Operation(); + operationSpec.setMethod("POST"); + operationSpec.setNotes(rpcDefn.getDescription()); + operationSpec.setNickname(rpcDefn.getQName().getLocalName()); + rpc.setOperations(Arrays.asList(operationSpec)); + + apis.add(rpc); + } + + /** + * @param node + * @param pathParams + * @return + */ + private List operations(DataSchemaNode node, List pathParams, boolean isConfig) { + List operations = new ArrayList<>(); + + OperationBuilder.Get getBuilder = new OperationBuilder.Get(node); + operations.add(getBuilder.pathParams(pathParams).build()); + + if (isConfig) { + OperationBuilder.Post postBuilder = new OperationBuilder.Post(node); + operations.add(postBuilder.pathParams(pathParams).build()); + + OperationBuilder.Put putBuilder = new OperationBuilder.Put(node); + operations.add(putBuilder.pathParams(pathParams).build()); + + OperationBuilder.Delete deleteBuilder = new OperationBuilder.Delete(node); + operations.add(deleteBuilder.pathParams(pathParams).build()); + } + return operations; + } + + private String createPath(final DataSchemaNode schemaNode, List pathParams) { + ArrayList pathListParams = new ArrayList(); + StringBuilder path = new StringBuilder(); + QName _qName = schemaNode.getQName(); + String localName = _qName.getLocalName(); + path.append(localName); + + if ((schemaNode instanceof ListSchemaNode)) { + final List listKeys = ((ListSchemaNode) schemaNode).getKeyDefinition(); + for (final QName listKey : listKeys) { + { + DataSchemaNode _dataChildByName = ((DataNodeContainer) schemaNode).getDataChildByName(listKey); + pathListParams.add(((LeafSchemaNode) _dataChildByName)); + + String pathParamIdentifier = new StringBuilder("/{").append(listKey.getLocalName()).append("}").toString(); + path.append(pathParamIdentifier); + + Parameter pathParam = new Parameter(); + pathParam.setName(listKey.getLocalName()); + pathParam.setDescription(_dataChildByName.getDescription()); + pathParam.setType("string"); + pathParam.setParamType("path"); + + pathParams.add(pathParam); + } + } + } + return path.toString(); + } + +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocServiceImpl.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocServiceImpl.java new file mode 100644 index 0000000000..241c8b84be --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocServiceImpl.java @@ -0,0 +1,72 @@ +/* + * 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.rest.doc.impl; + +import org.opendaylight.controller.sal.rest.doc.api.ApiDocService; +import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration; +import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +/** + * This service generates swagger + * (See https://helloreverb.com/developers/swagger) + * compliant documentation for RESTCONF APIs. The output of this is used by embedded Swagger UI. + */ +public class ApiDocServiceImpl implements ApiDocService { + + private static final ApiDocService INSTANCE = new ApiDocServiceImpl(); + + public static ApiDocService getInstance(){ + return INSTANCE; + } + + /** + * Generates index document for Swagger UI. This document lists out all modules with link to get APIs for + * each module. The API for each module is served by getDocByModule() method. + * + * @param uriInfo + * @return + */ + @Override + public Response getRootDoc(UriInfo uriInfo) { + + ApiDocGenerator generator = ApiDocGenerator.getInstance(); + ResourceList rootDoc = generator.getResourceListing(uriInfo); + + return Response.ok(rootDoc).build(); + } + + /** + * Generates Swagger compliant document listing APIs for module. + * + * @param module + * @param revision + * @param uriInfo + * @return + */ + @Override + public Response getDocByModule(String module, String revision, UriInfo uriInfo) { + ApiDocGenerator generator = ApiDocGenerator.getInstance(); + + ApiDeclaration doc = generator.getApiDeclaration(module, revision, uriInfo); + return Response.ok(doc).build(); + } + + /** + * Redirects to embedded swagger ui. + * + * @param uriInfo + * @return + */ + @Override + public Response getApiExplorer(UriInfo uriInfo) { + return Response.seeOther(uriInfo.getBaseUriBuilder().path("../explorer/index.html").build()).build(); + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ModelGenerator.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ModelGenerator.java new file mode 100644 index 0000000000..597051ed30 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ModelGenerator.java @@ -0,0 +1,498 @@ +/* + * 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.rest.doc.impl; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.opendaylight.yangtools.yang.model.api.*; +import org.opendaylight.yangtools.yang.model.api.type.*; +import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit; +import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair; +import org.opendaylight.yangtools.yang.model.util.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.*; + +/** + * Generates JSON Schema for data defined in Yang + */ +public class ModelGenerator { + + private static Logger _logger = LoggerFactory.getLogger(ModelGenerator.class); + + private static final String BASE_64 = "base64"; + private static final String BINARY_ENCODING_KEY = "binaryEncoding"; + private static final String MEDIA_KEY = "media"; + private static final String ONE_OF_KEY = "oneOf"; + private static final String UNIQUE_ITEMS_KEY = "uniqueItems"; + private static final String MAX_ITEMS = "maxItems"; + private static final String MIN_ITEMS = "minItems"; + private static final String SCHEMA_URL = "http://json-schema.org/draft-04/schema"; + private static final String SCHEMA_KEY = "$schema"; + private static final String MAX_LENGTH_KEY = "maxLength"; + private static final String MIN_LENGTH_KEY = "minLength"; + private static final String REQUIRED_KEY = "required"; + private static final String REF_KEY = "$ref"; + private static final String ITEMS_KEY = "items"; + private static final String TYPE_KEY = "type"; + private static final String PROPERTIES_KEY = "properties"; + private static final String DESCRIPTION_KEY = "description"; + private static final String OBJECT_TYPE = "object"; + private static final String ARRAY_TYPE = "array"; + private static final String ENUM = "enum"; + private static final String INTEGER = "integer"; + private static final String NUMBER = "number"; + private static final String BOOLEAN = "boolean"; + private static final String STRING = "string"; + + private static final Map>, String> YANG_TYPE_TO_JSON_TYPE_MAPPING; + + static { + Map>, String> tempMap1 = new HashMap>, String>(10); + tempMap1.put(StringType.class , STRING); + tempMap1.put(BooleanType.class , BOOLEAN); + tempMap1.put(Int8.class , INTEGER); + tempMap1.put(Int16.class , INTEGER); + tempMap1.put(Int32.class , INTEGER); + tempMap1.put(Int64.class , INTEGER); + tempMap1.put(Uint16.class , INTEGER); + tempMap1.put(Uint32.class , INTEGER); + tempMap1.put(Uint64.class , INTEGER); + tempMap1.put(Uint8.class , INTEGER); + tempMap1.put(Decimal64.class , NUMBER); + tempMap1.put(EnumerationType.class , ENUM); + //TODO: Binary type + + YANG_TYPE_TO_JSON_TYPE_MAPPING = Collections.unmodifiableMap(tempMap1); + } + + public ModelGenerator(){ + } + + public JSONObject convertToJsonSchema(Module module) throws IOException, JSONException { + JSONObject models = new JSONObject(); + processContainers(module, models); + processRPCs(module, models); + + return models; + } + + + + private void processContainers(Module module, JSONObject models) throws IOException, JSONException { + + String moduleName = module.getName(); + Set childNodes = module.getChildNodes(); + + for(DataSchemaNode childNode : childNodes){ + JSONObject moduleJSON=null; + String filename = childNode.getQName().getLocalName(); + /* + * For every container in the module + */ + if(childNode instanceof ContainerSchemaNode) { + moduleJSON = processContainer((ContainerSchemaNode)childNode, moduleName, true, models); + } + + if(moduleJSON!=null) { + _logger.debug("Adding model for [{}]", filename); + moduleJSON.put("id", filename); + models.put(filename, moduleJSON); + } + } + + } + + + /** + * Process the RPCs for a Module + * Spits out a file each of the name -input.json + * and -output.json for each RPC that contains + * input & output elements + * + * @param module + * @throws JSONException + * @throws IOException + */ + private void processRPCs(Module module, JSONObject models) throws JSONException, IOException { + + Set rpcs = module.getRpcs(); + String moduleName = module.getName(); + for(RpcDefinition rpc: rpcs) { + + ContainerSchemaNode input = rpc.getInput(); + if(input!=null) { + JSONObject inputJSON = processContainer(input, moduleName, true, models); + String filename = rpc.getQName().getLocalName() + "-input"; + inputJSON.put("id", filename); + //writeToFile(filename, inputJSON.toString(2), moduleName); + models.put(filename, inputJSON); + } + + ContainerSchemaNode output = rpc.getOutput(); + if(output!=null) { + JSONObject outputJSON = processContainer(output, moduleName, true, models); + String filename = rpc.getQName().getLocalName() + "-output"; + outputJSON.put("id", filename); + models.put(filename, outputJSON); + } + } + } + + + /** + * Processes the container node and populates the moduleJSON + * + * @param container + * @param moduleName + * @throws JSONException + * @throws IOException + */ + private JSONObject processContainer(ContainerSchemaNode container, String moduleName, boolean addSchemaStmt, JSONObject models) throws JSONException, IOException{ + JSONObject moduleJSON = getSchemaTemplate(); + if(addSchemaStmt) { + moduleJSON = getSchemaTemplate(); + } else { + moduleJSON = new JSONObject(); + } + moduleJSON.put(TYPE_KEY, OBJECT_TYPE); + + String containerDescription = container.getDescription(); + moduleJSON.put(DESCRIPTION_KEY, containerDescription); + + Set containerChildren = ((ContainerSchemaNode)container).getChildNodes(); + JSONObject properties = processChildren(containerChildren, moduleName, models); + moduleJSON.put(PROPERTIES_KEY, properties); + return moduleJSON; + } + + /** + * Processes the nodes + * @param nodes + * @param moduleName + * @return + * @throws JSONException + * @throws IOException + */ + private JSONObject processChildren(Set nodes, String moduleName, JSONObject models) throws JSONException, IOException { + + JSONObject properties = new JSONObject(); + + for(DataSchemaNode node : nodes){ + String name = node.getQName().getLocalName(); + JSONObject property = null; + if(node instanceof LeafSchemaNode) { + property = processLeafNode((LeafSchemaNode)node); + } else if (node instanceof ListSchemaNode) { + property = processListSchemaNode((ListSchemaNode)node, moduleName, models); + + } else if (node instanceof LeafListSchemaNode) { + property = processLeafListNode((LeafListSchemaNode)node); + + } else if (node instanceof ChoiceNode) { + property = processChoiceNode((ChoiceNode)node, moduleName, models); + + } else if (node instanceof AnyXmlSchemaNode) { + property = processAnyXMLNode((AnyXmlSchemaNode)node); + + } else if (node instanceof ContainerSchemaNode) { + property = processContainer((ContainerSchemaNode)node, moduleName, false, models); + + } else { + throw new IllegalArgumentException("Unknown DataSchemaNode type: " + node.getClass()); + } + + property.putOpt(DESCRIPTION_KEY, node.getDescription()); + properties.put(name, property); + } + return properties; + } + + /** + * + * @param listNode + * @throws JSONException + */ + private JSONObject processLeafListNode(LeafListSchemaNode listNode) throws JSONException { + JSONObject props = new JSONObject(); + props.put(TYPE_KEY, ARRAY_TYPE); + + JSONObject itemsVal = new JSONObject(); + processTypeDef(listNode.getType(), itemsVal); + props.put(ITEMS_KEY, itemsVal); + + ConstraintDefinition constraints = listNode.getConstraints(); + processConstraints(constraints, props); + + return props; + } + + /** + * + * @param choiceNode + * @param moduleName + * @throws JSONException + * @throws IOException + */ + private JSONObject processChoiceNode(ChoiceNode choiceNode, String moduleName, JSONObject models) throws JSONException, IOException { + + Set cases = choiceNode.getCases(); + + JSONArray choiceProps = new JSONArray(); + for(ChoiceCaseNode choiceCase: cases) { + String choiceName = choiceCase.getQName().getLocalName(); + JSONObject choiceProp = processChildren(choiceCase.getChildNodes(), moduleName, models); + JSONObject choiceObj = new JSONObject(); + choiceObj.put(choiceName, choiceProp); + choiceObj.put(TYPE_KEY, OBJECT_TYPE); + choiceProps.put(choiceObj); + } + + JSONObject oneOfProps = new JSONObject(); + oneOfProps.put(ONE_OF_KEY, choiceProps); + oneOfProps.put(TYPE_KEY, OBJECT_TYPE); + + return oneOfProps; + } + + + /** + * + * @param constraints + * @param props + * @throws JSONException + */ + private void processConstraints(ConstraintDefinition constraints, JSONObject props) throws JSONException { + boolean isMandatory = constraints.isMandatory(); + props.put(REQUIRED_KEY, isMandatory); + + Integer minElements = constraints.getMinElements(); + Integer maxElements = constraints.getMaxElements(); + if(minElements !=null) { + props.put(MIN_ITEMS, minElements); + } + if(maxElements !=null) { + props.put(MAX_ITEMS, maxElements); + } + } + + /** + * Parses a ListSchema node. + * + * Due to a limitation of the RAML--->JAX-RS tool, sub-properties + * must be in a separate JSON schema file. Hence, we have to write + * some properties to a new file, while continuing to process the rest. + * + * @param listNode + * @param moduleName + * @return + * @throws JSONException + * @throws IOException + */ + private JSONObject processListSchemaNode(ListSchemaNode listNode, String moduleName, JSONObject models) throws JSONException, IOException { + + Set listChildren = listNode.getChildNodes(); + String fileName = listNode.getQName().getLocalName(); + + JSONObject childSchemaProperties = processChildren(listChildren, moduleName, models); + JSONObject childSchema = getSchemaTemplate(); + childSchema.put(TYPE_KEY, OBJECT_TYPE); + childSchema.put(PROPERTIES_KEY, childSchemaProperties); + + /* + * Due to a limitation of the RAML--->JAX-RS tool, sub-properties + * must be in a separate JSON schema file. Hence, we have to write + * some properties to a new file, while continuing to process the rest. + */ + //writeToFile(fileName, childSchema.toString(2), moduleName); + childSchema.put("id", fileName); + models.put(fileName, childSchema); + + + JSONObject listNodeProperties = new JSONObject(); + listNodeProperties.put(TYPE_KEY, ARRAY_TYPE); + + JSONObject items = new JSONObject(); + items.put(REF_KEY,fileName ); + listNodeProperties.put(ITEMS_KEY, items); + + return listNodeProperties; + + } + + /** + * + * @param leafNode + * @return + * @throws JSONException + */ + private JSONObject processLeafNode(LeafSchemaNode leafNode) throws JSONException { + JSONObject property = new JSONObject(); + + String leafDescription = leafNode.getDescription(); + property.put(DESCRIPTION_KEY, leafDescription); + + processConstraints(leafNode.getConstraints(), property); + processTypeDef(leafNode.getType(), property); + + return property; + } + + /** + * + * @param leafNode + * @return + * @throws JSONException + */ + private JSONObject processAnyXMLNode(AnyXmlSchemaNode leafNode) throws JSONException { + JSONObject property = new JSONObject(); + + String leafDescription = leafNode.getDescription(); + property.put(DESCRIPTION_KEY, leafDescription); + + processConstraints(leafNode.getConstraints(), property); + + return property; + } + + /** + * @param property + * @throws JSONException + */ + private void processTypeDef(TypeDefinition leafTypeDef, JSONObject property) throws JSONException { + + if(leafTypeDef instanceof ExtendedType){ + processExtendedType(leafTypeDef, property); + } else if (leafTypeDef instanceof EnumerationType) { + processEnumType((EnumerationType)leafTypeDef, property); + + } else if (leafTypeDef instanceof BitsTypeDefinition) { + processBitsType((BitsTypeDefinition)leafTypeDef, property); + + } else if (leafTypeDef instanceof UnionTypeDefinition) { + processUnionType((UnionTypeDefinition)leafTypeDef, property); + + } else if (leafTypeDef instanceof IdentityrefTypeDefinition) { + property.putOpt(TYPE_KEY, "object"); + } else if (leafTypeDef instanceof BinaryTypeDefinition) { + processBinaryType((BinaryTypeDefinition)leafTypeDef, property); + } else { + //System.out.println("In else: " + leafTypeDef.getClass()); + String jsonType = YANG_TYPE_TO_JSON_TYPE_MAPPING.get(leafTypeDef.getClass()); + if(jsonType==null) { + jsonType = "object"; + } + property.putOpt(TYPE_KEY, jsonType); + } + } + + /** + * + * @param leafTypeDef + * @param property + * @throws JSONException + */ + private void processExtendedType(TypeDefinition leafTypeDef, JSONObject property) throws JSONException { + Object leafBaseType = leafTypeDef.getBaseType(); + if(leafBaseType instanceof ExtendedType){ + //recursively process an extended type until we hit a base type + processExtendedType((TypeDefinition)leafBaseType, property); + } else { + List lengthConstraints = ((ExtendedType) leafTypeDef).getLengthConstraints(); + for(LengthConstraint lengthConstraint: lengthConstraints) { + Number min = lengthConstraint.getMin(); + Number max = lengthConstraint.getMax(); + property.putOpt(MIN_LENGTH_KEY, min); + property.putOpt(MAX_LENGTH_KEY, max); + } + String jsonType = YANG_TYPE_TO_JSON_TYPE_MAPPING.get(leafBaseType.getClass()); + property.putOpt(TYPE_KEY,jsonType ); + } + + } + + /* + * + */ + private void processBinaryType(BinaryTypeDefinition binaryType, JSONObject property) throws JSONException { + property.put(TYPE_KEY, STRING); + JSONObject media = new JSONObject(); + media.put(BINARY_ENCODING_KEY, BASE_64); + property.put(MEDIA_KEY, media); + } + + /** + * + * @param enumLeafType + * @param property + * @throws JSONException + */ + private void processEnumType(EnumerationType enumLeafType, JSONObject property) throws JSONException { + List enumPairs = enumLeafType.getValues(); + List enumNames = new ArrayList(); + for(EnumPair enumPair: enumPairs) { + enumNames.add(enumPair.getName()); + } + property.putOpt(ENUM, new JSONArray(enumNames)); + } + + /** + * + * @param bitsType + * @param property + * @throws JSONException + */ + private void processBitsType(BitsTypeDefinition bitsType, JSONObject property) throws JSONException{ + property.put(TYPE_KEY, ARRAY_TYPE); + property.put(MIN_ITEMS, 0); + property.put(UNIQUE_ITEMS_KEY, true); + JSONArray enumValues = new JSONArray(); + + List bits = bitsType.getBits(); + for(Bit bit: bits) { + enumValues.put(bit.getName()); + } + JSONObject itemsValue = new JSONObject(); + itemsValue.put(ENUM, enumValues); + property.put(ITEMS_KEY, itemsValue); + } + + + /** + * + * @param unionType + * @param property + * @throws JSONException + */ + private void processUnionType(UnionTypeDefinition unionType, JSONObject property) throws JSONException{ + + List> unionTypes = unionType.getTypes(); + JSONArray unionArray = new JSONArray(); + for(TypeDefinition typeDef: unionTypes) { + unionArray.put(YANG_TYPE_TO_JSON_TYPE_MAPPING.get(typeDef.getClass())); + } + property.put(TYPE_KEY, unionArray); + } + + + /** + * Helper method to generate a pre-filled + * JSON schema object. + * @return + * @throws JSONException + */ + private JSONObject getSchemaTemplate() throws JSONException { + JSONObject schemaJSON = new JSONObject(); + schemaJSON.put(SCHEMA_KEY, SCHEMA_URL); + + return schemaJSON; + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/jaxrs/ApiDocApplication.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/jaxrs/ApiDocApplication.java new file mode 100644 index 0000000000..bec34b232a --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/jaxrs/ApiDocApplication.java @@ -0,0 +1,24 @@ +/* + * 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.rest.doc.jaxrs; + +import org.opendaylight.controller.sal.rest.doc.impl.ApiDocServiceImpl; + +import javax.ws.rs.core.Application; +import java.util.HashSet; +import java.util.Set; + +public class ApiDocApplication extends Application { + @Override + public Set getSingletons() { + Set singletons = new HashSet<>(); + singletons.add(ApiDocServiceImpl.getInstance()); + singletons.add(new JaxbContextResolver()); + return singletons; + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/jaxrs/JaxbContextResolver.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/jaxrs/JaxbContextResolver.java new file mode 100644 index 0000000000..5508507d5f --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/jaxrs/JaxbContextResolver.java @@ -0,0 +1,43 @@ +/* + * 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.rest.doc.jaxrs; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule; +import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.Provider; + +@Provider +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class JaxbContextResolver implements ContextResolver { + + private ObjectMapper ctx; + + public JaxbContextResolver(){ + ctx = new ObjectMapper(); + ctx.registerModule(new JsonOrgModule()); + ctx.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.ALWAYS); + } + + @Override + public ObjectMapper getContext(Class aClass) { + + if (ApiDeclaration.class.isAssignableFrom(aClass)){ + return ctx; + } + + return null;//must return null so that jax-rs can continue context search + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/model/builder/OperationBuilder.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/model/builder/OperationBuilder.java new file mode 100644 index 0000000000..fc890d5a2d --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/model/builder/OperationBuilder.java @@ -0,0 +1,118 @@ +/* + * 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.rest.doc.model.builder; + +import org.opendaylight.controller.sal.rest.doc.swagger.Operation; +import org.opendaylight.controller.sal.rest.doc.swagger.Parameter; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +import java.util.ArrayList; +import java.util.List; + +/** + * + */ +public final class OperationBuilder { + + /** + * + */ + public static class Get{ + + protected Operation spec; + protected DataSchemaNode schemaNode; + private final String METHOD_NAME = "GET"; + + public Get(DataSchemaNode node){ + this.schemaNode = node; + spec = new Operation(); + spec.setMethod(METHOD_NAME); + spec.setNickname(METHOD_NAME + "-" + node.getQName().getLocalName()); + spec.setType(node.getQName().getLocalName()); + spec.setNotes(node.getDescription()); + } + + public Get pathParams(List params){ + List pathParameters = new ArrayList<>(params); + spec.setParameters(pathParameters); + return this; + } + + public Operation build(){ + return spec; + } + } + + /** + * + */ + public static class Put{ + protected Operation spec; + protected DataSchemaNode schemaNode; + private final String METHOD_NAME = "PUT"; + + public Put(DataSchemaNode node){ + this.schemaNode = node; + spec = new Operation(); + spec.setType(node.getQName().getLocalName()); + spec.setNotes(node.getDescription()); + } + + public Put pathParams(List params){ + List parameters = new ArrayList<>(params); + Parameter payload = new Parameter(); + payload.setParamType("body"); + payload.setType(schemaNode.getQName().getLocalName()); + parameters.add(payload); + spec.setParameters(parameters); + return this; + } + + public Operation build(){ + spec.setMethod(METHOD_NAME); + spec.setNickname(METHOD_NAME + "-" + schemaNode.getQName().getLocalName()); + return spec; + } + } + + /** + * + */ + public static final class Post extends Put{ + + private final String METHOD_NAME = "POST"; + + public Post(DataSchemaNode node){ + super(node); + } + + public Operation build(){ + spec.setMethod(METHOD_NAME); + spec.setNickname(METHOD_NAME + "-" + schemaNode.getQName().getLocalName()); + return spec; + } + } + + /** + * + */ + public static final class Delete extends Get { + private final String METHOD_NAME = "DELETE"; + + public Delete(DataSchemaNode node){ + super(node); + } + + public Operation build(){ + spec.setMethod(METHOD_NAME); + spec.setNickname(METHOD_NAME + "-" + schemaNode.getQName().getLocalName()); + spec.setType(null); + return spec; + } + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Api.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Api.java new file mode 100644 index 0000000000..a2be741c74 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Api.java @@ -0,0 +1,37 @@ +/* + * 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.rest.doc.swagger; + +import java.util.List; + +/** + * Implementation of swagger spec + * (see + * https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#522-api-object) + */ +public class Api { + + private String path; + private List operations; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public List getOperations() { + return operations; + } + + public void setOperations(List operations) { + this.operations = operations; + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ApiDeclaration.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ApiDeclaration.java new file mode 100644 index 0000000000..e89bdaf603 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ApiDeclaration.java @@ -0,0 +1,91 @@ +/* + * 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.rest.doc.swagger; + +import org.json.JSONObject; + +import java.util.List; + +/** + * Implementation of swagger spec + * (see + * https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#52-api-declaration) + */ +public class ApiDeclaration { + private String apiVersion; + private String swaggerVersion; + private String basePath; + private String resourcePath; + private List produces; + private List apis; + private JSONObject models; + + public JSONObject getModels() { + return models; + } + + public void setModels(JSONObject models) { + this.models = models; + } + + public String getApiVersion() { + return apiVersion; + } + + public void setApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + } + + public String getSwaggerVersion() { + return swaggerVersion; + } + + public void setSwaggerVersion(String swaggerVersion) { + this.swaggerVersion = swaggerVersion; + } + + public String getBasePath() { + return basePath; + } + + public void setBasePath(String basePath) { + this.basePath = basePath; + } + + public String getResourcePath() { + return resourcePath; + } + + public void setResourcePath(String resourcePath) { + this.resourcePath = resourcePath; + } + + public List getProduces() { + return produces; + } + + public void setProduces(List produces) { + this.produces = produces; + } + + public List getApis() { + return apis; + } + + public void setApis(List apis) { + this.apis = apis; + } + + public boolean hasApi(){ + return (apis != null && !apis.isEmpty()); + } + + public boolean hasModel(){ + return (models != null && models.length() > 0); + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Operation.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Operation.java new file mode 100644 index 0000000000..d1150fd0bd --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Operation.java @@ -0,0 +1,90 @@ +/* + * 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.rest.doc.swagger; + +import java.util.List; + +/** + * Implementation of swagger spec + * (see + * https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#523-operation-object) + */ +public class Operation { + private String method; + private String summary; + private String notes; + private String type; + private String nickname; + private List consumes; + private List parameters; + private List responseMessages; + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public List getConsumes() { + return consumes; + } + + public void setConsumes(List consumes) { + this.consumes = consumes; + } + + public List getParameters() { + return parameters; + } + + public void setParameters(List parameters) { + this.parameters = parameters; + } + + public List getResponseMessages() { + return responseMessages; + } + + public void setResponseMessages(List responseMessages) { + this.responseMessages = responseMessages; + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Parameter.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Parameter.java new file mode 100644 index 0000000000..dd56b9e854 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Parameter.java @@ -0,0 +1,61 @@ +/* + * 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.rest.doc.swagger; + +/** + * Implementation of swagger spec + * (see + * https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#524-parameter-object) + */ +public class Parameter { + private String name; + private String description; + private boolean required; + private String type; + private String paramType; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public boolean isRequired() { + return required; + } + + public void setRequired(boolean required) { + this.required = required; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getParamType() { + return paramType; + } + + public void setParamType(String paramType) { + this.paramType = paramType; + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Resource.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Resource.java new file mode 100644 index 0000000000..c5c39799a8 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/Resource.java @@ -0,0 +1,34 @@ +/* + * 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.rest.doc.swagger; + +/** + * Implementation of swagger spec + * (see + * https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#512-resource-object) + */ +public class Resource { + private String path; + private String description; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ResourceList.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ResourceList.java new file mode 100644 index 0000000000..9b1a106d0e --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ResourceList.java @@ -0,0 +1,45 @@ +/* + * 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.rest.doc.swagger; + +import java.util.List; + +/** + * Implementation of swagger spec + * (see + * https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#51-resource-listing) + */ +public class ResourceList { + private String apiVersion; + private String swaggerVersion; + private List apis; + + public String getApiVersion() { + return apiVersion; + } + + public void setApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + } + + public String getSwaggerVersion() { + return swaggerVersion; + } + + public void setSwaggerVersion(String swaggerVersion) { + this.swaggerVersion = swaggerVersion; + } + + public List getApis() { + return apis; + } + + public void setApis(List apis) { + this.apis = apis; + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ResponseMessage.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ResponseMessage.java new file mode 100644 index 0000000000..6c23099286 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/swagger/ResponseMessage.java @@ -0,0 +1,34 @@ +/* + * 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.rest.doc.swagger; + +/** + * Implementation of swagger spec + * (see + * https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#525-response-message-object) + */ +public class ResponseMessage { + private int code; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/WEB-INF/web.xml b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/WEB-INF/web.xml new file mode 100644 index 0000000000..356a395b97 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/WEB-INF/web.xml @@ -0,0 +1,64 @@ + + + + + JAXRSApiDoc + com.sun.jersey.spi.container.servlet.ServletContainer + + javax.ws.rs.Application + org.opendaylight.controller.sal.rest.doc.jaxrs.ApiDocApplication + + 1 + + + + JAXRSApiDoc + /apis/* + + + + + + free access + /explorer/css/* + /explorer/images/* + /explorer/lib/* + /explorer/* + + + + diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/highlight.default.css b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/highlight.default.css new file mode 100644 index 0000000000..e417fc1799 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/highlight.default.css @@ -0,0 +1,135 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +pre code { + display: block; padding: 0.5em; + background: #F0F0F0; +} + +pre code, +pre .subst, +pre .tag .title, +pre .lisp .title, +pre .clojure .built_in, +pre .nginx .title { + color: black; +} + +pre .string, +pre .title, +pre .constant, +pre .parent, +pre .tag .value, +pre .rules .value, +pre .rules .value .number, +pre .preprocessor, +pre .ruby .symbol, +pre .ruby .symbol .string, +pre .aggregate, +pre .template_tag, +pre .django .variable, +pre .smalltalk .class, +pre .addition, +pre .flow, +pre .stream, +pre .bash .variable, +pre .apache .tag, +pre .apache .cbracket, +pre .tex .command, +pre .tex .special, +pre .erlang_repl .function_or_atom, +pre .markdown .header { + color: #800; +} + +pre .comment, +pre .annotation, +pre .template_comment, +pre .diff .header, +pre .chunk, +pre .markdown .blockquote { + color: #888; +} + +pre .number, +pre .date, +pre .regexp, +pre .literal, +pre .smalltalk .symbol, +pre .smalltalk .char, +pre .go .constant, +pre .change, +pre .markdown .bullet, +pre .markdown .link_url { + color: #080; +} + +pre .label, +pre .javadoc, +pre .ruby .string, +pre .decorator, +pre .filter .argument, +pre .localvars, +pre .array, +pre .attr_selector, +pre .important, +pre .pseudo, +pre .pi, +pre .doctype, +pre .deletion, +pre .envvar, +pre .shebang, +pre .apache .sqbracket, +pre .nginx .built_in, +pre .tex .formula, +pre .erlang_repl .reserved, +pre .prompt, +pre .markdown .link_label, +pre .vhdl .attribute, +pre .clojure .attribute, +pre .coffeescript .property { + color: #88F +} + +pre .keyword, +pre .id, +pre .phpdoc, +pre .title, +pre .built_in, +pre .aggregate, +pre .css .tag, +pre .javadoctag, +pre .phpdoc, +pre .yardoctag, +pre .smalltalk .class, +pre .winutils, +pre .bash .variable, +pre .apache .tag, +pre .go .typename, +pre .tex .command, +pre .markdown .strong, +pre .request, +pre .status { + font-weight: bold; +} + +pre .markdown .emphasis { + font-style: italic; +} + +pre .nginx .built_in { + font-weight: normal; +} + +pre .coffeescript .javascript, +pre .javascript .xml, +pre .tex .formula, +pre .xml .javascript, +pre .xml .vbscript, +pre .xml .css, +pre .xml .cdata { + opacity: 0.5; +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/screen.css b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/screen.css new file mode 100644 index 0000000000..1627ecd0d3 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/css/screen.css @@ -0,0 +1,1070 @@ +/* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */ +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; +} +body { + line-height: 1; +} +ol, +ul { + list-style: none; +} +blockquote, +q { + quotes: none; +} +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +.swagger-ui-wrap { + line-height: 1; + font-family: "Droid Sans", sans-serif; + max-width: 960px; + margin-left: auto; + margin-right: auto; +} +.swagger-ui-wrap b, +.swagger-ui-wrap strong { + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-ui-wrap q, +.swagger-ui-wrap blockquote { + quotes: none; +} +.swagger-ui-wrap p { + line-height: 1.4em; + padding: 0 0 10px; + color: #333333; +} +.swagger-ui-wrap q:before, +.swagger-ui-wrap q:after, +.swagger-ui-wrap blockquote:before, +.swagger-ui-wrap blockquote:after { + content: none; +} +.swagger-ui-wrap .heading_with_menu h1, +.swagger-ui-wrap .heading_with_menu h2, +.swagger-ui-wrap .heading_with_menu h3, +.swagger-ui-wrap .heading_with_menu h4, +.swagger-ui-wrap .heading_with_menu h5, +.swagger-ui-wrap .heading_with_menu h6 { + display: block; + clear: none; + float: left; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + width: 60%; +} +.swagger-ui-wrap table { + border-collapse: collapse; + border-spacing: 0; +} +.swagger-ui-wrap table thead tr th { + padding: 5px; + font-size: 0.9em; + color: #666666; + border-bottom: 1px solid #999999; +} +.swagger-ui-wrap table tbody tr:last-child td { + border-bottom: none; +} +.swagger-ui-wrap table tbody tr.offset { + background-color: #f0f0f0; +} +.swagger-ui-wrap table tbody tr td { + padding: 6px; + font-size: 0.9em; + border-bottom: 1px solid #cccccc; + vertical-align: top; + line-height: 1.3em; +} +.swagger-ui-wrap ol { + margin: 0px 0 10px; + padding: 0 0 0 18px; + list-style-type: decimal; +} +.swagger-ui-wrap ol li { + padding: 5px 0px; + font-size: 0.9em; + color: #333333; +} +.swagger-ui-wrap ol, +.swagger-ui-wrap ul { + list-style: none; +} +.swagger-ui-wrap h1 a, +.swagger-ui-wrap h2 a, +.swagger-ui-wrap h3 a, +.swagger-ui-wrap h4 a, +.swagger-ui-wrap h5 a, +.swagger-ui-wrap h6 a { + text-decoration: none; +} +.swagger-ui-wrap h1 a:hover, +.swagger-ui-wrap h2 a:hover, +.swagger-ui-wrap h3 a:hover, +.swagger-ui-wrap h4 a:hover, +.swagger-ui-wrap h5 a:hover, +.swagger-ui-wrap h6 a:hover { + text-decoration: underline; +} +.swagger-ui-wrap h1 span.divider, +.swagger-ui-wrap h2 span.divider, +.swagger-ui-wrap h3 span.divider, +.swagger-ui-wrap h4 span.divider, +.swagger-ui-wrap h5 span.divider, +.swagger-ui-wrap h6 span.divider { + color: #aaaaaa; +} +.swagger-ui-wrap a { + color: #547f00; +} +.swagger-ui-wrap a img { + border: none; +} +.swagger-ui-wrap article, +.swagger-ui-wrap aside, +.swagger-ui-wrap details, +.swagger-ui-wrap figcaption, +.swagger-ui-wrap figure, +.swagger-ui-wrap footer, +.swagger-ui-wrap header, +.swagger-ui-wrap hgroup, +.swagger-ui-wrap menu, +.swagger-ui-wrap nav, +.swagger-ui-wrap section, +.swagger-ui-wrap summary { + display: block; +} +.swagger-ui-wrap pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; +} +.swagger-ui-wrap pre code { + line-height: 1.6em; + background: none; +} +.swagger-ui-wrap .content > .content-type > div > label { + clear: both; + display: block; + color: #0F6AB4; + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-ui-wrap .content pre { + font-size: 12px; + margin-top: 5px; + padding: 5px; +} +.swagger-ui-wrap .icon-btn { + cursor: pointer; +} +.swagger-ui-wrap .info_title { + padding-bottom: 10px; + font-weight: bold; + font-size: 25px; +} +.swagger-ui-wrap p.big, +.swagger-ui-wrap div.big p { + font-size: 1em; + margin-bottom: 10px; +} +.swagger-ui-wrap form.fullwidth ol li.string input, +.swagger-ui-wrap form.fullwidth ol li.url input, +.swagger-ui-wrap form.fullwidth ol li.text textarea, +.swagger-ui-wrap form.fullwidth ol li.numeric input { + width: 500px !important; +} +.swagger-ui-wrap .info_license { + padding-bottom: 5px; +} +.swagger-ui-wrap .info_tos { + padding-bottom: 5px; +} +.swagger-ui-wrap .message-fail { + color: #cc0000; +} +.swagger-ui-wrap .info_contact { + padding-bottom: 5px; +} +.swagger-ui-wrap .info_description { + padding-bottom: 10px; + font-size: 15px; +} +.swagger-ui-wrap .markdown ol li, +.swagger-ui-wrap .markdown ul li { + padding: 3px 0px; + line-height: 1.4em; + color: #333333; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input, +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input, +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input { + display: block; + padding: 4px; + width: auto; + clear: both; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input.title, +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input.title, +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input.title { + font-size: 1.3em; +} +.swagger-ui-wrap table.fullwidth { + width: 100%; +} +.swagger-ui-wrap .model-signature { + font-family: "Droid Sans", sans-serif; + font-size: 1em; + line-height: 1.5em; +} +.swagger-ui-wrap .model-signature .signature-nav a { + text-decoration: none; + color: #AAA; +} +.swagger-ui-wrap .model-signature .signature-nav a:hover { + text-decoration: underline; + color: black; +} +.swagger-ui-wrap .model-signature .signature-nav .selected { + color: black; + text-decoration: none; +} +.swagger-ui-wrap .model-signature .propType { + color: #5555aa; +} +.swagger-ui-wrap .model-signature pre:hover { + background-color: #ffffdd; +} +.swagger-ui-wrap .model-signature pre { + font-size: .85em; + line-height: 1.2em; + overflow: auto; + max-height: 200px; + cursor: pointer; +} +.swagger-ui-wrap .model-signature ul.signature-nav { + display: block; + margin: 0; + padding: 0; +} +.swagger-ui-wrap .model-signature ul.signature-nav li:last-child { + padding-right: 0; + border-right: none; +} +.swagger-ui-wrap .model-signature ul.signature-nav li { + float: left; + margin: 0 5px 5px 0; + padding: 2px 5px 2px 0; + border-right: 1px solid #ddd; +} +.swagger-ui-wrap .model-signature .propOpt { + color: #555; +} +.swagger-ui-wrap .model-signature .snippet small { + font-size: 0.75em; +} +.swagger-ui-wrap .model-signature .propOptKey { + font-style: italic; +} +.swagger-ui-wrap .model-signature .description .strong { + font-weight: bold; + color: #000; + font-size: .9em; +} +.swagger-ui-wrap .model-signature .description div { + font-size: 0.9em; + line-height: 1.5em; + margin-left: 1em; +} +.swagger-ui-wrap .model-signature .description .stronger { + font-weight: bold; + color: #000; +} +.swagger-ui-wrap .model-signature .propName { + font-weight: bold; +} +.swagger-ui-wrap .model-signature .signature-container { + clear: both; +} +.swagger-ui-wrap .body-textarea { + width: 300px; + height: 100px; + border: 1px solid #aaa; +} +.swagger-ui-wrap .markdown p code, +.swagger-ui-wrap .markdown li code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #f0f0f0; + color: black; + padding: 1px 3px; +} +.swagger-ui-wrap .required { + font-weight: bold; +} +.swagger-ui-wrap input.parameter { + width: 300px; + border: 1px solid #aaa; +} +.swagger-ui-wrap h1 { + color: black; + font-size: 1.5em; + line-height: 1.3em; + padding: 10px 0 10px 0; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-ui-wrap .heading_with_menu { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-ui-wrap .heading_with_menu ul { + display: block; + clear: none; + float: right; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + margin-top: 10px; +} +.swagger-ui-wrap h2 { + color: black; + font-size: 1.3em; + padding: 10px 0 10px 0; +} +.swagger-ui-wrap h2 a { + color: black; +} +.swagger-ui-wrap h2 span.sub { + font-size: 0.7em; + color: #999999; + font-style: italic; +} +.swagger-ui-wrap h2 span.sub a { + color: #777777; +} +.swagger-ui-wrap span.weak { + color: #666666; +} +.swagger-ui-wrap .message-success { + color: #89BF04; +} +.swagger-ui-wrap caption, +.swagger-ui-wrap th, +.swagger-ui-wrap td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} +.swagger-ui-wrap .code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.text textarea { + font-family: "Droid Sans", sans-serif; + height: 250px; + padding: 4px; + display: block; + clear: both; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.select select { + display: block; + clear: both; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean label { + display: block; + float: left; + clear: none; + margin: 0; + padding: 0; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean input { + display: block; + float: left; + clear: none; + margin: 0 5px 0 0; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li.required label { + color: black; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li label { + display: block; + clear: both; + width: auto; + padding: 0 0 3px; + color: #666666; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li label abbr { + padding-left: 3px; + color: #888888; +} +.swagger-ui-wrap form.formtastic fieldset.inputs ol li p.inline-hints { + margin-left: 0; + font-style: italic; + font-size: 0.9em; + margin: 0; +} +.swagger-ui-wrap form.formtastic fieldset.buttons { + margin: 0; + padding: 0; +} +.swagger-ui-wrap span.blank, +.swagger-ui-wrap span.empty { + color: #888888; + font-style: italic; +} +.swagger-ui-wrap .markdown h3 { + color: #547f00; +} +.swagger-ui-wrap .markdown h4 { + color: #666666; +} +.swagger-ui-wrap .markdown pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; + margin: 0 0 10px 0; +} +.swagger-ui-wrap .markdown pre code { + line-height: 1.6em; +} +.swagger-ui-wrap div.gist { + margin: 20px 0 25px 0 !important; +} +.swagger-ui-wrap ul#resources { + font-family: "Droid Sans", sans-serif; + font-size: 0.9em; +} +.swagger-ui-wrap ul#resources li.resource { + border-bottom: 1px solid #dddddd; +} +.swagger-ui-wrap ul#resources li.resource:hover div.heading h2 a, +.swagger-ui-wrap ul#resources li.resource.active div.heading h2 a { + color: black; +} +.swagger-ui-wrap ul#resources li.resource:hover div.heading ul.options li a, +.swagger-ui-wrap ul#resources li.resource.active div.heading ul.options li a { + color: #555555; +} +.swagger-ui-wrap ul#resources li.resource:last-child { + border-bottom: none; +} +.swagger-ui-wrap ul#resources li.resource div.heading { + border: 1px solid transparent; + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-ui-wrap ul#resources li.resource div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 14px 10px 0 0; +} +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + border-right: 1px solid #dddddd; + color: #666666; + font-size: 0.9em; +} +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li a { + color: #aaaaaa; + text-decoration: none; +} +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover { + text-decoration: underline; + color: black; +} +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover, +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:active, +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li a.active { + text-decoration: underline; +} +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li:first-child, +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li.first { + padding-left: 0; +} +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li:last-child, +.swagger-ui-wrap ul#resources li.resource div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-ui-wrap ul#resources li.resource div.heading ul.options:first-child, +.swagger-ui-wrap ul#resources li.resource div.heading ul.options.first { + padding-left: 0; +} +.swagger-ui-wrap ul#resources li.resource div.heading h2 { + color: #999999; + padding-left: 0; + display: block; + clear: none; + float: left; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-ui-wrap ul#resources li.resource div.heading h2 a { + color: #999999; +} +.swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover { + color: black; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0 0 10px; + padding: 0; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0; + padding: 0; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 { + display: block; + clear: none; + float: left; + width: auto; + margin: 0; + padding: 0; + line-height: 1.1em; + color: black; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path { + padding-left: 10px; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a { + color: black; + text-decoration: none; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a:hover { + text-decoration: underline; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.http_method a { + text-transform: uppercase; + text-decoration: none; + color: white; + display: inline-block; + width: 50px; + font-size: 0.7em; + text-align: center; + padding: 7px 0 4px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span { + margin: 0; + padding: 0; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 6px 10px 0 0; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + font-size: 0.9em; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a { + text-decoration: none; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content { + border-top: none; + padding: 10px; + -moz-border-radius-bottomleft: 6px; + -webkit-border-bottom-left-radius: 6px; + -o-border-bottom-left-radius: 6px; + -ms-border-bottom-left-radius: 6px; + -khtml-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -moz-border-radius-bottomright: 6px; + -webkit-border-bottom-right-radius: 6px; + -o-border-bottom-right-radius: 6px; + -ms-border-bottom-right-radius: 6px; + -khtml-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + margin: 0 0 20px; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content h4 { + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header a { + padding: 4px 0 0 10px; + display: inline-block; + font-size: 0.9em; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header img { + display: block; + clear: none; + float: right; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit { + display: block; + clear: none; + float: left; + padding: 6px 8px; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type='text'].error { + outline: 2px solid black; + outline-color: #cc0000; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + padding: 10px; + font-size: 0.9em; + max-height: 400px; + overflow-y: auto; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading { + background-color: #f9f2e9; + border: 1px solid #f0e0ca; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a { + background-color: #c5862b; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0e0ca; + color: #c5862b; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a { + color: #c5862b; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content { + background-color: #faf5ee; + border: 1px solid #f0e0ca; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4 { + color: #c5862b; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #ffd20f; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #ffd20f; + color: #ffd20f; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li a { + color: #ffd20f; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content h4 { + color: #ffd20f; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading { + background-color: #f5e8e8; + border: 1px solid #e8c6c7; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #a41e22; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #e8c6c7; + color: #a41e22; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a { + color: #a41e22; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + background-color: #f7eded; + border: 1px solid #e8c6c7; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4 { + color: #a41e22; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a { + color: #c8787a; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading { + background-color: #e7f6ec; + border: 1px solid #c3e8d1; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a { + background-color: #10a54a; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3e8d1; + color: #10a54a; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a { + color: #10a54a; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content { + background-color: #ebf7f0; + border: 1px solid #c3e8d1; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4 { + color: #10a54a; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading { + background-color: #FCE9E3; + border: 1px solid #F5D5C3; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading h3 span.http_method a { + background-color: #D38042; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0cecb; + color: #D38042; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li a { + color: #D38042; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content { + background-color: #faf0ef; + border: 1px solid #f0cecb; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content h4 { + color: #D38042; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading { + background-color: #e7f0f7; + border: 1px solid #c3d9ec; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a { + background-color: #0f6ab4; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3d9ec; + color: #0f6ab4; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a { + color: #0f6ab4; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4 { + color: #0f6ab4; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a { + color: #6fa5d2; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + border-top: none; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li:last-child, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li:last-child, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li.last, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li.last, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:hover, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:active, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a.active { + text-decoration: underline; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li:first-child, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li.first { + padding-left: 0; +} +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations:first-child, +.swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations.first { + padding-left: 0; +} +.swagger-ui-wrap p#colophon { + margin: 0 15px 40px 15px; + padding: 10px 0; + font-size: 0.8em; + border-top: 1px solid #dddddd; + font-family: "Droid Sans", sans-serif; + color: #999999; + font-style: italic; +} +.swagger-ui-wrap p#colophon a { + text-decoration: none; + color: #547f00; +} +.swagger-ui-wrap h3 { + color: black; + font-size: 1.1em; + padding: 10px 0 10px 0; +} +.swagger-ui-wrap .markdown ol, +.swagger-ui-wrap .markdown ul { + font-family: "Droid Sans", sans-serif; + margin: 5px 0 10px; + padding: 0 0 0 18px; + list-style-type: disc; +} +.swagger-ui-wrap form.form_box { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; + padding: 10px; +} +.swagger-ui-wrap form.form_box label { + color: #0f6ab4 !important; +} +.swagger-ui-wrap form.form_box input[type=submit] { + display: block; + padding: 10px; +} +.swagger-ui-wrap form.form_box p.weak { + font-size: 0.8em; +} +.swagger-ui-wrap form.form_box p { + font-size: 0.9em; + padding: 0 0 15px; + color: #7e7b6d; +} +.swagger-ui-wrap form.form_box p a { + color: #646257; +} +.swagger-ui-wrap form.form_box p strong { + color: black; +} +#header { + background-color: #89bf04; + padding: 14px; +} +#header a#logo { + font-size: 1.5em; + font-weight: bold; + text-decoration: none; + background: transparent url(../images/logo_small.png) no-repeat left center; + padding: 20px 0 20px 40px; + color: white; +} +#header form#api_selector { + display: block; + clear: none; + float: right; +} +#header form#api_selector .input { + display: block; + clear: none; + float: left; + margin: 0 10px 0 0; +} +#header form#api_selector .input input#input_apiKey { + width: 200px; +} +#header form#api_selector .input input#input_baseUrl { + width: 400px; +} +#header form#api_selector .input a#explore { + display: block; + text-decoration: none; + font-weight: bold; + padding: 6px 8px; + font-size: 0.9em; + color: white; + background-color: #547f00; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; +} +#header form#api_selector .input a#explore:hover { + background-color: #547f00; +} +#header form#api_selector .input input { + font-size: 0.9em; + padding: 3px; + margin: 0; +} +#content_message { + margin: 10px 15px; + font-style: italic; + color: #999999; +} +#message-bar { + min-height: 30px; + text-align: center; + padding-top: 10px; +} diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/logo_small.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/logo_small.png new file mode 100644 index 0000000000..5496a65579 Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/logo_small.png differ diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/pet_store_api.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/pet_store_api.png new file mode 100644 index 0000000000..f9f9cd4aeb Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/pet_store_api.png differ diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/throbber.gif b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/throbber.gif new file mode 100644 index 0000000000..0639388924 Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/throbber.gif differ diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/wordnik_api.png b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/wordnik_api.png new file mode 100644 index 0000000000..dca4f1455a Binary files /dev/null and b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/images/wordnik_api.png differ diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/index.html b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/index.html new file mode 100644 index 0000000000..b8f67750c3 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/index.html @@ -0,0 +1,83 @@ + + + + Swagger UI + + + + + + + + + + + + + + + + + + + + +
+   +
+ +
+ +
+ + + + diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/backbone-min.js b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/backbone-min.js new file mode 100644 index 0000000000..c1c0d4fff2 --- /dev/null +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/resources/explorer/lib/backbone-min.js @@ -0,0 +1,38 @@ +// Backbone.js 0.9.2 + +// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Backbone may be freely distributed under the MIT license. +// For all details and documentation: +// http://backbonejs.org +(function(){var l=this,y=l.Backbone,z=Array.prototype.slice,A=Array.prototype.splice,g;g="undefined"!==typeof exports?exports:l.Backbone={};g.VERSION="0.9.2";var f=l._;!f&&"undefined"!==typeof require&&(f=require("underscore"));var i=l.jQuery||l.Zepto||l.ender;g.setDomLibrary=function(a){i=a};g.noConflict=function(){l.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var p=/\s+/,k=g.Events={on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(p);for(d=this._callbacks||(this._callbacks= +{});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,h,g,j,q;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(p):f.keys(e);d=a.shift();)if(h=e[d],delete e[d],h&&(b||c))for(g=h.tail;(h=h.next)!==g;)if(j=h.callback,q=h.context,b&&j!==b||c&&q!==c)this.on(d,j,q);return this}},trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(p);for(g= +z.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};k.bind=k.on;k.unbind=k.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,"defaults"))a=f.extend({},c,a);b&&b.collection&&(this.collection=b.collection);this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");this.changed={};this._silent= +{};this._pending={};this.set(a,{silent:!0});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,k,{changed:null,_silent:null,_pending:null,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(null== +b?"":""+b)},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;d instanceof o&&(d=d.attributes);if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return!1;this.idAttribute in d&&(this.id=d[this.idAttribute]);var b=c.changes={},h=this.attributes,g=this._escapedAttributes,j=this._previousAttributes||{};for(e in d){a=d[e];if(!f.isEqual(h[e],a)||c.unset&&f.has(h,e))delete g[e],(c.silent?this._silent: +b)[e]=!0;c.unset?delete h[e]:h[e]=a;!f.isEqual(j[e],a)||f.has(h,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=!0)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=!0;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=!0;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&c(b,d)}; +a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return!1;e=f.clone(this.attributes)}a=f.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c))return!1;var h=this,i=c.success;c.success=function(a,b,e){b=h.parse(a,e);if(c.wait){delete c.wait;b=f.extend(d||{},b)}if(!h.set(b,c))return false;i?i(h,a):h.trigger("sync",h,a,c)};c.error=g.wrapError(c.error, +h,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d(),!1;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=n(this,"urlRoot")||n(this.collection,"url")||t(); +return this.isNew()?a:a+("/"==a.charAt(a.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){a||(a={});var b=this._changing;this._changing=!0;for(var c in this._silent)this._pending[c]=!0;var d=f.extend({},a.changes,this._silent);this._silent={};for(c in d)this.trigger("change:"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending= +{};this.trigger("change",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=!1;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length|| +!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return!0;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error?b.error(this,c,b):this.trigger("error",this,c,b);return!1}});var r=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);b.comparator&&(this.comparator=b.comparator); +this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:!0,parse:b.parse})};f.extend(r.prototype,k,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,i,j={},k={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];c=0;for(d=a.length;c=b))this.iframe=i('