Merge "fix of Bug 149"
authorEd Warnicke <eaw@cisco.com>
Tue, 19 Nov 2013 14:16:32 +0000 (14:16 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 19 Nov 2013 14:16:32 +0000 (14:16 +0000)
50 files changed:
opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/factory_abs_template.ftl
opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java
opendaylight/distribution/opendaylight/pom.xml
opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml [deleted file]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java
opendaylight/md-sal/forwardingrules-manager/pom.xml [new file with mode: 0644]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FRMConsumerImpl.java [moved from opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java with 98% similarity]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FRMUtil.java [moved from opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java with 99% similarity]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/FlowConsumerImpl.java [moved from opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java with 99% similarity]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/GroupConsumerImpl.java [moved from opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java with 99% similarity]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/IForwardingRulesManager.java [moved from opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/IForwardingRulesManager.java with 91% similarity]
opendaylight/md-sal/forwardingrules-manager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/consumer/impl/MeterConsumerImpl.java [moved from opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/MeterConsumerImpl.java with 99% similarity]
opendaylight/md-sal/model/model-flow-base/src/main/yang/port-types.yang
opendaylight/md-sal/model/model-flow-management/src/main/yang/flow-config.yang
opendaylight/md-sal/model/model-flow-management/src/main/yang/group-config.yang
opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-config.yang
opendaylight/md-sal/model/model-flow-management/src/main/yang/port-config.yang
opendaylight/md-sal/model/model-flow-management/src/main/yang/table-config.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-error.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug01Test.java
opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-md-sal-binding.yang
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connector/netconf/test/MountTest.java [deleted file]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/StructuredDataToJsonProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedFormatException.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedJsonFormatException.java [deleted file]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlToCompositeNodeProvider.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/XmlProvidersTest.java
opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml [new file with mode: 0644]
opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java [moved from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RouteChangeListener.java with 52% similarity]
opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java [moved from opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTable.java with 69% similarity]
opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTableException.java [new file with mode: 0644]
opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/SystemException.java [new file with mode: 0644]
opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java [new file with mode: 0644]
opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java [new file with mode: 0644]
opendaylight/md-sal/zeromq-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java [new file with mode: 0644]
opendaylight/md-sal/zeromq-routingtable/integrationtest/pom.xml [new file with mode: 0644]
opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java [new file with mode: 0644]
opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/resources/logback.xml [new file with mode: 0644]

index 00f2581ae14ff82ecd6ab29e9a51c72120ad8eef..a331e4e0c1ad95245f838ebee17192e2a7c61c81 100644 (file)
@@ -17,7 +17,12 @@ package ${packageName};
 
     @Override
     public final boolean isModuleImplementingServiceInterface(Class<? extends ${abstractServiceInterfaceType}> serviceInterface) {
-        return serviceIfcs.contains(serviceInterface);
+        for (Class<?> ifc: serviceIfcs) {
+            if (serviceInterface.isAssignableFrom(ifc)){
+                return true;
+            }
+        }
+        return false;
     }
 
     @Override
index 282dff0ec621a50e46ba107d73627ca4152e7aba..556abad7af2b9b80f4623cca42c4411f7191e974 100644 (file)
@@ -748,8 +748,10 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
                 // available if source level is 5.0
                 if (c.getID() == 1610613329)
                     continue;
+                if (c.getID() == 1610613328) // 'for each' statements are only available if source level is 5.0
+                    continue;
                 fail("Error in generated source code " + file + ":"
-                        + c.getSourceLineNumber() + " " + c.toString());
+                        + c.getSourceLineNumber() + " id: " + c.getID() + " message:"  + c.toString());
             }
 
             ASTVisitor visitor = verifiers.get(file.getName());
index e5c8a975873d11fd25da0758762660cac0eafb43..8e22c6ea6ce0380211f1031707b4c56850704337 100644 (file)
           <artifactId>inventory-manager</artifactId>
           <version>${mdsal.version}</version>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller.md</groupId>
+          <artifactId>forwardingrules-manager</artifactId>
+          <version>${mdsal.version}</version>
+        </dependency>
 
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml b/opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml
deleted file mode 100644 (file)
index 11f2305..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-<?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.1-SNAPSHOT</version>
-    <relativePath>../../commons/opendaylight</relativePath>
-  </parent>
-  <scm>
-    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
-    <tag>HEAD</tag>
-  </scm>
-
-  <artifactId>forwardingrulesmanager_mdsal</artifactId>
-  <version>1.0-SNAPSHOT</version>
-  <packaging>bundle</packaging>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>${bundle.plugin.version}</version>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Embed-Transitive>
-              false
-            </Embed-Transitive>
-            <Bundle-Activator>
-              org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl.FRMConsumerImpl
-            </Bundle-Activator>
-          </instructions>
-          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>equinoxSDK381</groupId>
-      <artifactId>org.eclipse.osgi</artifactId>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-api</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>flow-management-compatibility</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-service</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller.model</groupId>
-      <artifactId>model-flow-management</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-binding-broker-impl</artifactId>
-      <version>1.0-SNAPSHOT</version>
-      <scope>provided</scope>
-    </dependency>
-  </dependencies>
-</project>
index d462251a9fb55b4d1aba050e200d31cf06071a84..bbad85b35f9b4b99a10c937d1fa2e833930c4ad2 100644 (file)
@@ -108,7 +108,7 @@ class ConfigurationReader implements FlowManagementReader {
     }
 
     override readFlow(FlowKey key) {
-        val flowCfg = manager.getStaticFlow(key.id,key.node.toADNode());
+        val flowCfg = manager.getStaticFlow(String.valueOf(key.id), key.node.toADNode());
         return flowCfg.toConfigurationFlow;
     }
 }
index e4d917337848967a0917e24538bcb28348f11184..ef806f33efbba82955e093bc47c035730800c586 100644 (file)
@@ -24,14 +24,14 @@ class FlowConfigMapping {
         idleTimeout = source.idleTimeout
         match = source.match
         node = source.node
-        key = new FlowKey(sourceCfg.name,node);
+        key = new FlowKey(Long.parseLong(sourceCfg.name),node);
         return it.build();
     }
 
     static def toFlowConfig(Flow sourceCfg) {
         val flow = toFlow(sourceCfg);
         val it = new FlowConfig;
-        name = sourceCfg.key.id
+        name = String.valueOf(sourceCfg.id);
         node = sourceCfg.node.toADNode();
 
         return it
@@ -40,7 +40,7 @@ class FlowConfigMapping {
     static def toFlowConfig(InstanceIdentifier<?> identifier) {
         val it = new FlowConfig()
         val FlowKey key = ((identifier.path.get(2) as IdentifiableItem<Flow,FlowKey>).key)
-        name = key.id;
+        name = String.valueOf(key.id);
         node = key.node.toADNode();
 
         return it;
index a82eedc3f95156c0980e7f5ce580faf6a16387c8..2fbe0a02025bbff6afc0eb020fa59fb6587dcc50 100644 (file)
@@ -31,7 +31,7 @@ public class SampleConsumer {
 
     Flow createSampleFlow(String name, NodeRef node) {
         FlowBuilder ret = new FlowBuilder();
-        FlowKey key = new FlowKey(name, node);
+        FlowKey key = new FlowKey(Long.parseLong(name), node);
         ret.setKey(key);
         return ret.build();
     }
diff --git a/opendaylight/md-sal/forwardingrules-manager/pom.xml b/opendaylight/md-sal/forwardingrules-manager/pom.xml
new file mode 100644 (file)
index 0000000..b5f5402
--- /dev/null
@@ -0,0 +1,73 @@
+<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>sal-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.opendaylight.controller.md</groupId>
+    <artifactId>forwardingrules-manager</artifactId>
+    <packaging>bundle</packaging>
+    
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+  
+        <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.opendaylight.controller.forwardingrulesmanager.consumer.impl.FRMConsumerImpl</Bundle-Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+  
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>    
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-api</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>flow-management-compatibility</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-flow-service</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-flow-management</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-broker-impl</artifactId>
+      <version>1.0-SNAPSHOT</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+</project>
index 8338d185cc36abbbbc34613fe1e3df84d805550a..f0b7e97a15ff5b2a221ed9e15212b7516459de7f 100644 (file)
@@ -8,7 +8,14 @@ module opendaylight-port-types {
     revision "2013-09-25" {
         description "Initial revision of Port Inventory model";
     }
-
+    
+    typedef port-reason {
+        type enumeration {
+            enum add;
+            enum delete;
+            enum update;
+        }
+    }
     
     typedef port-config {
         type bits {
@@ -26,7 +33,6 @@ module opendaylight-port-types {
             enum live;
         }
     }
-
     
     typedef port-features {
         type bits {
@@ -72,6 +78,14 @@ module opendaylight-port-types {
         }
     }
     
+    grouping flow-port-status {
+        leaf reason {
+            type port-reason;
+        }
+        
+        uses flow-capable-port;
+    }
+    
     grouping flow-capable-port {    
                 
         uses common-port;
@@ -114,7 +128,7 @@ module opendaylight-port-types {
         }
     }    
     
-    grouping ofp-port-mod {
+    grouping port-mod {
         container port {
             list port {
                 key "port-mod-order";
index 7361358aff2d65c18346db532e74ba9268a465e5..1c57142997f05279780d5931a058b4f5ed96f896 100644 (file)
@@ -23,7 +23,7 @@ module flow-management {
             key "node id"; 
 
             leaf id {
-                type string;
+                type uint32;
             }
             uses flow:flow-entry;
         }
index 48dda2edcd9435a40e9230caf68ea797912bd0a3..2fc051087d38c099af6e0189a86ef1b0711aecf2 100644 (file)
@@ -22,7 +22,7 @@ module group-management {
             key "id node"; 
                         
             leaf id {
-                type string;
+                type uint32;
             }                       
             
             uses group-entry;
index 111d3d60faaf29fcfff6e93f05be3bad10b089e5..35d4550ebf7a472cdd0b054f9f73cc181d9cb8fa 100644 (file)
@@ -22,7 +22,7 @@ module meter-management {
             key "id node"; 
                         
             leaf id {
-                type string;
+                type uint32;
             }                    
             
             uses meter-entry;
index 945cc32ab5d33bb194d10e9ff63d971d573495fb..50762b87ce821411583acffa86418e656539c99c 100644 (file)
@@ -14,7 +14,7 @@ module port-management {
         leaf node {
             type inv:node-ref;
         }
-        uses port:ofp-port-mod;
+        uses port:port-mod;
     }   
      
     container ports {
@@ -22,7 +22,7 @@ module port-management {
             key "id node"; 
                         
             leaf id {
-                type string;
+                type uint32;
             }                       
             
             uses port-entry;
index 88dcfce91c43c1f515e7067db045e7b2b6ee611b..512fb6528bbc6320ec1b6de699fa4c7c9e08b896 100644 (file)
@@ -23,7 +23,7 @@ module table-management {
             key "id node"; 
                         
             leaf id {
-                type string;
+                type uint32;
             }                    
             
             uses table-entry;
index 171f9563ee318c7c78c8c05f9e6ed701ef771457..369b279b95264a317ae51001f016290bbdac79cb 100644 (file)
@@ -16,13 +16,15 @@ module flow-errors {
             enum flow-mod-failed;
             enum group-mod-failed;
             enum port-mod-failed;
-            enum table-mod-failed;
-            enum meter-mod-failed;
+            enum table-mod-failed;            
             enum queue-op-failed;
             enum switch-config-failed;
             enum role-request-failed;
+            enum meter-mod-failed;
             enum table-features-failed;
-            enum experimenter;
+            enum experimenter {
+                value "65535";
+            }
         }
     }
     
index df0b2527b8731c4036d902d481d7adee1b1e7233..a32a45f2fdfea5cb5ce894c9c569942e0752d48e 100644 (file)
@@ -97,9 +97,11 @@ module sal-flow {
     
     notification node-error-notification {
         uses error:error-message;
+        uses tr:transaction-aware;
     }
     
     notification node-experimenter-error-notification {
         uses error:experimenter-error-message;
+        uses tr:transaction-aware;
     }
 }
\ No newline at end of file
index df527ef26778d41c18db40fdf08e452e6d728784..9588652a1c6cdb8fb63901f8cb4ccf72228c7b9c 100644 (file)
@@ -13,7 +13,7 @@ module sal-port {
     grouping node-port {
         uses "inv:node-context-ref";
         
-        uses port-type:ofp-port-mod;
+        uses port-type:flow-port-status;
     }
 
     /** Base configuration structure **/
@@ -21,10 +21,10 @@ module sal-port {
         uses "inv:node-context-ref";
 
         container original-port {
-            uses port-type:ofp-port-mod;
+            uses port-type:port-mod;
         }
         container updated-port {
-            uses port-type:ofp-port-mod;
+            uses port-type:port-mod;
         }
     }
 
index 3198109bc4f0d97268b3a79b559b5182ea4c7996..bdbcce0950fa449dbc43a7be562fa22bbb7f3ade 100644 (file)
 
         <module>inventory-manager</module>
         <module>statistics-manager</module>
+        <module>forwardingrules-manager</module>
+        
         <!-- Compability Packages -->
         <module>compatibility</module>
-
+        <module>zeromq-routingtable/implementation</module>
         <module>sal-zeromq-connector</module>
     </modules>
 
@@ -61,6 +63,7 @@
            </activation>
             <modules>
                 <module>sal-binding-it</module>
+                <module>zeromq-routingtable/integrationtest</module>
                 <module>clustered-data-store/integrationtest</module>
                 <module>test</module>
             </modules>
index 70be175598b591428d6a9386ae7c9a58315f6769..08eb409b3dbf9552a3152e2a88fb43ecb44f562c 100644 (file)
@@ -46,7 +46,7 @@ public class DOMCodecBug01Test extends AbstractDataServiceTest {
     private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
     private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
     
-    private static final String FLOW_ID = "foo";
+    private static final long FLOW_ID = 1234;
     private static final String NODE_ID = "node:1";
 
     private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
index 8fb6c897d5d3500454cbcfa16f8f108c3a2cc47e..bf3d7abd1ed0433c3f6c334ec8f2de595def2bb1 100644 (file)
@@ -17,4 +17,20 @@ module opendaylight-md-sal-binding {
         base "config:service-type";
         config:java-class "org.opendaylight.controller.sal.binding.api.BindingAwareBroker";
     }
+
+    identity binding-data-broker {
+        base "config:service-type";
+        config:java-class "org.opendaylight.controller.sal.binding.api.data.DataProviderService";
+    }
+
+    identity binding-rpc-registry {
+        base "config:service-type";
+        config:java-class "org.opendaylight.controller.sal.binding.api.RpcProviderRegistry";
+    }
+
+    identity binding-notification-service {
+        base "config:service-type";
+        config:java-class "org.opendaylight.controller.sal.binding.api.NotificationProviderService";
+    }
+
 }
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connector/netconf/test/MountTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connector/netconf/test/MountTest.java
deleted file mode 100644 (file)
index 4abf0e1..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-package org.opendaylight.controller.sal.connector.netconf.test;
-
-import static junit.framework.Assert.assertEquals;
-import static org.junit.Assert.*;
-import io.netty.channel.ChannelFuture;
-import io.netty.util.HashedWheelTimer;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import javax.net.ssl.SSLContext;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
-import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
-import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.controller.config.yang.store.api.YangStoreException;
-import org.opendaylight.controller.config.yang.store.impl.HardcodedYangStoreService;
-import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
-import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
-import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.client.NetconfClient;
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
-import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
-import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
-import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
-import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
-import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
-import org.opendaylight.controller.netconf.impl.SessionIdProvider;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
-import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
-import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
-import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
-import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceManager;
-import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl;
-import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-
-public class MountTest extends AbstractConfigTest {
-
-    private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
-    private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024);
-    private static final URI NETCONF_MONITORING_NS = URI.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring");
-    
-    private static final QName NETCONF_MONITORING = new QName(NETCONF_MONITORING_NS, new Date(2010,10,04), "ietf-netconf-monitoring");
-    private static final QName NETCONF_MONITORING_STATE = new QName(NETCONF_MONITORING,"netconf-state");
-    
-
-    private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession;
-    private DefaultCommitNotificationProducer commitNot;
-    private NetconfServerDispatcher dispatch;
-    private DataProviderService dataBroker;
-    private MountPointManagerImpl mountManager;
-    private NetconfDeviceManager netconfManager;
-
-    private static QName CONFIG_MODULES = new QName(
-            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
-    private static QName CONFIG_SERVICES = new QName(
-            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
-
-    private NetconfClient createSession(final InetSocketAddress address, NetconfClientDispatcher dispatcher) throws InterruptedException {
-        final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, dispatcher);
-        return netconfClient;
-    }
-    
-    @Before
-    public void setUp() throws Exception {
-        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(getModuleFactories().toArray(
-                new ModuleFactory[0])));
-
-        loadMessages();
-
-        NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
-        factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
-
-        commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
-
-        dispatch = createDispatcher(Optional.<SSLContext> absent(), factoriesListener);
-        ChannelFuture s = dispatch.createServer(tcpAddress);
-        s.await();
-
-        dataBroker = new DataBrokerImpl();
-        mountManager = new MountPointManagerImpl();
-        mountManager.setDataBroker(dataBroker);
-        netconfManager = new NetconfDeviceManager();
-
-        netconfManager.setMountService(mountManager);
-        netconfManager.setDataService(dataBroker);
-        netconfManager.start();
-
-        try (NetconfClient netconfClient = createSession(tcpAddress, netconfManager.getDispatcher())) {
-            // send edit_config.xml
-            final Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument();
-            assertNotNull(rpcReply);
-        }
-    }
-
-
-    protected List<ModuleFactory> getModuleFactories() {
-        return getModuleFactoriesS();
-    }
-
-    static List<ModuleFactory> getModuleFactoriesS() {
-        return Lists.newArrayList(new TestImplModuleFactory(), new DepTestImplModuleFactory(),
-                new NetconfTestImplModuleFactory());
-    }
-
-    private void loadMessages() throws IOException, SAXException, ParserConfigurationException {
-        this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml");
-        this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
-        this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml");
-        this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml");
-    }
-
-    private NetconfServerDispatcher createDispatcher(Optional<SSLContext> sslC,
-            NetconfOperationServiceFactoryListenerImpl factoriesListener) {
-        SessionIdProvider idProvider = new SessionIdProvider();
-        NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
-                new HashedWheelTimer(5000, TimeUnit.MILLISECONDS), factoriesListener, idProvider);
-
-        NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
-                factoriesListener, commitNot, idProvider);
-
-        return new NetconfServerDispatcher(sslC, serverNegotiatorFactory, listenerFactory);
-    }
-
-    private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
-        final Collection<InputStream> yangDependencies = getBasicYangs();
-        return new HardcodedYangStoreService(yangDependencies);
-    }
-
-    private Collection<InputStream> getBasicYangs() throws IOException {
-        List<String> paths = Arrays.asList("/META-INF/yang/config.yang", "/META-INF/yang/rpc-context.yang",
-                "/META-INF/yang/config-test.yang", "/META-INF/yang/config-test-impl.yang",
-                "/META-INF/yang/ietf-inet-types.yang");
-        final Collection<InputStream> yangDependencies = new ArrayList<>();
-        for (String path : paths) {
-            final InputStream is = Preconditions
-                    .checkNotNull(getClass().getResourceAsStream(path), path + " not found");
-            yangDependencies.add(is);
-        }
-        return yangDependencies;
-    }
-
-    @Test
-    public void test() {
-        // MountProvisionInstance mount =
-        // Mockito.mock(MountProvisionInstance.class);
-        InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
-                .node(InventoryUtils.INVENTORY_NODE).toInstance();
-        netconfManager.netconfNodeAdded(path, tcpAddress);
-        InstanceIdentifier mountPointPath = path;
-        MountProvisionInstance mountPoint = mountManager.getMountPoint(mountPointPath);
-
-        CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
-                .toInstance());
-        assertNotNull(data);
-        assertEquals(CONFIG_MODULES, data.getNodeType());
-
-        CompositeNode data2 = mountPoint.readOperationalData(InstanceIdentifier.builder().toInstance());
-        assertNotNull(data2);
-
-        InstanceIdentifier fullPath = InstanceIdentifier.builder(mountPointPath).node(CONFIG_MODULES).toInstance();
-
-        CompositeNode data3 = dataBroker.readOperationalData(fullPath);
-        assertNotNull(data3);
-        assertEquals(CONFIG_MODULES, data.getNodeType());
-    }
-
-}
index 3115994e01575a57661db4bbc73bc81927e9713d..a0acaf156facb47a74f9e672f1514277f78fc4a4 100644 (file)
@@ -17,17 +17,17 @@ import com.google.gson.JsonPrimitive;
 
 class JsonReader {
 
-    public CompositeNodeWrapper read(InputStream entityStream) throws UnsupportedJsonFormatException {
+    public CompositeNodeWrapper read(InputStream entityStream) throws UnsupportedFormatException {
         JsonParser parser = new JsonParser();
         
         JsonElement rootElement = parser.parse(new InputStreamReader(entityStream));
         if (!rootElement.isJsonObject()) {
-            throw new UnsupportedJsonFormatException("Root element of Json has to be Object");
+            throw new UnsupportedFormatException("Root element of Json has to be Object");
         }
         
         Set<Entry<String, JsonElement>> entrySetsOfRootJsonObject = rootElement.getAsJsonObject().entrySet();
         if (entrySetsOfRootJsonObject.size() != 1) {
-            throw new UnsupportedJsonFormatException("Json Object should contain one element");
+            throw new UnsupportedFormatException("Json Object should contain one element");
         } else {
             Entry<String, JsonElement> childEntry = Lists.newArrayList(entrySetsOfRootJsonObject).get(0);
             String firstElementName = childEntry.getKey();
@@ -41,10 +41,10 @@ class JsonReader {
                     if (firstElementInArray.isJsonObject()) {
                         return createStructureWithRoot(firstElementName, firstElementInArray.getAsJsonObject());
                     }
-                    throw new UnsupportedJsonFormatException("Array as the first element in Json Object can have only Object element");
+                    throw new UnsupportedFormatException("Array as the first element in Json Object can have only Object element");
                 }
             }
-            throw new UnsupportedJsonFormatException("First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet.");
+            throw new UnsupportedFormatException("First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet.");
         }
     }
     
index daaedd92b8d6c85f05f26365b90f6bbe68f7d5d6..27ebebabd7f7fe97c7dcc24f20c1a5de761f1284 100644 (file)
@@ -35,7 +35,7 @@ public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNo
         JsonReader jsonReader = new JsonReader();
         try {
             return jsonReader.read(entityStream);
-        } catch (UnsupportedJsonFormatException e) {
+        } catch (UnsupportedFormatException e) {
             throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
                     .entity(e.getMessage()).build());
         }
index 35b751c73fcf1f007f3a9d419b63fbea2c7727d2..53b401e4a2c55856dc215c4fc5b62987ebaa71f0 100644 (file)
@@ -1,19 +1,31 @@
 package org.opendaylight.controller.sal.rest.impl;
 
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.core.api.Broker;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+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;
 
-public class RestconfProvider extends AbstractProvider {
+public class RestconfProvider implements BundleActivator, Provider, ServiceTrackerCustomizer<Broker, Broker> {
 
+    public final static String NOT_INITALIZED_MSG = "Restcof is not initialized yet. Please try again later";
+    
     private ListenerRegistration<SchemaServiceListener> listenerRegistration;
+    private ServiceTracker<Broker, Broker> brokerServiceTrancker;
+    private BundleContext bundleContext;
+    private ProviderSession session;
 
     @Override
     public void onSessionInitiated(ProviderSession session) {
@@ -28,8 +40,14 @@ public class RestconfProvider extends AbstractProvider {
     }
 
     @Override
-    protected void stopImpl(BundleContext context) {
-        super.stopImpl(context);
+    public void start(BundleContext context) throws Exception {
+        bundleContext = context;
+        brokerServiceTrancker = new ServiceTracker<>(context, Broker.class, this);
+        brokerServiceTrancker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) {
         if (listenerRegistration != null) {
             try {
                 listenerRegistration.close();
@@ -37,5 +55,32 @@ public class RestconfProvider extends AbstractProvider {
                 e.printStackTrace();
             }
         }
+        session.close();
+        brokerServiceTrancker.close();
+    }
+
+    @Override
+    public Collection<ProviderFunctionality> getProviderFunctionality() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Broker addingService(ServiceReference<Broker> reference) {
+        Broker broker = bundleContext.getService(reference);
+        broker.registerProvider(this, bundleContext);
+        return broker;
+    }
+
+    @Override
+    public void modifiedService(ServiceReference<Broker> reference, Broker service) {
+        // NOOP
+    }
+
+    @Override
+    public void removedService(ServiceReference<Broker> reference, Broker service) {
+        bundleContext.ungetService(reference);
+        BrokerFacade.getInstance().setContext(null);
+        BrokerFacade.getInstance().setDataService(null);
+        ControllerContext.getInstance().setSchemas(null);
     }
 }
index 4a851a3f6ca531f6042b9d20df7f4d9ba3cd3517..90e6d2affc5cde925d4adc941b24d42005aad117 100644 (file)
@@ -24,7 +24,7 @@ import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import com.google.gson.stream.JsonWriter;
 
 @Provider
-@Produces({ API + RestconfService.JSON })
+@Produces({API+RestconfService.JSON})
 public enum StructuredDataToJsonProvider implements MessageBodyWriter<StructuredData> {
     INSTANCE;
     
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedFormatException.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedFormatException.java
new file mode 100644 (file)
index 0000000..615f209
--- /dev/null
@@ -0,0 +1,23 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+public class UnsupportedFormatException extends Exception {
+
+    private static final long serialVersionUID = -1741388894406313402L;
+
+    public UnsupportedFormatException() {
+        super();
+    }
+
+    public UnsupportedFormatException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public UnsupportedFormatException(String message) {
+        super(message);
+    }
+
+    public UnsupportedFormatException(Throwable cause) {
+        super(cause);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedJsonFormatException.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/UnsupportedJsonFormatException.java
deleted file mode 100644 (file)
index dccf29b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.opendaylight.controller.sal.rest.impl;
-
-public class UnsupportedJsonFormatException extends Exception {
-
-    private static final long serialVersionUID = -1741388894406313402L;
-
-    public UnsupportedJsonFormatException() {
-        super();
-    }
-
-    public UnsupportedJsonFormatException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public UnsupportedJsonFormatException(String message) {
-        super(message);
-    }
-
-    public UnsupportedJsonFormatException(Throwable cause) {
-        super(cause);
-    }
-
-}
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
new file mode 100644 (file)
index 0000000..9f31eb4
--- /dev/null
@@ -0,0 +1,157 @@
+package org.opendaylight.controller.sal.rest.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Stack;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+
+public class XmlReader {
+    
+    private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+    private XMLEventReader eventReader;
+
+    public CompositeNodeWrapper read(InputStream entityStream) throws XMLStreamException, UnsupportedFormatException {
+        eventReader = xmlInputFactory.createXMLEventReader(entityStream);
+        
+        if (eventReader.hasNext()) {
+            XMLEvent element = eventReader.peek();
+            if (element.isStartDocument()) {
+                eventReader.nextEvent();
+            }
+        }
+
+        if (eventReader.hasNext() && !isCompositeNodeEvent(eventReader.peek())) {
+            throw new UnsupportedFormatException("Root element of XML has to be composite element.");
+        }
+        
+        final Stack<NodeWrapper<?>> processingQueue = new Stack<>();
+        CompositeNodeWrapper root = null;
+        NodeWrapper<?> element = null;
+        while (eventReader.hasNext()) {
+            final XMLEvent event = eventReader.nextEvent();
+
+            if (event.isStartElement()) {
+                final StartElement startElement = event.asStartElement();
+                CompositeNodeWrapper compParentNode = null;
+                if (!processingQueue.isEmpty() && processingQueue.peek() instanceof CompositeNodeWrapper) {
+                    compParentNode = (CompositeNodeWrapper) processingQueue.peek();
+                }
+                NodeWrapper<?> newNode = null;
+                if (isCompositeNodeEvent(event)) {
+                    if (root == null) {
+                        root = resolveCompositeNodeFromStartElement(startElement);
+                        newNode = root;
+                    } else {
+                        newNode = resolveCompositeNodeFromStartElement(startElement);
+                    }
+                } else if (isSimpleNodeEvent(event)) {
+                    if (root == null) {
+                        throw new UnsupportedFormatException("Root element of XML has to be composite element.");
+                    }
+                    newNode = resolveSimpleNodeFromStartElement(startElement);
+                }
+
+                if (newNode != null) {
+                    processingQueue.push(newNode);
+                    if (compParentNode != null) {
+                        compParentNode.addValue(newNode);
+                    }
+                }
+            } else if (event.isEndElement()) {
+                element = processingQueue.pop();
+            }
+        }
+        
+        if (!root.getLocalName().equals(element.getLocalName())) {
+            throw new UnsupportedFormatException("XML should contain only one root element");
+        }
+        
+        return root;
+    }
+    
+    private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
+        checkArgument(event != null, "XML Event cannot be NULL!");
+        if (event.isStartElement()) {
+            if (eventReader.hasNext()) {
+                final XMLEvent innerEvent;
+                innerEvent = eventReader.peek();
+                if (innerEvent.isCharacters()) {
+                    final Characters chars = innerEvent.asCharacters();
+                    if (!chars.isWhiteSpace()) {
+                        return true;
+                    }
+                } else if (innerEvent.isEndElement()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    private boolean isCompositeNodeEvent(final XMLEvent event) throws XMLStreamException {
+        checkArgument(event != null, "XML Event cannot be NULL!");
+        if (event.isStartElement()) {
+            if (eventReader.hasNext()) {
+                XMLEvent innerEvent;
+                innerEvent = eventReader.peek();
+                if (innerEvent.isCharacters()) {
+                    Characters chars = innerEvent.asCharacters();
+                    if (chars.isWhiteSpace()) {
+                        eventReader.nextEvent();
+                        innerEvent = eventReader.peek();
+                    }
+                }
+                if (innerEvent.isStartElement()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    private SimpleNodeWrapper resolveSimpleNodeFromStartElement(final StartElement startElement) throws XMLStreamException {
+        checkArgument(startElement != null, "Start Element cannot be NULL!");
+        String data = null;
+
+        if (eventReader.hasNext()) {
+            final XMLEvent innerEvent = eventReader.peek();
+            if (innerEvent.isCharacters()) {
+                final Characters chars = innerEvent.asCharacters();
+                if (!chars.isWhiteSpace()) {
+                    data = innerEvent.asCharacters().getData();
+                }
+            } else if (innerEvent.isEndElement()) {
+                data = "";
+            }
+        }
+        
+        return new SimpleNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement), data);
+    }
+    
+    private CompositeNodeWrapper resolveCompositeNodeFromStartElement(final StartElement startElement) {
+        checkArgument(startElement != null, "Start Element cannot be NULL!");
+        return new CompositeNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
+    }
+    
+    private String getLocalNameFrom(StartElement startElement) {
+        return startElement.getName().getLocalPart();
+    }
+    
+    private URI getNamespaceFrom(StartElement startElement) {
+        String namespaceURI = startElement.getName().getNamespaceURI();
+        return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
+    }
+    
+}
index 09733f5e907faa533167be5211b39cf2839b6345..07b30327f07d7c8d8723e79268d213702bc189b4 100644 (file)
@@ -18,19 +18,12 @@ import javax.xml.stream.XMLStreamException;
 
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 @Provider
 @Consumes({API+RestconfService.XML})
 public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
     INSTANCE;
     
-    private final static Logger logger = LoggerFactory.getLogger(XmlToCompositeNodeProvider.class);
-
     @Override
     public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         return true;
@@ -40,16 +33,10 @@ public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNod
     public CompositeNode readFrom(Class<CompositeNode> type, Type genericType, Annotation[] annotations,
             MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
             throws IOException, WebApplicationException {
+        XmlReader xmlReader = new XmlReader();
         try {
-            Node<?> node = XmlTreeBuilder.buildDataTree(entityStream);
-            if (node instanceof SimpleNode) {
-                logger.info("Node is SimpleNode");
-                throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
-                        .entity("XML should start with XML element that contains 1..N XML child elements.").build());
-            }
-            return (CompositeNode) node;
-        } catch (XMLStreamException e) {
-            logger.info("Error during translation of InputStream to Node\n" + e.getMessage());
+            return xmlReader.read(entityStream);
+        } catch (XMLStreamException | UnsupportedFormatException e) {
             throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
                     .entity(e.getMessage()).build());
         }
index 3c31c5a313ec0b45a9a8390729638331d4a7a7a0..f5b913253201ee3d045bfbc00d3af994fdf8cba0 100644 (file)
@@ -1,13 +1,15 @@
 package org.opendaylight.controller.sal.restconf.impl
 
+import javax.ws.rs.WebApplicationException
+import javax.ws.rs.core.Response
 import org.opendaylight.controller.md.sal.common.api.data.DataReader
 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService
+import org.opendaylight.controller.sal.rest.impl.RestconfProvider
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.common.RpcResult
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import static org.opendaylight.controller.sal.restconf.impl.BrokerFacade.*
 
 class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
 
@@ -24,31 +26,43 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
             throw new IllegalStateException("Already instantiated");
         }
     }
-    
+
     def static BrokerFacade getInstance() {
         return INSTANCE
     }
 
+    private def void checkPreconditions() {
+        if (context == null || dataService == null) {
+            throw new WebApplicationException(Response.status(Response.Status.SERVICE_UNAVAILABLE)
+                    .entity(RestconfProvider::NOT_INITALIZED_MSG).build())
+        }
+    }
+
     override readConfigurationData(InstanceIdentifier path) {
+        checkPreconditions
         return dataService.readConfigurationData(path);
     }
 
     override readOperationalData(InstanceIdentifier path) {
+        checkPreconditions
         return dataService.readOperationalData(path);
     }
 
     def RpcResult<CompositeNode> invokeRpc(QName type, CompositeNode payload) {
+        checkPreconditions
         val future = context.rpc(type, payload);
         return future.get;
     }
 
     def commitConfigurationDataPut(InstanceIdentifier path, CompositeNode payload) {
+        checkPreconditions
         val transaction = dataService.beginTransaction;
         transaction.putConfigurationData(path, payload);
         return transaction.commit()
     }
 
     def commitOperationalDataPut(InstanceIdentifier path, CompositeNode payload) {
+        checkPreconditions
         val transaction = dataService.beginTransaction;
         transaction.putOperationalData(path, payload);
         return transaction.commit()
index 624178569d4e71551507f7733cec7c93bf4b032c..c1ee611e07c77241b1346f0683387d503111e1e9 100644 (file)
@@ -8,6 +8,11 @@ import java.net.URLEncoder
 import java.util.HashMap
 import java.util.List
 import java.util.Map
+import java.util.concurrent.ConcurrentHashMap
+import javax.ws.rs.WebApplicationException
+import javax.ws.rs.core.Response
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.controller.sal.rest.impl.RestconfProvider
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder
@@ -21,12 +26,10 @@ import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
 import org.opendaylight.yangtools.yang.model.api.SchemaContext
 
 import static com.google.common.base.Preconditions.*
-import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition
-import java.util.concurrent.ConcurrentHashMap
 
 class ControllerContext implements SchemaServiceListener {
 
@@ -51,6 +54,13 @@ class ControllerContext implements SchemaServiceListener {
     static def getInstance() {
         return INSTANCE
     }
+    
+    private def void checkPreconditions() {
+        if (schemas == null) {
+            throw new WebApplicationException(Response.status(Response.Status.SERVICE_UNAVAILABLE)
+                    .entity(RestconfProvider::NOT_INITALIZED_MSG).build())
+        }
+    }
 
     public def InstanceIdWithSchemaNode toInstanceIdentifier(String restconfInstance) {
         val ret = InstanceIdentifier.builder();
@@ -69,6 +79,7 @@ class ControllerContext implements SchemaServiceListener {
     }
 
     private def findModule(String restconfInstance) {
+        checkPreconditions
         checkNotNull(restconfInstance);
         val pathArgs = restconfInstance.split("/");
         if (pathArgs.empty) {
@@ -93,6 +104,7 @@ class ControllerContext implements SchemaServiceListener {
     }
 
     def String toFullRestconfIdentifier(InstanceIdentifier path) {
+        checkPreconditions
         val elements = path.path;
         val ret = new StringBuilder();
         val startQName = elements.get(0).nodeType;
@@ -120,6 +132,7 @@ class ControllerContext implements SchemaServiceListener {
     }
 
     def CharSequence toRestconfIdentifier(QName qname) {
+        checkPreconditions
         var module = uriToModuleName.get(qname.namespace)
         if (module == null) {
             val moduleSchema = schemas.findModuleByNamespaceAndRevision(qname.namespace, qname.revision);
index ea3a4fbcfcbae90e848c39e505008dd701613b26..a41a48287df87f887dd37c12b0fd88f4539f7597 100644 (file)
@@ -113,7 +113,7 @@ class RestconfImpl implements RestconfService {
             val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
             for (child : children) {
                 addNamespaceToNodeFromSchemaRecursively(child,
-                    (schema as DataNodeContainer).childNodes.findFirst[n|n.QName.localName === child.localName])
+                    (schema as DataNodeContainer).childNodes.findFirst[n|n.QName.localName.equals(child.localName)])
             }
         }
     }
index 9d004362d29d0b64b9a8636f51430ccfa46d8ca3..baf226712ffbb255550948c3c5f36160d4c30262 100644 (file)
@@ -13,6 +13,10 @@ import java.net.URLEncoder;
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
 
@@ -31,6 +35,7 @@ import org.glassfish.jersey.test.TestProperties;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
@@ -73,7 +78,7 @@ public class XmlProvidersTest extends JerseyTest {
         restconfImpl.setControllerContext(controllerContext);
     }
 
-//    @Before
+    @Before
     public void logs() {
         List<LogRecord> loggedRecords = getLoggedRecords();
         for (LogRecord l : loggedRecords) {
@@ -102,26 +107,32 @@ public class XmlProvidersTest extends JerseyTest {
     public void testXmlToCompositeNodeProvider() throws ParserConfigurationException, SAXException, IOException {
         URI uri = null;
         try {
-            uri = new URI("/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
+            uri = new URI("/config/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
         } catch (UnsupportedEncodingException | URISyntaxException e) {
             e.printStackTrace();
         }
         InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
         final CompositeNode loadedCompositeNode = TestUtils.loadCompositeNode(xmlStream);
-        when(brokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenReturn(new RpcResult<CompositeNode>() {
-            
+        when(brokerFacade.commitConfigurationDataPut(any(InstanceIdentifier.class), any(CompositeNode.class))).thenReturn(new Future<RpcResult<TransactionStatus>>() {
+            @Override
+            public boolean cancel(boolean mayInterruptIfRunning) {
+                return false;
+            }
             @Override
-            public boolean isSuccessful() {
-                return true;
+            public boolean isCancelled() {
+                return false;
             }
-            
             @Override
-            public CompositeNode getResult() {
-                return loadedCompositeNode;
+            public boolean isDone() {
+                return false;
             }
-            
             @Override
-            public Collection<RpcError> getErrors() {
+            public RpcResult<TransactionStatus> get() throws InterruptedException, ExecutionException {
+                return null;
+            }
+            @Override
+            public RpcResult<TransactionStatus> get(long timeout, TimeUnit unit) throws InterruptedException,
+                    ExecutionException, TimeoutException {
                 return null;
             }
         });
@@ -132,7 +143,7 @@ public class XmlProvidersTest extends JerseyTest {
         Document doc = docBuilder.parse(xmlStream);
         
         Response response = target(uri.toASCIIString()).request(MediaTypes.API+RestconfService.XML).post(Entity.entity(TestUtils.getDocumentInPrintableForm(doc), new MediaType("application","vnd.yang.api+xml")));
-        assertEquals(200, response.getStatus());
+        assertEquals(204, response.getStatus());
     }
     
     @Test
diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml b/opendaylight/md-sal/zeromq-routingtable/implementation/pom.xml
new file mode 100644 (file)
index 0000000..37c973e
--- /dev/null
@@ -0,0 +1,99 @@
+<?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>sal-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
+    </parent>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+        <tag>HEAD</tag>
+    </scm>
+
+    <artifactId>zeromq-routingtable.implementation</artifactId>
+    <version>0.4.1-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>${bundle.plugin.version}</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+
+                        <Import-Package>
+                            javax.xml.bind.annotation,
+                            org.opendaylight.controller.sal.core,
+                            org.opendaylight.controller.sal.utils,
+                            org.opendaylight.controller.sal.packet,
+                            org.opendaylight.controller.sal.topology,
+                            org.opendaylight.controller.clustering.services,
+                            org.opendaylight.controller.md.sal.common.api.data,
+                            org.opendaylight.yangtools.yang.binding,
+                            org.osgi.service.component,
+                            org.slf4j,
+                            org.apache.felix.dm,
+                            org.apache.commons.lang3.builder,
+                            org.apache.commons.lang3.tuple,
+                            org.eclipse.osgi.framework.console,
+                            org.osgi.framework,
+                            javax.transaction,
+                            com.google.common.base
+                        </Import-Package>
+                        <Bundle-Activator>
+                            org.opendaylight.controller.sal.connector.remoterpc.impl.Activator
+                        </Bundle-Activator>
+                    </instructions>
+                    <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-connector-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>clustering.services</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+
+
+    </dependencies>
+</project>
@@ -7,13 +7,12 @@
  */
 package org.opendaylight.controller.sal.connector.remoterpc.api;
 
-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.util.EventListener;
 
-public interface RouteChangeListener extends EventListener {
+public interface RouteChangeListener<I,R> extends EventListener {
+
+
+   void onRouteUpdated(I key, R new_value);
 
-  public void onRouteChanged(RouteChange<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>  change);
+   void onRouteDeleted(I key);
 }
@@ -11,6 +11,8 @@ import java.util.Set;
 
 public interface RoutingTable<I,R> {
 
+
+
   /**
    * Adds a network address for the route. If address for route
    * exists, appends the address to the list
@@ -18,17 +20,22 @@ public interface RoutingTable<I,R> {
    * @param routeId route identifier
    * @param route network address
    */
-  public void addRoute(I routeId, R route);
+  public void addRoute(I routeId, R route) throws SystemException,  RoutingTableException;
 
   /**
    * Adds a network address for the route. If the route already exists,
-   * it throws. This method would be used when registering a global service.
+   * it throws <code>DuplicateRouteException</code>.
+   * This method would be used when registering a global service.
+   *
    *
    * @param routeId route identifier
    * @param route network address
    * @throws DuplicateRouteException
    */
-  public void addGlobalRoute(I routeId, R route) throws DuplicateRouteException;
+  public void addGlobalRoute(I routeId, R route) throws  RoutingTableException, SystemException;
+
+
+
 
   /**
    * Removes the network address for the route from routing table. If only
@@ -38,6 +45,14 @@ public interface RoutingTable<I,R> {
    */
   public void removeRoute(I routeId, R route);
 
+
+    /**
+     * Remove the route.
+     * This method would be used when registering a global service.
+     * @param routeId
+     */
+    public void removeGlobalRoute(I routeId);
+
   /**
    * Returns a set of network addresses associated with this route
    * @param routeId
@@ -49,12 +64,18 @@ public interface RoutingTable<I,R> {
    * Returns only one address from the list of network addresses
    * associated with the route. The algorithm to determine that
    * one address is upto the implementer
-   * @param route
+   * @param routeId
    * @return
    */
   public R getARoute(I routeId);
 
   public void registerRouteChangeListener(RouteChangeListener listener);
 
-  public class DuplicateRouteException extends Exception {}
+  public class DuplicateRouteException extends RoutingTableException {
+      public DuplicateRouteException(String message) {
+          super(message);
+      }
+
+  }
+
 }
diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTableException.java b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/RoutingTableException.java
new file mode 100644 (file)
index 0000000..fc7f6f1
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.sal.connector.remoterpc.api;
+
+/**
+ * @author: syedbahm
+ */
+public class RoutingTableException extends Exception {
+
+    /**
+     * Constructs a new exception with {@code null} as its detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     */
+    public RoutingTableException() {
+        super();
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message.  The
+     * cause is not initialized, and may subsequently be initialized by
+     * a call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public RoutingTableException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A <tt>null</tt> value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     */
+    public RoutingTableException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/SystemException.java b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/api/SystemException.java
new file mode 100644 (file)
index 0000000..491858e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.sal.connector.remoterpc.api;
+
+/**
+ * @author: syedbahm
+ *
+ */
+public class SystemException extends  Exception {
+    /**
+     * Constructs a new exception with {@code null} as its detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     */
+    public SystemException() {
+        super();
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message.  The
+     * cause is not initialized, and may subsequently be initialized by
+     * a call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public SystemException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A <tt>null</tt> value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     * @since 1.4
+     */
+    public SystemException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/Activator.java
new file mode 100644 (file)
index 0000000..4541443
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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.sal.connector.remoterpc.impl;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+/**
+ * @author: syedbahm
+ */
+public class Activator extends ComponentActivatorAbstractBase {
+
+    protected static final Logger logger = LoggerFactory
+            .getLogger(Activator.class);
+    private static final String CACHE_UPDATE_AWARE_REGISTRY_KEY = "cachenames" ;
+
+
+    /**
+     * Method which tells how many Global implementations are
+     * supported by the bundle. This way we can tune the number of
+     * components created. This components will be created ONLY at the
+     * time of bundle startup and will be destroyed only at time of
+     * bundle destruction, this is the major difference with the
+     * implementation retrieved via getImplementations where all of
+     * them are assumed to be in a container!
+     *
+     *
+     * @return The list of implementations the bundle will support,
+     * in Global version
+     */
+
+    @Override
+    protected Object[] getGlobalImplementations(){
+        logger.debug("Calling getGlobalImplementations to return:", RoutingTableImpl.class);
+        return new Object[] {
+                RoutingTableImpl.class
+        };
+    }
+
+    /**
+     * Configure the dependency for a given instance Global
+     *
+     * @param c Component assigned for this instance, this will be
+     * what will be used for configuration
+     * @param imp implementation to be configured
+     *
+     */
+    @Override
+    protected void configureGlobalInstance(Component c, Object imp){
+        if (imp.equals(RoutingTableImpl.class)) {
+            Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
+            Set<String> propSet = new HashSet<String>();
+            propSet.add(RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE);
+            props.put(CACHE_UPDATE_AWARE_REGISTRY_KEY, propSet);
+
+            c.setInterface(new String[] { RoutingTable.class.getName(),ICacheUpdateAware.class.getName()  }, props);
+            logger.debug("configureGlobalInstance adding dependency:", IClusterGlobalServices.class);
+
+            c.add(createServiceDependency().setService(
+                    IClusterGlobalServices.class).setCallbacks(
+                    "setClusterGlobalServices",
+                    "unsetClusterGlobalServices").setRequired(true));
+
+        }
+    }
+
+
+}
diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java b/opendaylight/md-sal/zeromq-routingtable/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImpl.java
new file mode 100644 (file)
index 0000000..558c8a8
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * 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.sal.connector.remoterpc.impl;
+
+import com.google.common.base.Preconditions;
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.*;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
+import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import java.util.*;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author: syedbahm
+ */
+public class RoutingTableImpl<I, R> implements RoutingTable<I, R>,ICacheUpdateAware<I,R> {
+    public static final String ROUTING_TABLE_GLOBAL_CACHE = "routing_table_global_cache";
+
+  private Logger log = LoggerFactory
+            .getLogger(RoutingTableImpl.class);
+
+  private IClusterGlobalServices clusterGlobalServices = null;
+  private RoutingTableImpl routingTableInstance = null;
+  private ConcurrentMap routingTableCache = null;
+  private List<RouteChangeListener>  routeChangeListeners = new ArrayList<RouteChangeListener>();
+  private ServiceRegistration cacheAwareRegistration = null;
+                                                      
+ public RoutingTableImpl() {
+  }
+
+  @Override
+  public void addRoute(I routeId, R route) throws RoutingTableException {
+       throw new UnsupportedOperationException(" Not implemented yet!");
+  }
+
+  @Override
+  public void addGlobalRoute(I routeId, R route) throws RoutingTableException, SystemException {
+    Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
+    Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
+    try {
+
+      Set<R> existingRoute = null;
+      // ok does the global route is already registered ?
+      if ((existingRoute = getRoutes(routeId)) == null) {
+
+          if(log.isDebugEnabled()){
+              log.debug("addGlobalRoute: adding  a new route with id"+ routeId + " and value = "+route);
+          }
+        // lets start a transaction
+        clusterGlobalServices.tbegin();
+        Set<R> routes  = new HashSet<R>();
+        routes.add(route);
+        routingTableCache.put(routeId, routes);
+        clusterGlobalServices.tcommit();
+      } else {
+        throw new DuplicateRouteException(" There is already existing route " + existingRoute);
+      }
+
+    } catch (NotSupportedException e) {
+      throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e);
+    } catch (HeuristicRollbackException e) {
+      throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e);
+    } catch (RollbackException e) {
+      throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e);
+    } catch (HeuristicMixedException e) {
+      throw new RoutingTableException("Transaction error - while trying to create route id=" + routeId + "with route" + route, e);
+    } catch (javax.transaction.SystemException e){
+        throw new SystemException ( "System error occurred - while trying to create with value",e);
+    }
+
+  }
+
+  @Override
+  public void removeRoute(I routeId, R route) {
+         throw new UnsupportedOperationException("Not implemented yet!");
+  }
+    @Override
+    public void removeGlobalRoute(I routeId) {
+        routingTableCache.remove(routeId);
+    }
+
+  @Override
+  public Set<R> getRoutes(I routeId) {
+
+      //Note: currently works for global routes only wherein there is just single route
+      Preconditions.checkNotNull(routeId, "getARoute: routeId cannot be null!");
+      return (Set<R>) routingTableCache.get(routeId);
+  }
+
+  @Override
+  public R getARoute(I routeId) {
+       throw new UnsupportedOperationException("Not implemented yet!");
+  }
+
+  /**
+   * Registers listener for sending any change notification
+   * 
+   * @param listener
+   */
+  @Override
+  public void registerRouteChangeListener(RouteChangeListener listener) {
+      routeChangeListeners.add(listener);
+  }
+
+
+    /**
+     * Returning the list of route change listeners for Unit testing
+     * Note: the package scope is default
+     * @return   List of registered RouteChangeListener<I,R> listeners
+     */
+  List<RouteChangeListener> getRegisteredRouteChangeListeners(){
+      return routeChangeListeners;
+  }
+
+  public void setClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) {
+    this.clusterGlobalServices = clusterGlobalServices;
+  }
+
+  public void unsetClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) {
+    if(cacheAwareRegistration != null) {
+        cacheAwareRegistration.unregister();
+    }
+    this.clusterGlobalServices = null;
+  }
+
+    /**
+     * Creates the Routing Table clustered global services cache
+     * @throws CacheExistException  -- cluster global services exception when cache exist
+     * @throws CacheConfigException -- cluster global services exception during cache config
+     * @throws CacheListenerAddException  -- cluster global services exception during adding of listener
+     */
+
+  void createRoutingTableCache() throws CacheExistException, CacheConfigException, CacheListenerAddException {
+    // TBD: HOW DO WE DECIDE ON PROPERTIES OF THE CACHE i.e. what duration it
+    // should be caching?
+
+    // let us check here if the cache already exists -- if so don't create
+    if (!clusterGlobalServices.existCache(
+        ROUTING_TABLE_GLOBAL_CACHE)) {
+
+        if(log.isDebugEnabled()){
+            log.debug("createRoutingTableCache: creating a new routing table cache "+ROUTING_TABLE_GLOBAL_CACHE );
+        }
+      routingTableCache = clusterGlobalServices.createCache(
+          ROUTING_TABLE_GLOBAL_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+    } else {
+        if(log.isDebugEnabled()){
+            log.debug("createRoutingTableCache: found existing routing table cache "+ROUTING_TABLE_GLOBAL_CACHE );
+        }
+      routingTableCache = clusterGlobalServices.getCache(
+          ROUTING_TABLE_GLOBAL_CACHE);
+    }
+
+  }
+
+  /**
+   * Function called by the dependency manager when all the required
+   * dependencies are satisfied
+   * 
+   */
+  void init(Component c) {
+    try {
+
+      createRoutingTableCache();
+    } catch (CacheExistException e) {
+      throw new IllegalStateException("could not construct routing table cache");
+    } catch (CacheConfigException e) {
+      throw new IllegalStateException("could not construct routing table cache");
+    } catch (CacheListenerAddException e) {
+        throw new IllegalStateException("could not construct routing table cache");
+    }
+  }
+
+
+    /**
+     * Get routing table method is useful for unit testing
+     * <note>It has package scope</note>
+     */
+    ConcurrentMap getRoutingTableCache(){
+        return this.routingTableCache;
+    }
+
+
+      /**
+       * Invoked when a new entry is available in the cache, the key is
+       * only provided, the value will come as an entryUpdate invocation
+       *
+       * @param key         Key for the entry just created
+       * @param cacheName   name of the cache for which update has been
+       *                    received
+       * @param originLocal true if the event is generated from this
+       *                    node
+       */
+      @Override
+      public void entryCreated(I key, String cacheName, boolean originLocal) {
+          //TBD: do we require this.
+          if(log.isDebugEnabled()){
+              log.debug("RoutingTableUpdates: entryCreated  routeId = "+key
+                      + " cacheName="+cacheName
+                      );
+          }
+      }
+
+      /**
+       * Called anytime a given entry is updated
+       *
+       * @param key         Key for the entry modified
+       * @param new_value   the new value the key will have
+       * @param cacheName   name of the cache for which update has been
+       *                    received
+       * @param originLocal true if the event is generated from this
+       *                    node
+       */
+      @Override
+      public void entryUpdated(I key, R new_value, String cacheName, boolean originLocal) {
+          if(log.isDebugEnabled()){
+              log.debug("RoutingTableUpdates: entryUpdated  routeId = "+key
+                      + ",value = "+ new_value
+                      + " ,cacheName="+cacheName
+                      );
+          }
+          for(RouteChangeListener rcl:routeChangeListeners){
+              rcl.onRouteUpdated(key, new_value);
+          }
+      }
+
+      /**
+       * Called anytime a given key is removed from the
+       * ConcurrentHashMap we are listening to.
+       *
+       * @param key         Key of the entry removed
+       * @param cacheName   name of the cache for which update has been
+       *                    received
+       * @param originLocal true if the event is generated from this
+       *                    node
+       */
+      @Override
+      public void entryDeleted(I key, String cacheName, boolean originLocal) {
+          if(log.isDebugEnabled()){
+              log.debug("RoutingTableUpdates: entryUpdated  routeId = "+key
+                      + " local = "+ originLocal
+                      + " cacheName="+cacheName
+                       );
+          }
+          for(RouteChangeListener rcl:routeChangeListeners){
+              rcl.onRouteDeleted(key);
+          }
+      }
+  }
\ No newline at end of file
diff --git a/opendaylight/md-sal/zeromq-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java b/opendaylight/md-sal/zeromq-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java
new file mode 100644 (file)
index 0000000..75cc6f5
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * 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.sal.connector.remoterpc.impl;
+
+import junit.framework.Assert;
+import org.apache.felix.dm.Component;
+import org.junit.Test;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import java.net.URI;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author: syedbahm
+ */
+public class RoutingTableImplTest {
+
+    private IClusterGlobalServices ics =  mock(IClusterGlobalServices.class);
+    private RoutingTableImpl rti = new RoutingTableImpl();
+
+    private final URI namespace = URI.create("http://cisco.com/example");
+    private final QName QNAME = new QName(namespace,"global");
+
+    ConcurrentMap concurrentMapMock = mock(ConcurrentMap.class);
+
+
+    @Test
+    public void testAddGlobalRoute() throws Exception {
+        ConcurrentMap concurrentMap = createRoutingTableCache();
+
+        Assert.assertNotNull(concurrentMap);
+        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier =  mock(RpcRouter.RouteIdentifier.class);
+        InstanceIdentifier identifier = mock(InstanceIdentifier.class);
+        when(routeIdentifier.getType()).thenReturn(QNAME);
+        when(routeIdentifier.getRoute()).thenReturn(identifier);
+
+        rti.addGlobalRoute(routeIdentifier, "172.27.12.1:5000");
+
+        Set<String> globalService = new HashSet<String>();
+        globalService.add("172.27.12.1:5000");
+
+        when(concurrentMap.get(routeIdentifier)).thenReturn(globalService);
+        ConcurrentMap latestCache = rti.getRoutingTableCache();
+
+        Assert.assertEquals(concurrentMap,latestCache);
+
+        Set<String> servicesGlobal = (Set<String>)latestCache.get(routeIdentifier);
+        Assert.assertEquals(servicesGlobal.size(),1);
+
+        Assert.assertEquals(servicesGlobal.iterator().next(),"172.27.12.1:5000");
+
+    }
+
+    @Test
+    public void testGetRoutes() throws Exception {
+        ConcurrentMap concurrentMap = createRoutingTableCache();
+
+        Assert.assertNotNull(concurrentMap);
+        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier =  mock(RpcRouter.RouteIdentifier.class);
+        InstanceIdentifier identifier = mock(InstanceIdentifier.class);
+        when(routeIdentifier.getContext()).thenReturn(QNAME);
+        when(routeIdentifier.getRoute()).thenReturn(identifier);
+
+        rti.addGlobalRoute(routeIdentifier, "172.27.12.1:5000");
+
+        Set<String> globalService = new HashSet<String>();
+        globalService.add("172.27.12.1:5000");
+
+        when(concurrentMap.get(routeIdentifier)).thenReturn(globalService);
+        ConcurrentMap latestCache = rti.getRoutingTableCache();
+
+        Assert.assertEquals(concurrentMap,latestCache);
+
+        Set<String> servicesGlobal =  rti.getRoutes(routeIdentifier);
+
+
+        Assert.assertEquals(servicesGlobal.size(),1);
+
+        Assert.assertEquals(servicesGlobal.iterator().next(),"172.27.12.1:5000");
+
+
+
+    }
+    @Test
+    public void testRegisterRouteChangeListener() throws Exception {
+        Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),0);
+        rti.registerRouteChangeListener(new RouteChangeListenerImpl());
+
+        Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),1);
+
+    }
+    @Test
+    public void testRemoveGlobalRoute()throws Exception {
+
+        ConcurrentMap concurrentMap = createRoutingTableCache();
+
+        Assert.assertNotNull(concurrentMap);
+        RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier =  mock(RpcRouter.RouteIdentifier.class);
+        InstanceIdentifier identifier = mock(InstanceIdentifier.class);
+        when(routeIdentifier.getContext()).thenReturn(QNAME);
+        when(routeIdentifier.getRoute()).thenReturn(identifier);
+
+        rti.addGlobalRoute(routeIdentifier, "172.27.12.1:5000");
+
+        Set<String> globalService = new HashSet<String>();
+        globalService.add("172.27.12.1:5000");
+
+        when(concurrentMap.get(routeIdentifier)).thenReturn(globalService);
+        ConcurrentMap latestCache = rti.getRoutingTableCache();
+
+        Assert.assertEquals(concurrentMap,latestCache);
+
+        Set<String> servicesGlobal =  rti.getRoutes(routeIdentifier);
+
+
+        Assert.assertEquals(servicesGlobal.size(),1);
+
+        Assert.assertEquals(servicesGlobal.iterator().next(),"172.27.12.1:5000");
+
+        rti.removeGlobalRoute(routeIdentifier);
+
+        Assert.assertNotNull(rti.getRoutes(routeIdentifier));
+
+
+    }
+
+    private ConcurrentMap createRoutingTableCache() throws Exception {
+
+        //here init
+        Component c = mock(Component.class);
+
+        when(ics.existCache(
+                RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE)).thenReturn(false);
+
+        when(ics.createCache(RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(concurrentMapMock);
+         rti.setClusterGlobalServices(this.ics);
+        rti.init(c);
+
+        Assert.assertEquals(concurrentMapMock,rti.getRoutingTableCache() );
+        return concurrentMapMock;
+
+    }
+
+
+    @Test
+    public void testCreateRoutingTableCacheReturnExistingCache() throws Exception {
+        ConcurrentMap concurrentMap = createRoutingTableCache();
+
+        //OK here we should try creating again the cache but this time it should return the existing one
+        when(ics.existCache(
+                RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE)).thenReturn(true);
+
+        when(ics.getCache(
+                RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE)).thenReturn(concurrentMap);
+
+
+        //here init
+        Component c = mock(Component.class);
+
+        rti.init(c);
+
+        Assert.assertEquals(concurrentMap,rti.getRoutingTableCache());
+
+
+
+
+
+    }
+
+    private class RouteChangeListenerImpl<I,R> implements RouteChangeListener<I,R>{
+
+        @Override
+        public void onRouteUpdated(I key, R new_value) {
+            //To change body of implemented methods use File | Settings | File Templates.
+        }
+
+        @Override
+        public void onRouteDeleted(I key) {
+            //To change body of implemented methods use File | Settings | File Templates.
+        }
+    }
+
+}
diff --git a/opendaylight/md-sal/zeromq-routingtable/integrationtest/pom.xml b/opendaylight/md-sal/zeromq-routingtable/integrationtest/pom.xml
new file mode 100644 (file)
index 0000000..308d5a9
--- /dev/null
@@ -0,0 +1,281 @@
+<?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.integrationtest</artifactId>
+    <version>0.5.1-SNAPSHOT</version>
+    <relativePath>../../../commons/integrationtest</relativePath>
+  </parent>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+    <tag>HEAD</tag>
+  </scm>
+
+  <artifactId>zeromq-routingtable.integrationtest</artifactId>
+  <version>0.4.1-SNAPSHOT</version>
+
+  <dependencies>
+    <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>zeromq-routingtable.implementation</artifactId>
+        <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>clustering.services</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal.implementation</artifactId>
+          <version>0.4.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>containermanager</artifactId>
+          <version>0.5.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>containermanager.it.implementation</artifactId>
+          <version>0.5.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>clustering.stub</artifactId>
+          <version>0.4.0-SNAPSHOT</version>
+      </dependency>
+        <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+       <groupId>org.ops4j.pax.exam</groupId>
+       <artifactId>pax-exam-container-native</artifactId>
+       <scope>test</scope>
+     </dependency>
+     <dependency>
+       <groupId>org.ops4j.pax.exam</groupId>
+       <artifactId>pax-exam-junit4</artifactId>
+       <scope>test</scope>
+     </dependency>
+     <dependency>
+        <groupId>org.ops4j.pax.exam</groupId>
+        <artifactId>pax-exam-link-mvn</artifactId>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.ops4j.pax.url</groupId>
+        <artifactId>pax-url-aether</artifactId>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>log4j-over-slf4j</artifactId>
+      </dependency>
+      <dependency>
+        <groupId>ch.qos.logback</groupId>
+        <artifactId>logback-core</artifactId>
+      </dependency>
+      <dependency>
+        <groupId>ch.qos.logback</groupId>
+        <artifactId>logback-classic</artifactId>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
+      </dependency>
+      <dependency>
+        <groupId>eclipselink</groupId>
+        <artifactId>javax.resource</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>com.google.guava</groupId>
+          <artifactId>guava</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal</artifactId>
+          <version>0.5.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>yang-binding</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>yang-common</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-connector-api</artifactId>
+          <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-common-util</artifactId>
+          <version>1.0-SNAPSHOT</version>
+      </dependency>
+
+      <dependency>
+          <groupId>junit</groupId>
+          <artifactId>junit</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-common-api</artifactId>
+          <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-common-util</artifactId>
+          <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-binding-broker-impl</artifactId>
+          <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-binding-broker-impl</artifactId>
+          <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.ops4j.pax.exam</groupId>
+          <artifactId>pax-exam-container-native</artifactId>
+          <version>${exam.version}</version>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.ops4j.pax.exam</groupId>
+          <artifactId>pax-exam-junit4</artifactId>
+          <version>${exam.version}</version>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.ops4j.pax.exam</groupId>
+          <artifactId>pax-exam-link-mvn</artifactId>
+          <version>${exam.version}</version>
+          <scope>test</scope>
+      </dependency>
+
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>config-manager</artifactId>
+          <version>0.2.3-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>equinoxSDK381</groupId>
+          <artifactId>org.eclipse.osgi</artifactId>
+          <version>3.8.1.v20120830-144521</version>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>log4j-over-slf4j</artifactId>
+          <version>1.7.2</version>
+      </dependency>
+      <dependency>
+          <groupId>ch.qos.logback</groupId>
+          <artifactId>logback-core</artifactId>
+          <version>1.0.9</version>
+      </dependency>
+      <dependency>
+          <groupId>ch.qos.logback</groupId>
+          <artifactId>logback-classic</artifactId>
+          <version>1.0.9</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+          <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+          <version>4.0</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+          <artifactId>xtend-lib-osgi</artifactId>
+          <version>2.4.3</version>
+      </dependency>
+
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>clustering.services</artifactId>
+          <version>0.4.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>junit</groupId>
+          <artifactId>junit</artifactId>
+          <scope>test</scope>
+      </dependency>
+
+      <dependency>
+          <groupId>equinoxSDK381</groupId>
+          <artifactId>org.eclipse.osgi</artifactId>
+          <version>3.8.1.v20120830-144521</version>
+      </dependency>
+      <dependency>
+          <groupId>org.ops4j.pax.exam</groupId>
+          <artifactId>pax-exam-junit4</artifactId>
+          <version>3.0.0</version>
+      </dependency>
+      <dependency>
+          <groupId>org.ops4j.pax.exam</groupId>
+          <artifactId>pax-exam-junit4</artifactId>
+          <version>3.0.0</version>
+      </dependency>
+      <dependency>
+          <groupId>org.ops4j.pax.exam</groupId>
+          <artifactId>pax-exam</artifactId>
+          <version>3.0.0</version>
+      </dependency>
+  </dependencies>
+  <properties>
+    <!-- Sonar jacoco plugin to get integration test coverage info -->
+    <sonar.jacoco.reportPath>../implementation/target/jacoco.exec</sonar.jacoco.reportPath>
+    <sonar.jacoco.itReportPath>../implementation/target/jacoco-it.exec</sonar.jacoco.itReportPath>
+  </properties>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.jacoco</groupId>
+          <artifactId>jacoco-maven-plugin</artifactId>
+          <version>0.5.3.201107060350</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+        <version>${jacoco.version}</version>
+        <configuration>
+          <destFile>../implementation/target/jacoco-it.exec</destFile>
+          <includes>org.opendaylight.controller.*</includes>
+        </configuration>
+        <executions>
+          <execution>
+            <id>pre-test</id>
+            <goals>
+              <goal>prepare-agent</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>post-test</id>
+            <configuration>
+              <skip>true</skip>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java b/opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/ZeroMQRoutingTableTestIT.java
new file mode 100644 (file)
index 0000000..3b6d398
--- /dev/null
@@ -0,0 +1,290 @@
+package org.opendaylight.controller.sal.connector.remoterpc.impl;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.util.PathUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import java.io.Serializable;
+import java.net.URI;
+import java.util.Set;
+
+
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemPackages;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
+
+
+
+@RunWith(PaxExam.class)
+public class
+        ZeroMQRoutingTableTestIT {
+    private Logger log = LoggerFactory
+            .getLogger(ZeroMQRoutingTableTestIT.class);
+
+    public static final String ODL = "org.opendaylight.controller";
+    public static final String YANG = "org.opendaylight.yangtools";
+    public static final String CONTROLLER = "org.opendaylight.controller";
+    public static final String YANGTOOLS = "org.opendaylight.yangtools";
+    // get the OSGI bundle context
+    @Inject
+    private BundleContext bc;
+    @Inject
+    private RoutingTable routingTable = null;
+
+    // Configure the OSGi container
+    @Configuration
+    public Option[] config() {
+        return options(
+                //
+                systemProperty("logback.configurationFile").value(
+                        "file:" + PathUtils.getBaseDir()
+                                + "/src/test/resources/logback.xml"),
+                // To start OSGi console for inspection remotely
+                systemProperty("osgi.console").value("2401"),
+                // Set the systemPackages (used by clustering)
+                systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
+                // List framework bundles
+
+                mavenBundle("equinoxSDK381",
+                        "org.eclipse.equinox.console").versionAsInProject(),
+                mavenBundle("equinoxSDK381",
+                        "org.eclipse.equinox.util").versionAsInProject(),
+                mavenBundle("equinoxSDK381",
+                        "org.eclipse.osgi.services").versionAsInProject(),
+                mavenBundle("equinoxSDK381",
+                        "org.eclipse.equinox.ds").versionAsInProject(),
+                mavenBundle("equinoxSDK381",
+                        "org.apache.felix.gogo.command").versionAsInProject(),
+                mavenBundle("equinoxSDK381",
+                        "org.apache.felix.gogo.runtime").versionAsInProject(),
+                mavenBundle("equinoxSDK381",
+                        "org.apache.felix.gogo.shell").versionAsInProject(),
+                // List logger bundles
+                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
+                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
+                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(),
+                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(),
+                // List all the bundles on which the test case depends
+                mavenBundle(ODL,
+                        "clustering.services").versionAsInProject(),
+
+                mavenBundle(ODL, "sal").versionAsInProject(),
+                mavenBundle(ODL,
+                        "sal.implementation").versionAsInProject(),
+                mavenBundle(ODL, "containermanager").versionAsInProject(),
+                mavenBundle(ODL,
+                        "containermanager.it.implementation").versionAsInProject(),
+                mavenBundle("org.jboss.spec.javax.transaction",
+                        "jboss-transaction-api_1.1_spec").versionAsInProject(),
+                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
+                mavenBundle("org.apache.felix",
+                        "org.apache.felix.dependencymanager").versionAsInProject(),
+                mavenBundle("org.apache.felix",
+                        "org.apache.felix.dependencymanager.shell").versionAsInProject(),
+                mavenBundle("eclipselink", "javax.resource").versionAsInProject(),
+
+                mavenBundle("com.google.guava","guava").versionAsInProject(),
+                // List logger bundles
+                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
+                mavenBundle("org.slf4j", "log4j-over-slf4j")
+                        .versionAsInProject(),
+                mavenBundle("ch.qos.logback", "logback-core")
+                        .versionAsInProject(),
+                mavenBundle("ch.qos.logback", "logback-classic")
+                        .versionAsInProject(),
+
+                mavenBundle(ODL, "clustering.services")
+                        .versionAsInProject(),
+                mavenBundle(ODL, "clustering.stub")
+                        .versionAsInProject(),
+
+
+                // List all the bundles on which the test case depends
+                mavenBundle(ODL, "sal")
+                        .versionAsInProject(),
+                mavenBundle(ODL, "sal-connector-api")
+                        .versionAsInProject(),
+                mavenBundle(ODL, "zeromq-routingtable.implementation")
+                        .versionAsInProject(),
+
+                mavenBundle("org.jboss.spec.javax.transaction",
+                        "jboss-transaction-api_1.1_spec").versionAsInProject(),
+                mavenBundle("org.apache.commons", "commons-lang3")
+                        .versionAsInProject(),
+                mavenBundle("org.apache.felix",
+                        "org.apache.felix.dependencymanager")
+                        .versionAsInProject(),
+
+                mavenBundle(ODL,
+                        "sal-core-api")
+                        .versionAsInProject(),
+                mavenBundle("org.opendaylight.yangtools","yang-data-api")
+                        .versionAsInProject(),
+                mavenBundle("org.opendaylight.yangtools","yang-model-api")
+                        .versionAsInProject(),
+                mavenBundle("org.opendaylight.yangtools","yang-binding")
+                        .versionAsInProject(),
+
+                mavenBundle(CONTROLLER, "sal-binding-api").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(),
+                mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), //
+                mavenBundle("org.javassist", "javassist").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), //
+
+                mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+
+
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
+
+
+                mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
+                mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
+
+                mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
+
+                mavenBundle(YANG, "concepts").versionAsInProject(),
+                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
+                mavenBundle(YANG, "yang-common").versionAsInProject(), //
+                mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(),
+                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
+                mavenBundle("org.javassist", "javassist").versionAsInProject(),
+                mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
+                mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
+                mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
+                mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
+
+                mavenBundle(ODL, "sal-common").versionAsInProject(), //
+                mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
+                mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
+                mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
+
+                mavenBundle(ODL, "config-api").versionAsInProject(), //
+                mavenBundle(ODL, "config-manager").versionAsInProject(), //
+                mavenBundle("commons-io", "commons-io").versionAsInProject(),
+                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
+
+                mavenBundle(ODL, "sal-binding-api").versionAsInProject(), //
+                mavenBundle(ODL, "sal-binding-config").versionAsInProject(),
+                mavenBundle("org.javassist", "javassist").versionAsInProject(), //
+                mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
+
+                mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
+                mavenBundle(YANG, "yang-data-impl").versionAsInProject(), //
+                mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
+                mavenBundle(YANG, "yang-model-util").versionAsInProject(), //
+                mavenBundle(YANG, "yang-parser-api").versionAsInProject(),
+                mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
+
+
+                mavenBundle(YANG, "binding-generator-spi").versionAsInProject(), //
+                mavenBundle(YANG, "binding-model-api").versionAsInProject(), //
+                mavenBundle(YANG, "binding-generator-util").versionAsInProject(),
+                mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
+                mavenBundle(YANG, "binding-type-provider").versionAsInProject(),
+                mavenBundle(YANG, "binding-generator-api").versionAsInProject(),
+                mavenBundle(YANG, "binding-generator-spi").versionAsInProject(),
+                mavenBundle(YANG, "binding-generator-impl").versionAsInProject(),
+
+
+                mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
+                mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
+                mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
+
+                mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
+
+                mavenBundle(YANG, "concepts").versionAsInProject(),
+                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
+                mavenBundle(YANG, "yang-common").versionAsInProject(), //
+                mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(),
+                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
+                mavenBundle("org.javassist", "javassist").versionAsInProject(),
+
+                junitBundles());
+    }
+
+    private String stateToString(int state) {
+        switch (state) {
+            case Bundle.ACTIVE:
+                return "ACTIVE";
+            case Bundle.INSTALLED:
+                return "INSTALLED";
+            case Bundle.RESOLVED:
+                return "RESOLVED";
+            case Bundle.UNINSTALLED:
+                return "UNINSTALLED";
+            default:
+                return "Not CONVERTED";
+        }
+    }
+
+    @Test
+  public  void testAddGlobalRoute () throws Exception{
+       RoutingIdentifierImpl rii  = new RoutingIdentifierImpl();
+       routingTable.addGlobalRoute(rii,"172.27.12.1:5000");
+
+       Set<String> routes = routingTable.getRoutes(rii);
+
+       for(String route:routes){
+           Assert.assertEquals(route,"172.27.12.1:5000");
+       }
+
+
+    }
+
+
+   class RoutingIdentifierImpl implements RpcRouter.RouteIdentifier,Serializable {
+
+       private final URI namespace = URI.create("http://cisco.com/example");
+       private final QName QNAME = new QName(namespace,"global");
+       private final QName instance = new QName(URI.create("127.0.0.1"),"local");
+
+       @Override
+       public QName getContext() {
+           return QNAME;
+       }
+
+       @Override
+       public QName getType() {
+           return QNAME;
+       }
+
+       @Override
+       public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier getRoute() {
+           return InstanceIdentifier.of(instance);
+       }
+   }
+
+
+
+
+
+}
diff --git a/opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/resources/logback.xml b/opendaylight/md-sal/zeromq-routingtable/integrationtest/src/test/resources/logback.xml
new file mode 100644 (file)
index 0000000..6d9dfda
--- /dev/null
@@ -0,0 +1,12 @@
+<configuration scan="true">
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+      </pattern>
+    </encoder>
+  </appender>
+
+  <root level="error">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>