Merge "Improve RpcProviderRegistry loading"
authorTony Tkacik <ttkacik@cisco.com>
Fri, 18 Jul 2014 08:45:04 +0000 (08:45 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 18 Jul 2014 08:45:04 +0000 (08:45 +0000)
33 files changed:
features/base/src/main/resources/features.xml
features/config/pom.xml [moved from opendaylight/config/feature/pom.xml with 97% similarity]
features/config/src/main/resources/features.xml [new file with mode: 0644]
features/mdsal/pom.xml [moved from opendaylight/md-sal/feature/pom.xml with 97% similarity]
features/mdsal/src/main/resources/features.xml [moved from opendaylight/md-sal/feature/src/main/resources/features.xml with 56% similarity]
features/netconf/pom.xml [new file with mode: 0644]
features/netconf/src/main/resources/features.xml [new file with mode: 0644]
features/pom.xml [new file with mode: 0644]
features/protocol-framework/pom.xml [new file with mode: 0644]
features/protocol-framework/src/main/resources/features.xml [new file with mode: 0644]
opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/jaxb/Context.java
opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/FilterProcessor.java
opendaylight/commons/filter-valve/src/main/java/org/opendaylight/controller/filtervalve/cors/model/UrlMatcher.java
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/feature/src/main/resources/features.xml [deleted file]
opendaylight/config/pom.xml
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/flexible/FlexibleThreadPoolModule.java
opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl-flexible.yang
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight-karaf/src/main/resources/configuration/initial/02-clustering.xml [deleted file]
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-netconf.xml
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceTwoPhaseCommitTransaction.java
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTest.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/AbstractNetconfSessionNegotiator.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfEOMAggregator.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/NetconfMessageToXMLEncoder.java
pom.xml

index 6028617..b9107b9 100644 (file)
@@ -79,6 +79,8 @@
    <feature name="base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
       <bundle start="true" start-level="35">mvn:eclipselink/javax.persistence/2.0.4.v201112161009</bundle>
       <bundle start="true" start-level="35">mvn:eclipselink/javax.resource/1.5.0.v200906010428</bundle>
+      <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/2.5.0</bundle>
+      <bundle start="true" start-level="35">mvn:org.eclipse.persistence/org.eclipse.persistence.core/2.5.0</bundle>
    </feature>
    <feature name="base-gemini-web" description="Gemini Web" version="${geminiweb.version}">
       <feature>http</feature>
similarity index 97%
rename from opendaylight/config/feature/pom.xml
rename to features/config/pom.xml
index aaf33cc..01a4ea7 100644 (file)
@@ -5,6 +5,7 @@
     <groupId>org.opendaylight.controller</groupId>
     <artifactId>config-subsystem</artifactId>
     <version>0.2.5-SNAPSHOT</version>
+    <relativePath>../../opendaylight/config/</relativePath>
   </parent>
   <artifactId>config-features</artifactId>
 
diff --git a/features/config/src/main/resources/features.xml b/features/config/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..7c11b5b
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<features name="odl-config-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/netconf-features/${netconf.version}/xml/features</repository>
+
+  <feature name='odl-config-startup' version='${project.version}'>
+    <feature version='${project.version}'>odl-config-netconf-connector</feature>
+    <feature version='${project.version}'>odl-config-persister</feature>
+    <feature version='${project.version}'>odl-netconf-impl</feature>
+  </feature>
+
+  <feature name='odl-config-core' version='${project.version}'>
+    <feature version='${yangtools.version}'>yangtools-concepts</feature>
+    <feature version='${yangtools.version}'>yangtools-binding</feature>
+    <feature version='${yangtools.version}'>yangtools-binding-generator</feature>
+    <feature version='${mdsal.version}'>odl-mdsal-commons</feature>
+    <feature version='${project.version}'>odl-config-api</feature>
+    <bundle>mvn:org.opendaylight.controller/config-util/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/yang-jmx-generator/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/shutdown-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/shutdown-impl/${project.version}</bundle>
+    <bundle>mvn:org.osgi/org.osgi.core/${osgi.core.version}</bundle>
+    <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
+    <bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
+  </feature>
+  <feature name='odl-config-manager' version='${project.version}'>
+    <feature version='${project.version}'>odl-config-core</feature>
+    <bundle>mvn:org.opendaylight.controller/config-manager/${project.version}</bundle>
+  </feature>
+  <feature name='odl-config-persister' version='${project.version}'>
+    <feature version='${netconf.version}'>odl-netconf-api</feature>
+    <feature version='${project.version}'>odl-config-api</feature>
+    <feature version='${yangtools.version}'>yangtools-binding-generator</feature>
+    <bundle>mvn:org.opendaylight.controller/config-persister-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/config-persister-file-xml-adapter/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/config-persister-directory-xml-adapter/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/config-persister-impl/${project.version}</bundle>
+
+    <bundle>mvn:org.opendaylight.controller/netconf-util/${netconf.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netconf-mapping-api/${netconf.version}</bundle>
+
+    <bundle>mvn:com.google.guava/guava/${guava.version}</bundle>
+    <bundle>mvn:commons-io/commons-io/${commons.io.version}</bundle>
+    <bundle>mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
+    <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.core/${eclipse.persistence.version}</bundle>
+    <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/${eclipse.persistence.version}</bundle>
+  </feature>
+  <feature name='odl-config-api' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/config-api/${project.version}</bundle>
+
+    <!-- yangtools features -->
+    <feature version='${yangtools.version}'>yangtools-concepts</feature>
+    <feature version='${yangtools.version}'>yangtools-binding</feature>
+  </feature>
+
+  <feature name='odl-config-netty-config-api' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netty-config-api/${project.version}</bundle>
+
+    <!-- netty bundles -->
+    <bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-common/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
+
+    <feature version='${project.version}'>odl-config-api</feature>
+  </feature>
+  <feature name='odl-config-netty' version='${project.version}'>
+    <feature version='${project.version}'>odl-config-netty-config-api</feature>
+    <bundle>mvn:org.opendaylight.controller/netty-event-executor-config/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netty-threadgroup-config/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netty-timer-config/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/threadpool-config-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/threadpool-config-impl/${project.version}</bundle>
+    <feature version='${project.version}'>odl-config-startup</feature>
+  </feature>
+  <feature name='odl-config-dispatcher' version='${project.version}'>
+      <bundle>mvn:org.opendaylight.controller/netconf-config-dispatcher/${project.version}</bundle>
+  </feature>
+
+</features>
\ No newline at end of file
similarity index 97%
rename from opendaylight/md-sal/feature/pom.xml
rename to features/mdsal/pom.xml
index c08c3e5..2983c5e 100644 (file)
@@ -5,6 +5,7 @@
     <groupId>org.opendaylight.controller</groupId>
     <artifactId>sal-parent</artifactId>
     <version>1.1-SNAPSHOT</version>
+    <relativePath>../../opendaylight/md-sal</relativePath>
   </parent>
   <artifactId>mdsal-features</artifactId>
 
@@ -9,20 +9,20 @@
         <feature version='${project.version}'>odl-mdsal-restconf</feature>
     </feature>
     <feature name='odl-mdsal-commons' version='${project.version}'>
-        <feature version='${yangtools.version}'>yangtools-concepts</feature>
-        <feature version='${yangtools.version}'>yangtools-binding</feature>
+        <feature version='${yangtools.version}'>yangtools-data-binding</feature>
         <bundle>mvn:org.opendaylight.controller/sal-common/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-common-api/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-common-impl/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-common-util/${project.version}</bundle>
-        <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
-        <bundle>wrap:mvn:org.eclipse.xtend/org.eclipse.xtend.lib/${xtend.version}</bundle>
     </feature>
     <feature name='odl-mdsal-broker' version='${project.version}'>
         <feature version='${yangtools.version}'>yangtools-concepts</feature>
         <feature version='${yangtools.version}'>yangtools-binding</feature>
         <feature version='${mdsal.version}'>odl-mdsal-commons</feature>
-        <feature version='${config.version}'>odl-config-subsystem</feature>
+        <feature version='${config.version}'>odl-config-core</feature>
+        <feature version='${config.version}'>odl-config-manager</feature>
+        <feature version='${config.version}'>odl-config-api</feature>
+        <feature version='${config.version}'>odl-config-persister</feature>
         <bundle>mvn:org.opendaylight.controller/sal-core-api/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-core-spi/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-broker-impl/${project.version}</bundle>
@@ -31,6 +31,7 @@
         <bundle>mvn:org.opendaylight.controller/sal-binding-broker-impl/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-binding-util/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-connector-api/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/sal-inmemory-datastore/${project.version}</bundle>
     </feature>
     <feature name='odl-mdsal-restconf' version='${project.version}'>
         <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
         <bundle>wrap:mvn:io.netty/netty-handler/${netty.version}</bundle>
         <bundle>wrap:mvn:io.netty/netty-transport/${netty.version}</bundle>
     </feature>
+    <feature name='odl-mdsal-model' version='${project.version}'>
+        <bundle>mvn:org.opendaylight.controller.model/model-flow-base/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-flow-management/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-flow-service/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-flow-statistics/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-inventory/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.model/model-topology/${project.version}</bundle>
+    </feature>
+    <feature name='odl-mdsal-toaster' version='${project.version}'>
+        <feature version='${yangtools.version}'>yangtools-concepts</feature>
+        <feature version='${yangtools.version}'>yangtools-binding</feature>
+        <feature version='${project.version}'>odl-mdsal-broker</feature>
+        <feature version='${project.version}'>odl-mdsal-all</feature>
+        <bundle>mvn:org.opendaylight.controller.samples/sample-toaster/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.samples/sample-toaster-consumer/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.samples/sample-toaster-provider/${project.version}</bundle>
+    </feature>
+    <feature name='odl-mdsal-misc' version='${project.version}'>
+        <bundle>mvn:org.opendaylight.controller/sal-netconf-connector/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/sal-restconf-broker/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/sal-remote/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/topology-manager/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/topology-lldp-discovery/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/statistics-manager/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/inventory-manager/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller.md/forwardingrules-manager/${project.version}</bundle>
+    </feature>
+
 </features>
diff --git a/features/netconf/pom.xml b/features/netconf/pom.xml
new file mode 100644 (file)
index 0000000..457fc64
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>netconf-subsystem</artifactId>
+    <version>0.2.5-SNAPSHOT</version>
+    <relativePath>../../opendaylight/netconf</relativePath>
+  </parent>
+  <artifactId>netconf-features</artifactId>
+
+  <packaging>pom</packaging>
+
+  <properties>
+    <features.file>features.xml</features.file>
+  </properties>
+
+  <dependencies></dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <filtering>true</filtering>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>filter</id>
+            <goals>
+              <goal>resources</goal>
+            </goals>
+            <phase>generate-resources</phase>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/${features.file}</file>
+                  <type>xml</type>
+                  <classifier>features</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+  </scm>
+</project>
diff --git a/features/netconf/src/main/resources/features.xml b/features/netconf/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..50a537b
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<features name="odl-netconf-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.controller/features-odl-protocol-framework/${protocol-framework.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/config-features/${config.version}/xml/features</repository>
+
+  <feature name='odl-netconf-api' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netconf-api/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring-extension/${project.version}</bundle>
+    <feature version='${protocol-framework.version}'>odl-protocol-framework</feature>
+    <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf-inet-types.version}</bundle>
+    <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf-yang-types.version}</bundle>
+  </feature>
+  <feature name='odl-netconf-mapping-api' version='${project.version}'>
+    <feature version='${project.version}'>odl-netconf-api</feature>
+    <bundle>mvn:org.opendaylight.controller/netconf-mapping-api/${project.version}</bundle>
+  </feature>
+  <feature name='odl-netconf-util' version='${project.version}'>
+    <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+    <bundle>mvn:org.opendaylight.controller/netconf-util/${project.version}</bundle>
+  </feature>
+  <feature name='odl-config-netconf-connector' version='${project.version}'>
+    <feature version='${config.version}'>odl-config-manager</feature>
+    <bundle>mvn:org.opendaylight.controller/config-netconf-connector/${project.version}</bundle>
+    <feature version='${project.version}'>odl-netconf-api</feature>
+    <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+    <feature version='${project.version}'>odl-netconf-util</feature>
+  </feature>
+
+  <feature name='odl-netconf-impl' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netconf-impl/${project.version}</bundle>
+    <feature version='${project.version}'>odl-netconf-api</feature>
+    <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+    <feature version='${project.version}'>odl-netconf-util</feature>
+    <feature version='${project.version}'>odl-netconf-netty-util</feature>
+  </feature>
+  <feature name='odl-netconf-netty-util' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netconf-netty-util/${project.version}</bundle>
+    <feature version='${project.version}'>odl-netconf-api</feature>
+    <feature version='${project.version}'>odl-netconf-mapping-api</feature>
+    <feature version='${project.version}'>odl-netconf-util</feature>
+    <bundle>mvn:org.opendaylight.controller.thirdparty/ganymed/${ganymed.version}</bundle>
+    <bundle>mvn:org.openexi/nagasena/${exi.nagasena.version}</bundle>
+    <bundle>mvn:io.netty/netty-codec/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-handler/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-common/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-buffer/${netty.version}</bundle>
+    <bundle>mvn:io.netty/netty-transport/${netty.version}</bundle>
+  </feature>
+  <feature name='odl-netconf-misc' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/netconf-client/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netconf-monitoring/${project.version}</bundle>
+    <bundle>mvn:org.opendaylight.controller/netconf-tcp/${project.version}</bundle>
+  </feature>
+
+</features>
\ No newline at end of file
diff --git a/features/pom.xml b/features/pom.xml
new file mode 100644 (file)
index 0000000..dce47fa
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../opendaylight/commons/opendaylight</relativePath>
+  </parent>
+  <artifactId>features-controller</artifactId>
+  <packaging>pom</packaging>
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+  <modules>
+    <module>config</module>
+    <module>mdsal</module>
+    <module>netconf</module>
+    <module>protocol-framework</module>
+  </modules>
+</project>
diff --git a/features/protocol-framework/pom.xml b/features/protocol-framework/pom.xml
new file mode 100644 (file)
index 0000000..f0208d6
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+    <relativePath>../../opendaylight/commons/opendaylight</relativePath>
+  </parent>
+  <artifactId>features-odl-protocol-framework</artifactId>
+  <version>${protocol-framework.version}</version>
+  <packaging>pom</packaging>
+
+  <properties>
+    <features.file>features.xml</features.file>
+  </properties>
+
+  <dependencies></dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <filtering>true</filtering>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>filter</id>
+            <goals>
+              <goal>resources</goal>
+            </goals>
+            <phase>generate-resources</phase>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/${features.file}</file>
+                  <type>xml</type>
+                  <classifier>features</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+  </scm>
+</project>
diff --git a/features/protocol-framework/src/main/resources/features.xml b/features/protocol-framework/src/main/resources/features.xml
new file mode 100644 (file)
index 0000000..d2560f5
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<features name="odl-protocol-framework-${protocol-framework.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.controller/config-features/${config.version}/xml/features</repository>
+  <feature name='odl-protocol-framework' version='${project.version}'>
+    <bundle>mvn:org.opendaylight.controller/protocol-framework/${protocol-framework.version}</bundle>
+    <feature version='${config.version}'>odl-config-api</feature> <!-- needed by netty-config-api -->
+    <feature version='${config.version}'>odl-config-netty-config-api</feature> <!-- needed by netty-config-api -->
+  </feature>
+</features>
\ No newline at end of file
index dbe0745..cec780c 100644 (file)
@@ -69,9 +69,10 @@ public class Context {
         initialized = true;
     }
 
-    public List<Filter> findMatchingFilters(String pathInfo) {
+    public List<Filter> findMatchingFilters(String path) {
+        logger.trace("findMatchingFilters({})", path);
         checkState(initialized, "Not initialized");
-        return urlMatcher.findMatchingFilters(pathInfo);
+        return urlMatcher.findMatchingFilters(path);
     }
 
     @XmlAttribute(name = "path")
index dc3e9dc..ae9d79a 100644 (file)
@@ -37,14 +37,14 @@ public class FilterProcessor {
             throws IOException, ServletException {
 
         String contextPath = request.getContext().getPath();
-        String pathInfo = request.getPathInfo();
+        String path = request.getDecodedRequestURI();
 
         Optional<Context> maybeContext = host.findContext(contextPath);
-        logger.trace("Processing context {} path {}, found {}", contextPath, pathInfo, maybeContext);
+        logger.trace("Processing context {} path {}, found {}", contextPath, path, maybeContext);
         if (maybeContext.isPresent()) {
             // process filters
             Context context = maybeContext.get();
-            List<Filter> matchingFilters = context.findMatchingFilters(pathInfo);
+            List<Filter> matchingFilters = context.findMatchingFilters(path);
             FilterChain fromLast = nextValveFilterChain;
             ListIterator<Filter> it = matchingFilters.listIterator(matchingFilters.size());
             final boolean trace = logger.isTraceEnabled();
index 9535fb1..210326f 100644 (file)
@@ -62,31 +62,31 @@ public class UrlMatcher<FILTER> {
     /**
      * Find filters matching path
      *
-     * @param pathInfo as returned by request.getPathInfo()
+     * @param path relative and decoded path to resource
      * @return list of matching filters
      */
-    public List<FILTER> findMatchingFilters(String pathInfo) {
-        checkNotNull(pathInfo);
+    public List<FILTER> findMatchingFilters(String path) {
+        checkNotNull(path);
         TreeMap<Integer, FILTER> sortedMap = new TreeMap<>();
         // add matching prefixes
         for (Entry<String, Entry<FILTER, Integer>> prefixEntry : prefixMap.entrySet()) {
-            if (pathInfo.startsWith(prefixEntry.getKey())) {
+            if (path.startsWith(prefixEntry.getKey())) {
                 put(sortedMap, prefixEntry.getValue());
             }
         }
         // add matching suffixes
         for (Entry<String, Entry<FILTER, Integer>> suffixEntry : suffixMap.entrySet()) {
-            if (pathInfo.endsWith(suffixEntry.getKey())) {
+            if (path.endsWith(suffixEntry.getKey())) {
                 put(sortedMap, suffixEntry.getValue());
             }
         }
         // add exact match
-        Entry<FILTER, Integer> exactMatch = exactMatchMap.get(pathInfo);
+        Entry<FILTER, Integer> exactMatch = exactMatchMap.get(path);
         if (exactMatch != null) {
             put(sortedMap, exactMatch);
         }
         ArrayList<FILTER> filters = new ArrayList<>(sortedMap.values());
-        logger.trace("Matching filters for path {} are {}", pathInfo, filters);
+        logger.trace("Matching filters for path {} are {}", path, filters);
         return filters;
     }
 
index 28c23c8..163c64e 100644 (file)
@@ -91,6 +91,7 @@
     <forwarding.staticrouting.northbound.version>0.4.2-SNAPSHOT</forwarding.staticrouting.northbound.version>
     <forwardingrulesmanager.implementation.version>0.4.2-SNAPSHOT</forwardingrulesmanager.implementation.version>
     <forwardingrulesmanager.version>0.6.0-SNAPSHOT</forwardingrulesmanager.version>
+    <ganymed.version>1.1-SNAPSHOT</ganymed.version>
     <hosttracker.api.version>0.5.2-SNAPSHOT</hosttracker.api.version>
     <hosttracker.implementation.version>0.5.2-SNAPSHOT</hosttracker.implementation.version>
     <hosttracker.northbound.version>0.4.2-SNAPSHOT</hosttracker.northbound.version>
       <dependency>
         <groupId>org.opendaylight.controller.thirdparty</groupId>
         <artifactId>ganymed</artifactId>
-        <version>1.1-SNAPSHOT</version>
+        <version>${ganymed.version}</version>
       </dependency>
       <!-- Third parties from opendaylight released -->
       <dependency>
diff --git a/opendaylight/config/feature/src/main/resources/features.xml b/opendaylight/config/feature/src/main/resources/features.xml
deleted file mode 100644 (file)
index a84a743..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<features name="config-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
-  <feature name='config-all' version='${project.version}'>
-    <feature version='${project.version}'>odl-config-subsystem</feature>
-  </feature>
-
-  <feature name='odl-config-subsystem' version='${project.version}'>
-    <feature version='${yangtools.version}'>yangtools-concepts</feature>
-    <feature version='${yangtools.version}'>yangtools-binding</feature>
-    <feature version='${yangtools.version}'>yangtools-binding-generator</feature>
-    <feature version='${mdsal.version}'>odl-mdsal-commons</feature>
-    <bundle>mvn:org.opendaylight.controller/config-api/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-util/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-manager/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/yang-jmx-generator/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-persister-api/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-persister-file-xml-adapter/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/config-persister-directory-xml-adapter/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/shutdown-api/${project.version}</bundle>
-    <bundle>mvn:org.opendaylight.controller/shutdown-impl/${project.version}</bundle>
-    <bundle>mvn:org.osgi/org.osgi.core/${osgi.core.version}</bundle>
-    <bundle>wrap:mvn:com.google.guava/guava/${guava.version}</bundle>
-    <bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
-  </feature>
-</features>
\ No newline at end of file
index a8a4c87..66bb01f 100644 (file)
@@ -39,7 +39,6 @@
     <module>shutdown-impl</module>
     <module>netconf-config-dispatcher</module>
     <module>config-module-archetype</module>
-    <module>feature</module>
   </modules>
 
   <dependencies>
index 3dfa6e2..5036399 100644 (file)
@@ -10,15 +10,20 @@ package org.opendaylight.controller.config.threadpool.util;
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.RejectedExecutionHandler;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 
+import com.google.common.base.Optional;
+
 /**
  * Implementation of {@link ThreadPool} using flexible number of threads wraps
  * {@link ExecutorService}.
@@ -28,12 +33,33 @@ public class FlexibleThreadPoolWrapper implements ThreadPool, Closeable {
 
     public FlexibleThreadPoolWrapper(int minThreadCount, int maxThreadCount, long keepAlive, TimeUnit timeUnit,
             ThreadFactory threadFactory) {
+        this(minThreadCount, maxThreadCount, keepAlive, timeUnit, threadFactory, getQueue(Optional.<Integer>absent()));
+    }
+
+    public FlexibleThreadPoolWrapper(int minThreadCount, int maxThreadCount, long keepAlive, TimeUnit timeUnit,
+            ThreadFactory threadFactory, Optional<Integer> queueCapacity) {
+        this(minThreadCount, maxThreadCount, keepAlive, timeUnit, threadFactory, getQueue(queueCapacity));
+    }
+
+    private FlexibleThreadPoolWrapper(int minThreadCount, int maxThreadCount, long keepAlive, TimeUnit timeUnit,
+            ThreadFactory threadFactory, BlockingQueue<Runnable> queue) {
 
         executor = new ThreadPoolExecutor(minThreadCount, maxThreadCount, keepAlive, timeUnit,
-                new SynchronousQueue<Runnable>(), threadFactory);
+                queue, threadFactory, new FlexibleRejectionHandler());
         executor.prestartAllCoreThreads();
     }
 
+    /**
+     * 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.
+     */
+    private static ForwardingBlockingQueue getQueue(Optional<Integer> capacity) {
+        final BlockingQueue<Runnable> delegate = capacity.isPresent() ? new LinkedBlockingQueue<Runnable>(capacity.get()) : new LinkedBlockingQueue<Runnable>();
+        return new ForwardingBlockingQueue(delegate);
+    }
+
     @Override
     public ExecutorService getExecutor() {
         return Executors.unconfigurableExecutorService(executor);
@@ -77,4 +103,37 @@ public class FlexibleThreadPoolWrapper implements ThreadPool, Closeable {
         executor.shutdown();
     }
 
+    /**
+     * if the max threads are met, then it will raise a rejectedExecution. We then push to the queue.
+     */
+    private static class FlexibleRejectionHandler implements RejectedExecutionHandler {
+        @Override
+        public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) {
+            try {
+                executor.getQueue().put(r);
+            } catch (InterruptedException e) {
+                throw new RejectedExecutionException("Interrupted while waiting on the queue", e);
+            }
+        }
+    }
+
+    private static class ForwardingBlockingQueue extends com.google.common.util.concurrent.ForwardingBlockingQueue<Runnable> {
+        private final BlockingQueue<Runnable> delegate;
+
+        public ForwardingBlockingQueue(BlockingQueue<Runnable> delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        protected BlockingQueue<Runnable> delegate() {
+            return delegate;
+        }
+
+        @Override
+        public boolean offer(final Runnable r) {
+            // ThreadPoolExecutor will spawn a new thread after core size is reached only
+            // if the queue.offer returns false.
+            return false;
+        }
+    }
 }
index 94639d4..d6abe16 100644 (file)
@@ -17,6 +17,7 @@
 */
 package org.opendaylight.controller.config.yang.threadpool.impl.flexible;
 
+import com.google.common.base.Optional;
 import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
@@ -50,11 +51,15 @@ public final class FlexibleThreadPoolModule extends org.opendaylight.controller.
         JmxAttributeValidationException.checkNotNull(getMaxThreadCount(), maxThreadCountJmxAttribute);
         JmxAttributeValidationException.checkCondition(getMaxThreadCount() > 0, "must be greater than zero",
                 maxThreadCountJmxAttribute);
+
+        if(getQueueCapacity() != null) {
+            JmxAttributeValidationException.checkCondition(getQueueCapacity() > 0, "Queue capacity cannot be < 1", queueCapacityJmxAttribute);
+        }
     }
 
     @Override
     public java.lang.AutoCloseable createInstance() {
         return new FlexibleThreadPoolWrapper(getMinThreadCount(), getMaxThreadCount(), getKeepAliveMillis(),
-                TimeUnit.MILLISECONDS, getThreadFactoryDependency());
+                TimeUnit.MILLISECONDS, getThreadFactoryDependency(), Optional.fromNullable(getQueueCapacity()));
     }
 }
index be275ef..c124f63 100644 (file)
@@ -46,6 +46,12 @@ module threadpool-impl-flexible {
                 type uint32;
             }
 
+            leaf queueCapacity {
+                type uint16;
+                mandatory false;
+                description "Capacity of queue that holds waiting tasks";
+            }
+
             container threadFactory {
                 uses config:service-ref {
                     refine type {
index 221bfa7..4ef0b8e 100644 (file)
       <type>kar</type>
       <scope>runtime</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-odl-protocol-framework</artifactId>
+      <version>${protocol-framework.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>netconf-features</artifactId>
+      <version>${netconf.version}</version>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>config-features</artifactId>
       <type>xml</type>
       <scope>runtime</scope>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>features-yangtools</artifactId>
-      <version>${yangtools.version}</version>
-      <classifier>features</classifier>
-      <type>xml</type>
-      <scope>runtime</scope>
-    </dependency>
   </dependencies>
 
   <build>
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
deleted file mode 100644 (file)
index 7853b86..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<snapshot>
-    <configuration>
-        <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                <module>
-                   <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">prefix:remote-zeromq-rpc-server</type>
-                   <name>remoter</name>
-                   <port xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">5666</port>
-                   <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc">
-                       <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</type>
-                       <name>dom-broker</name>
-                   </dom-broker>
-               </module>
-            </modules>
-            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-            </services>
-        </data>
-    </configuration>
-
-    <required-capabilities>
-       <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28</capability>
-        <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote:rpc?module=odl-sal-dom-rpc-remote-cfg&amp;revision=2013-10-28</capability>
-    </required-capabilities>
-</snapshot>
-
index 8fedbe4..f81a332 100644 (file)
@@ -12,7 +12,7 @@
     <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
 
-        <!-- Netconf dispatcher to be used by all netconf-connectors --> 
+        <!-- Netconf dispatcher to be used by all netconf-connectors -->
         <module>
           <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher">prefix:netconf-client-dispatcher</type>
           <name>global-netconf-dispatcher</name>
           </timer>
         </module>
 
-        <!-- Thread factory to be used by all threadpools in netconf-connectors --> 
+        <!-- Thread factory to be used by all threadpools in netconf-connectors -->
         <module>
           <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">prefix:threadfactory-naming</type>
           <name>global-netconf-processing-executor-threadfactory</name>
           <name-prefix xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">remote-connector-processing-executor</name-prefix>
-        </module> 
-        <!-- Flexible threadpool for all netconf connectors, Max thread count is set to 4 --> 
+        </module>
+        <!-- flexible threadpool for all netconf connectors, Max thread count is set to 4.  -->
         <module>
           <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">prefix:threadpool-flexible</type>
           <name>global-netconf-processing-executor</name>
           <minThreadCount xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">1</minThreadCount>
           <max-thread-count xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">4</max-thread-count>
           <keepAliveMillis xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">600000</keepAliveMillis>
+
           <threadFactory xmlns="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible">
             <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool">prefix:threadfactory</type>
             <name>global-netconf-processing-executor-threadfactory</name>
           </threadFactory>
-        </module>  
+        </module>
       </modules>
 
       <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
index d3f6d2d..1cfd5a6 100644 (file)
@@ -63,9 +63,6 @@
     <!--sal-protocolbuffer-encoding-->
     <module>sal-protocolbuffer-encoding</module>
 
-    <!--  Karaf feature -->
-    <module>feature</module>
-
     <!-- Yang Test Models for MD-SAL -->
     <module>sal-test-model</module>
   </modules>
index 3ed02df..01a5989 100644 (file)
@@ -1,14 +1,17 @@
 package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
 
-import com.google.common.util.concurrent.MoreExecutors;
+import java.util.concurrent.Executors;
+
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 
+import com.google.common.util.concurrent.MoreExecutors;
+
 public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryConfigDataStoreProviderModule {
-    public InMemoryConfigDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+    public InMemoryConfigDataStoreProviderModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
-    public InMemoryConfigDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.inmemory_datastore_provider.InMemoryConfigDataStoreProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+    public InMemoryConfigDataStoreProviderModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final org.opendaylight.controller.config.yang.inmemory_datastore_provider.InMemoryConfigDataStoreProviderModule oldModule, final java.lang.AutoCloseable oldInstance) {
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
 
@@ -19,7 +22,7 @@ public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.cont
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-      InMemoryDOMDataStore   ids = new InMemoryDOMDataStore("DOM-CFG", MoreExecutors.sameThreadExecutor());
+      InMemoryDOMDataStore   ids = new InMemoryDOMDataStore("DOM-CFG", MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
       getSchemaServiceDependency().registerSchemaServiceListener(ids);
       return ids;
     }
index eea9599..172b0db 100644 (file)
@@ -1,14 +1,17 @@
 package org.opendaylight.controller.config.yang.inmemory_datastore_provider;
 
-import com.google.common.util.concurrent.MoreExecutors;
+import java.util.concurrent.Executors;
+
 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
 
+import com.google.common.util.concurrent.MoreExecutors;
+
 public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight.controller.config.yang.inmemory_datastore_provider.AbstractInMemoryOperationalDataStoreProviderModule {
-    public InMemoryOperationalDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+    public InMemoryOperationalDataStoreProviderModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
-    public InMemoryOperationalDataStoreProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.inmemory_datastore_provider.InMemoryOperationalDataStoreProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+    public InMemoryOperationalDataStoreProviderModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final org.opendaylight.controller.config.yang.inmemory_datastore_provider.InMemoryOperationalDataStoreProviderModule oldModule, final java.lang.AutoCloseable oldInstance) {
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
 
@@ -19,7 +22,7 @@ public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-      InMemoryDOMDataStore ids = new InMemoryDOMDataStore("DOM-OPER", MoreExecutors.sameThreadExecutor());
+      InMemoryDOMDataStore ids = new InMemoryDOMDataStore("DOM-OPER", MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
       getSchemaServiceDependency().registerSchemaServiceListener(ids);
       return ids;
     }
index dca8fca..de4ac7a 100644 (file)
@@ -7,15 +7,19 @@
  */
 package org.opendaylight.controller.sal.connect.netconf;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.concurrent.ExecutorService;
-
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.controller.sal.connect.api.MessageTransformer;
 import org.opendaylight.controller.sal.connect.api.RemoteDevice;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
@@ -36,9 +40,6 @@ import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-
 /**
  *  This is a mediator between NetconfDeviceCommunicator and NetconfDeviceSalFacade
  */
@@ -53,6 +54,7 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionCapabilit
     private final MessageTransformer<NetconfMessage> messageTransformer;
     private final SchemaContextProviderFactory schemaContextProviderFactory;
     private final SchemaSourceProviderFactory<InputStream> sourceProviderFactory;
+    private final NotificationHandler notificationHandler;
 
     public static NetconfDevice createNetconfDevice(final RemoteDeviceId id,
             final AbstractCachingSchemaSourceProvider<String, InputStream> schemaSourceProvider,
@@ -79,6 +81,7 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionCapabilit
         this.sourceProviderFactory = sourceProviderFactory;
         this.processingExecutor = MoreExecutors.listeningDecorator(processingExecutor);
         this.schemaContextProviderFactory = schemaContextProviderFactory;
+        this.notificationHandler = new NotificationHandler(salFacade, messageTransformer, id);
     }
 
     @Override
@@ -99,6 +102,7 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionCapabilit
                 final SchemaContextProvider schemaContextProvider = setUpSchemaContext(delegate, remoteSessionCapabilities);
                 updateMessageTransformer(schemaContextProvider);
                 salFacade.onDeviceConnected(schemaContextProvider, remoteSessionCapabilities, deviceRpc);
+                notificationHandler.onRemoteSchemaUp();
             }
         });
 
@@ -142,7 +146,63 @@ public final class NetconfDevice implements RemoteDevice<NetconfSessionCapabilit
 
     @Override
     public void onNotification(final NetconfMessage notification) {
-        final CompositeNode parsedNotification = messageTransformer.toNotification(notification);
-        salFacade.onNotification(parsedNotification);
+        notificationHandler.handleNotification(notification);
+    }
+
+    /**
+     * Handles incoming notifications. Either caches them(until onRemoteSchemaUp is called) or passes to sal Facade.
+     */
+    private final static class NotificationHandler {
+
+        private final RemoteDeviceHandler<?> salFacade;
+        private final List<NetconfMessage> cache = new LinkedList<>();
+        private final MessageTransformer<NetconfMessage> messageTransformer;
+        private boolean passNotifications = false;
+        private final RemoteDeviceId id;
+
+        NotificationHandler(final RemoteDeviceHandler<?> salFacade, final MessageTransformer<NetconfMessage> messageTransformer, final RemoteDeviceId id) {
+            this.salFacade = salFacade;
+            this.messageTransformer = messageTransformer;
+            this.id = id;
+        }
+
+        synchronized void handleNotification(final NetconfMessage notification) {
+            if(passNotifications) {
+                passNotification(messageTransformer.toNotification(notification));
+            } else {
+                cacheNotification(notification);
+            }
+        }
+
+        /**
+         * Forward all cached notifications and pass all notifications from this point directly to sal facade.
+         */
+        synchronized void onRemoteSchemaUp() {
+            passNotifications = true;
+
+            for (final NetconfMessage cachedNotification : cache) {
+                passNotification(messageTransformer.toNotification(cachedNotification));
+            }
+
+            cache.clear();
+        }
+
+        private void cacheNotification(final NetconfMessage notification) {
+            Preconditions.checkState(passNotifications == false);
+
+            logger.debug("{}: Caching notification {}, remote schema not yet fully built", id, notification);
+            if(logger.isTraceEnabled()) {
+                logger.trace("{}: Caching notification {}", id, XmlUtil.toString(notification.getDocument()));
+            }
+
+            cache.add(notification);
+        }
+
+        private void passNotification(final CompositeNode parsedNotification) {
+            logger.debug("{}: Forwarding notification {}", id, parsedNotification);
+            Preconditions.checkNotNull(parsedNotification);
+            salFacade.onNotification(parsedNotification);
+        }
+
     }
 }
index 0ef76d3..960f2ef 100644 (file)
@@ -44,6 +44,7 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
@@ -90,16 +91,14 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
     }
 
     private void sendMerge(final InstanceIdentifier key, final CompositeNode value) throws InterruptedException, ExecutionException {
-        sendEditRpc(createEditConfigStructure(key, Optional.<String>absent(), Optional.of(value)), Optional.<String>absent());
+        sendEditRpc(createEditConfigStructure(key, Optional.<ModifyAction>absent(), Optional.of(value)), Optional.<ModifyAction>absent());
     }
 
     private void sendDelete(final InstanceIdentifier toDelete) throws InterruptedException, ExecutionException {
-        // FIXME use org.opendaylight.yangtools.yang.data.api.ModifyAction instead of strings
-        // TODO add string lowercase value to ModifyAction enum entries
-        sendEditRpc(createEditConfigStructure(toDelete, Optional.of("delete"), Optional.<CompositeNode>absent()), Optional.of("none"));
+        sendEditRpc(createEditConfigStructure(toDelete, Optional.of(ModifyAction.DELETE), Optional.<CompositeNode>absent()), Optional.of(ModifyAction.NONE));
     }
 
-    private void sendEditRpc(final CompositeNode editStructure, final Optional<String> defaultOperation) throws InterruptedException, ExecutionException {
+    private void sendEditRpc(final CompositeNode editStructure, final Optional<ModifyAction> defaultOperation) throws InterruptedException, ExecutionException {
         final ImmutableCompositeNode editConfigRequest = createEditConfigRequest(editStructure, defaultOperation);
         final RpcResult<CompositeNode> rpcResult = rpc.invokeRpc(NETCONF_EDIT_CONFIG_QNAME, editConfigRequest).get();
 
@@ -110,7 +109,7 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
         }
     }
 
-    private ImmutableCompositeNode createEditConfigRequest(final CompositeNode editStructure, final Optional<String> defaultOperation) {
+    private ImmutableCompositeNode createEditConfigRequest(final CompositeNode editStructure, final Optional<ModifyAction> defaultOperation) {
         final CompositeNodeBuilder<ImmutableCompositeNode> ret = ImmutableCompositeNode.builder();
 
         // Target
@@ -119,7 +118,7 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
 
         // Default operation
         if(defaultOperation.isPresent()) {
-            SimpleNode<String> defOp = NodeFactory.createImmutableSimpleNode(NETCONF_DEFAULT_OPERATION_QNAME, null, defaultOperation.get());
+            final SimpleNode<String> defOp = NodeFactory.createImmutableSimpleNode(NETCONF_DEFAULT_OPERATION_QNAME, null, modifyOperationToXmlString(defaultOperation.get()));
             ret.add(defOp);
         }
 
@@ -134,7 +133,7 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
         return ret.toInstance();
     }
 
-    private CompositeNode createEditConfigStructure(final InstanceIdentifier dataPath, final Optional<String> operation,
+    private CompositeNode createEditConfigStructure(final InstanceIdentifier dataPath, final Optional<ModifyAction> operation,
             final Optional<CompositeNode> lastChildOverride) {
         Preconditions.checkArgument(Iterables.isEmpty(dataPath.getPathArguments()) == false, "Instance identifier with empty path %s", dataPath);
 
@@ -174,7 +173,7 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
         return predicates;
     }
 
-    private CompositeNode getDeepestEditElement(final PathArgument arg, final Optional<String> operation, final Optional<CompositeNode> lastChildOverride) {
+    private CompositeNode getDeepestEditElement(final PathArgument arg, final Optional<ModifyAction> operation, final Optional<CompositeNode> lastChildOverride) {
         final CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
         builder.setQName(arg.getNodeType());
 
@@ -182,7 +181,7 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
         addPredicatesToCompositeNodeBuilder(predicates, builder);
 
         if (operation.isPresent()) {
-            builder.setAttribute(NETCONF_OPERATION_QNAME, operation.get());
+            builder.setAttribute(NETCONF_OPERATION_QNAME, modifyOperationToXmlString(operation.get()));
         }
         if (lastChildOverride.isPresent()) {
             final List<Node<?>> children = lastChildOverride.get().getValue();
@@ -196,6 +195,10 @@ final class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransact
         return builder.toInstance();
     }
 
+    private String modifyOperationToXmlString(final ModifyAction operation) {
+        return operation.name().toLowerCase();
+    }
+
     /**
      * Send commit rpc to finish the transaction
      * In case of failure or unexpected error response, ExecutionException is thrown
index ec2a820..defaab6 100644 (file)
@@ -12,6 +12,7 @@ import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import java.io.InputStream;
@@ -82,6 +83,32 @@ public class NetconfDeviceTest {
         Mockito.verify(facade, Mockito.timeout(5000)).onDeviceDisconnected();
     }
 
+    @Test
+    public void testNotificationBeforeSchema() throws Exception {
+        final RemoteDeviceHandler<NetconfSessionCapabilities> facade = getFacade();
+        final RemoteDeviceCommunicator<NetconfMessage> listener = getListener();
+
+        final MessageTransformer<NetconfMessage> messageTransformer = getMessageTransformer();
+        final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), messageTransformer, getSchemaContextProviderFactory(), getSourceProviderFactory());
+
+        device.onNotification(netconfMessage);
+        device.onNotification(netconfMessage);
+
+        verify(facade, times(0)).onNotification(any(CompositeNode.class));
+
+        final NetconfSessionCapabilities sessionCaps = getSessionCaps(true,
+                Lists.newArrayList(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&amp;revision=" + TEST_REVISION));
+
+        device.onRemoteSessionUp(sessionCaps, listener);
+
+        verify(messageTransformer, timeout(10000).times(2)).toNotification(netconfMessage);
+        verify(facade, times(2)).onNotification(compositeNode);
+
+        device.onNotification(netconfMessage);
+        verify(messageTransformer, times(3)).toNotification(netconfMessage);
+        verify(facade, times(3)).onNotification(compositeNode);
+    }
+
     @Test
     public void testNetconfDeviceReconnect() throws Exception {
         final RemoteDeviceHandler<NetconfSessionCapabilities> facade = getFacade();
@@ -136,6 +163,7 @@ public class NetconfDeviceTest {
         final RemoteDeviceHandler<NetconfSessionCapabilities> remoteDeviceHandler = mockCloseableClass(RemoteDeviceHandler.class);
         doNothing().when(remoteDeviceHandler).onDeviceConnected(any(SchemaContextProvider.class), any(NetconfSessionCapabilities.class), any(RpcImplementation.class));
         doNothing().when(remoteDeviceHandler).onDeviceDisconnected();
+        doNothing().when(remoteDeviceHandler).onNotification(any(CompositeNode.class));
         return remoteDeviceHandler;
     }
 
@@ -173,6 +201,7 @@ public class NetconfDeviceTest {
         final MessageTransformer<NetconfMessage> messageTransformer = mockClass(MessageTransformer.class);
         doReturn(netconfMessage).when(messageTransformer).toRpcRequest(any(QName.class), any(CompositeNode.class));
         doReturn(rpcResultC).when(messageTransformer).toRpcResult(any(NetconfMessage.class), any(QName.class));
+        doReturn(compositeNode).when(messageTransformer).toNotification(any(NetconfMessage.class));
         doNothing().when(messageTransformer).onGlobalContextUpdated(any(SchemaContext.class));
         return messageTransformer;
     }
@@ -197,4 +226,4 @@ public class NetconfDeviceTest {
         doReturn(Futures.immediateFuture(rpcResult)).when(remoteDeviceCommunicator).sendRequest(any(NetconfMessage.class), any(QName.class));
         return remoteDeviceCommunicator;
     }
-}
\ No newline at end of file
+}
index af61db1..b1db280 100644 (file)
@@ -95,6 +95,8 @@ final class FlowComparator {
         if (statsFlow == storedFlow) {
             return true;
         }
+        if (storedFlow == null && statsFlow != null) return false;
+        if (statsFlow == null && storedFlow != null) return false;
         if (storedFlow.getClass() != statsFlow.getClass()) {
             return false;
         }
index 1360a54..de3f732 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.nettyutil;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
@@ -104,7 +105,7 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
 
     private void start() {
         final NetconfMessage helloMessage = this.sessionPreferences.getHelloMessage();
-        logger.debug("Session negotiation started with hello message {}", XmlUtil.toString(helloMessage.getDocument()));
+        logger.debug("Session negotiation started with hello message {} on channel {}", XmlUtil.toString(helloMessage.getDocument()), channel);
 
         channel.pipeline().addLast(NAME_OF_EXCEPTION_HANDLER, new ExceptionHandlingInboundChannelHandler());
 
@@ -125,12 +126,20 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
                         // Do not fail negotiation if promise is done or canceled
                         // It would result in setting result of the promise second time and that throws exception
                         if (isPromiseFinished() == false) {
-                            // FIXME BUG-1365 calling "negotiation failed" closes the channel, but the channel does not get closed if data is still being transferred
-                            // Loopback connection initiation might
                             negotiationFailed(new IllegalStateException("Session was not established after " + timeout));
+                            changeState(State.FAILED);
+
+                            channel.closeFuture().addListener(new GenericFutureListener<ChannelFuture>() {
+                                @Override
+                                public void operationComplete(ChannelFuture future) throws Exception {
+                                    if(future.isSuccess()) {
+                                        logger.debug("Channel {} closed: success", future.channel());
+                                    } else {
+                                        logger.warn("Channel {} closed: fail", future.channel());
+                                    }
+                                }
+                            });
                         }
-
-                        changeState(State.FAILED);
                     } else if(channel.isOpen()) {
                         channel.pipeline().remove(NAME_OF_EXCEPTION_HANDLER);
                     }
@@ -214,9 +223,9 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
     protected abstract S getSession(L sessionListener, Channel channel, NetconfHelloMessage message) throws NetconfDocumentedException;
 
     private synchronized void changeState(final State newState) {
-        logger.debug("Changing state from : {} to : {}", state, newState);
-        Preconditions.checkState(isStateChangePermitted(state, newState), "Cannot change state from %s to %s", state,
-                newState);
+        logger.debug("Changing state from : {} to : {} for channel: {}", state, newState, channel);
+        Preconditions.checkState(isStateChangePermitted(state, newState), "Cannot change state from %s to %s for chanel %s", state,
+                newState, channel);
         this.state = newState;
     }
 
index f260bcb..a87a08d 100644 (file)
@@ -9,56 +9,15 @@
 package org.opendaylight.controller.netconf.nettyutil.handler;
 
 import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ByteToMessageDecoder;
-
-import java.util.List;
-
+import io.netty.buffer.Unpooled;
+import io.netty.handler.codec.DelimiterBasedFrameDecoder;
 import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Charsets;
+public class NetconfEOMAggregator extends DelimiterBasedFrameDecoder {
 
-public class NetconfEOMAggregator extends ByteToMessageDecoder {
-    private final static Logger logger = LoggerFactory.getLogger(NetconfEOMAggregator.class);
+    public static final ByteBuf DELIMITER = Unpooled.wrappedBuffer(NetconfMessageConstants.END_OF_MESSAGE);
 
-    @Override
-    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
-        int index = indexOfSequence(in, NetconfMessageConstants.END_OF_MESSAGE);
-        if (index == -1) {
-            logger.debug("Message is not complete, read again.");
-            if (logger.isTraceEnabled()) {
-                String str = in.toString(Charsets.UTF_8);
-                logger.trace("Message read so far: {}", str);
-            }
-            ctx.read();
-        } else {
-            ByteBuf msg = in.readBytes(index);
-            in.readBytes(NetconfMessageConstants.END_OF_MESSAGE.length);
-            in.discardReadBytes();
-            logger.debug("Message is complete.");
-            out.add(msg);
-        }
+    public NetconfEOMAggregator() {
+        super(Integer.MAX_VALUE, DELIMITER);
     }
-
-    private int indexOfSequence(ByteBuf in, byte[] sequence) {
-        int index = -1;
-        for (int i = 0; i < in.readableBytes() - sequence.length + 1; i++) {
-            if (in.getByte(i) == sequence[0]) {
-                index = i;
-                for (int j = 1; j < sequence.length; j++) {
-                    if (in.getByte(i + j) != sequence[j]) {
-                        index = -1;
-                        break;
-                    }
-                }
-                if (index != -1) {
-                    return index;
-                }
-            }
-        }
-        return index;
-    }
-
 }
index fae2000..d810a87 100644 (file)
@@ -12,6 +12,7 @@ import io.netty.buffer.ByteBufOutputStream;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToByteEncoder;
 
+import java.io.BufferedWriter;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
@@ -61,7 +62,8 @@ public class NetconfMessageToXMLEncoder extends MessageToByteEncoder<NetconfMess
             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
             transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
 
-            StreamResult result = new StreamResult(new OutputStreamWriter(os));
+            // Wrap OutputStreamWriter with BufferedWriter as suggested in javadoc for OutputStreamWriter
+            StreamResult result = new StreamResult(new BufferedWriter(new OutputStreamWriter(os)));
             DOMSource source = new DOMSource(msg.getDocument());
             transformer.transform(source, result);
         }
diff --git a/pom.xml b/pom.xml
index af84002..242ab8e 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <module>opendaylight/dummy-console</module>
     <module>opendaylight/karaf-branding</module>
     <module>opendaylight/distribution/opendaylight-karaf</module>
+    <module>features</module>
   </modules>
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.