Merge "Bug:129 Connection Manager Dashlet"
authorGiovanni Meo <gmeo@cisco.com>
Thu, 7 Nov 2013 14:10:26 +0000 (14:10 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 7 Nov 2013 14:10:26 +0000 (14:10 +0000)
134 files changed:
README.OPENDAYLIGHT
opendaylight/commons/checkstyle/src/main/resources/controller/checkstyle.xml
opendaylight/config/pom.xml
opendaylight/config/threadpool-config-api/pom.xml [new file with mode: 0644]
opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ScheduledThreadPool.java [new file with mode: 0644]
opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ThreadPool.java [new file with mode: 0644]
opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/pom.xml [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableAsyncEventBus.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableEventBus.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FixedThreadPoolWrapper.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/NamingThreadPoolFactory.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/ScheduledThreadPoolWrapper.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModule.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModuleFactory.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModule.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModuleFactory.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModule.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModuleFactory.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModule.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModuleFactory.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModule.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModuleFactory.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModule.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModuleFactory.java [new file with mode: 0644]
opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl.yang [new file with mode: 0644]
opendaylight/distribution/opendaylight/pom.xml
opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml [moved from opendaylight/md-sal/flow-management-compatibility/pom.xml with 94% similarity]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend [moved from opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FRMRuntimeDataProvider.xtend with 98% similarity]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend [moved from opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowConfigMapping.xtend with 89% similarity]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java [moved from opendaylight/md-sal/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/FlowManagementReader.java with 100% similarity]
opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml [new file with mode: 0644]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.xtend [new file with mode: 0644]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.xtend [new file with mode: 0644]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.xtend [new file with mode: 0644]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.xtend [new file with mode: 0644]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.xtend [new file with mode: 0644]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.xtend [new file with mode: 0644]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.xtend [new file with mode: 0644]
opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.xtend [new file with mode: 0644]
opendaylight/md-sal/compatibility/pom.xml [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/pom.xml [moved from opendaylight/md-sal/sal-compability/pom.xml with 65% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ComponentActivator.xtend [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ComponentActivator.xtend with 97% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/DataPacketAdapter.xtend [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/DataPacketAdapter.xtend with 93% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FlowProgrammerAdapter.xtend [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/FlowProgrammerAdapter.xtend with 93% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/FromSalConversionsUtils.java with 98% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryAndReadAdapter.xtend [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/InventoryAndReadAdapter.xtend with 98% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/MDFlowMapping.xtend [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/MDFlowMapping.xtend with 98% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/NodeMapping.xtend with 98% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ProtocolConstants.java [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ProtocolConstants.java with 88% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/ToSalConversionsUtils.java [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalConversionsUtils.java with 98% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/DataPacketServiceAdapter.java [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/DataPacketServiceAdapter.java with 92% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowStatisticsAdapter.java [moved from opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowStatisticsAdapter.java with 98% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestFromSalConversionsUtils.java [moved from opendaylight/md-sal/sal-compability/src/test/java/org/opendaylight/controller/sal/compability/TestFromSalConversionsUtils.java with 85% similarity]
opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/TestToSalConversionsUtils.java [moved from opendaylight/md-sal/sal-compability/src/test/java/org/opendaylight/controller/sal/compability/TestToSalConversionsUtils.java with 82% similarity]
opendaylight/md-sal/model/model-topology/pom.xml [new file with mode: 0644]
opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang [new file with mode: 0644]
opendaylight/md-sal/model/pom.xml
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-api/pom.xml
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-util/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-binding-util/src/main/java/org/opendaylight/controller/md/sal/binding/util/TypeSafeDataReader.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-impl/pom.xml
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java [new file with mode: 0644]
opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalPropertyClassUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowServiceAdapter.java [deleted file]
opendaylight/md-sal/sal-connector-api/src/main/java/org/opendaylight/controller/sal/connector/api/RpcRouter.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/data/DataProviderService.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/pom.xml
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ProviderContextImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/pom.xml
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversion.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/simple-yang-types.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/data.xml [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/pom.xml [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Activator.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Message.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RouteIdentifierImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcReplyImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcRequestImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/ZeroMqRpcRouter.java [new file with mode: 0644]
opendaylight/md-sal/samples/pom.xml
opendaylight/md-sal/test/pom.xml [new file with mode: 0644]
opendaylight/md-sal/test/zeromq-test-consumer/pom.xml [new file with mode: 0644]
opendaylight/md-sal/test/zeromq-test-consumer/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java [new file with mode: 0644]
opendaylight/md-sal/test/zeromq-test-it/pom.xml [new file with mode: 0644]
opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceConsumerController.java [new file with mode: 0644]
opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceProviderController.java [new file with mode: 0644]
opendaylight/md-sal/test/zeromq-test-provider/pom.xml [new file with mode: 0644]
opendaylight/md-sal/test/zeromq-test-provider/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java
opendaylight/netconf/config-persister-impl/src/main/resources/netconfOp/editConfig.xml
opendaylight/netconf/pom.xml
opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Bandwidth.java
opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SubnetConfig.java
pom.xml
third-party/commons/thirdparty/pom.xml
third-party/ganymed/pom.xml [new file with mode: 0644]
third-party/ganymed/src/main/java/ch/ethz/ssh2/Connection.java [new file with mode: 0644]
third-party/ganymed/src/main/java/ch/ethz/ssh2/transport/TransportManager.java [new file with mode: 0644]

index e85aa31b7be2088cc20487e93ff0ed3fe21e4bdc..78d54a7e87fa7288fdf912e76406a0d76b0cde33 100644 (file)
@@ -21,12 +21,20 @@ HOW TO BUILD
 ============
 In order to build it's required to have JDK 1.7+ and Maven 3+, to get
 a build going it's needed to:
-1) Choose the distribution, from within opendaylight/distribution
-2) Go in the directory and run
+1) From the root directory run
    "mvn clean install"
-3) On succesfull completion go in the target directory to pick the zip
-file of the distribution or controller can be executed right from
-there going into the distribution directory.
+2) On succesfull completion go in the directory:
+"opendaylight/distribution/opendaylight/target"
+
+to pick the zip file of the distribution or controller can be executed
+right from there going into the distribution directory.
+
+Please note that this way no integration tests but only UT will be
+executed, if you are planning on committing code be aware that the
+code will be tested also for Integrations tests hence make sure before
+submitting a patch to build using the command:
+   "mvn clean install -Pintegrationtests"
+to get IT executed.
 
 HOW TO RELEASE ARTIFACTS
 ========================
index c810d6523a0832fcb15da4a369e6ec2463c49339..57f169db730806a837d93eb73ffe245b61f0eb25 100644 (file)
@@ -18,6 +18,7 @@
        <module name="UnusedImports"/>\r
        <module name="AvoidStarImport"/>\r
        <module name="UpperEll"/>\r
+       <module name="EmptyStatement"/>\r
     </module>\r
 \r
 </module>\r
index 949c283f7de3ce0ce877a3c433246523efdde426..9db5b769887704d97a5eab02653dea9f9418489d 100755 (executable)
         <module>config-persister-file-adapter</module>
         <module>yang-jmx-generator</module>
         <module>yang-jmx-generator-plugin</module>
-        <module>yang-jmx-generator-it</module>
         <module>yang-store-api</module>
         <module>yang-store-impl</module>
         <module>yang-test</module>
         <module>logback-config</module>
+        <module>threadpool-config-api</module>
+        <module>threadpool-config-impl</module>
     </modules>
+
+    <profiles>
+      <profile>
+        <id>integrationtests</id>
+        <activation>
+          <activeByDefault>false</activeByDefault>
+        </activation>
+        <modules>
+          <module>yang-jmx-generator-it</module>
+        </modules>
+      </profile>
+    </profiles>
+
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <java.version.source>1.7</java.version.source>
diff --git a/opendaylight/config/threadpool-config-api/pom.xml b/opendaylight/config/threadpool-config-api/pom.xml
new file mode 100644 (file)
index 0000000..b991b69
--- /dev/null
@@ -0,0 +1,51 @@
+<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">
+   <parent>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-subsystem</artifactId>
+      <version>0.2.2-SNAPSHOT</version>
+   </parent>
+   <modelVersion>4.0.0</modelVersion>
+   <artifactId>threadpool-config-api</artifactId>
+   <name>${project.artifactId}</name>
+   <packaging>bundle</packaging>
+   <prerequisites>
+      <maven>3.0.4</maven>
+   </prerequisites>
+
+   <dependencies>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-api</artifactId>
+      </dependency>
+      <dependency>
+         <groupId>com.google.guava</groupId>
+         <artifactId>guava</artifactId>
+      </dependency>
+   </dependencies>
+
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>maven-bundle-plugin</artifactId>
+            <configuration>
+               <instructions>
+                  <Import-Package>
+                     org.opendaylight.controller.config.api.*,
+                     com.google.common.eventbus,
+                  </Import-Package>
+                  <Export-Package>
+                     org.opendaylight.controller.config.threadpool,
+                     org.opendaylight.controller.config.yang.threadpool
+                  </Export-Package>
+               </instructions>
+            </configuration>
+         </plugin>
+         <plugin>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-maven-plugin</artifactId>
+         </plugin>
+      </plugins>
+   </build>
+</project>
\ No newline at end of file
diff --git a/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ScheduledThreadPool.java b/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ScheduledThreadPool.java
new file mode 100644 (file)
index 0000000..bf6c016
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.threadpool;
+
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * Interface representing scheduled {@link ThreadPool}.
+ */
+public interface ScheduledThreadPool extends ThreadPool {
+
+    @Override
+    public ScheduledExecutorService getExecutor();
+}
\ No newline at end of file
diff --git a/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ThreadPool.java b/opendaylight/config/threadpool-config-api/src/main/java/org/opendaylight/controller/config/threadpool/ThreadPool.java
new file mode 100644 (file)
index 0000000..701b0bc
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.threadpool;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Interface representing thread pool.
+ */
+public interface ThreadPool {
+
+    public ExecutorService getExecutor();
+
+    public int getMaxThreadCount();
+}
\ No newline at end of file
diff --git a/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang b/opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang
new file mode 100644 (file)
index 0000000..14a20fd
--- /dev/null
@@ -0,0 +1,77 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module threadpool {
+       yang-version 1;
+       namespace "urn:opendaylight:params:xml:ns:yang:controller:threadpool";
+       prefix "th";
+
+       import config { prefix config; revision-date 2013-04-05; }
+
+       organization "Cisco Systems, Inc.";
+
+       contact "Robert Varga <rovarga@cisco.com>";
+
+    description
+        "This module contains the base YANG definitions for
+         thread-related services.
+
+        Copyright (c)2013 Cisco Systems, Inc. All rights reserved.;
+        
+        This program and the accompanying materials are made available
+               under the terms of the Eclipse Public License v1.0 which
+               accompanies this distribution, and is available at
+               http://www.eclipse.org/legal/epl-v10.html";
+
+    revision "2013-04-09" {
+        description
+            "Added eventbus service.";
+    }
+
+    revision "2013-04-05" {
+        description
+            "Updated with YANG extension for Java class specification.";
+    }
+
+    revision "2013-04-03" {
+        description
+            "Initial revision by Anton Tkacik, Tomas Olvecky and
+             Robert Varga.";
+    }
+
+    identity eventbus {
+        description
+            "Service representing an event bus. The service acts as message
+             router between event producers and event consumers";
+
+        base "config:service-type";
+        config:java-class "com.google.common.eventbus.EventBus";
+    }
+
+    identity threadfactory {
+        description
+            "Service representing a ThreadFactory instance. It is directly
+             useful in Java world, where various library pieces need to create
+             threads and you may want to inject a customized thread
+             implementation.";
+
+        base "config:service-type";
+        config:java-class "java.util.concurrent.ThreadFactory";
+    }
+
+       identity threadpool {
+        description
+            "A simple pool of threads able to execute work.";
+
+               base "config:service-type";
+        config:java-class "org.opendaylight.controller.config.threadpool.ThreadPool";
+       }
+
+       identity scheduled-threadpool {
+        description
+            "An extension of the simple pool of threads able to schedule
+             work to be executed at some point in time.";
+
+               base "threadpool";
+        config:java-class "org.opendaylight.controller.config.threadpool.ScheduledThreadPool";
+       }
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/pom.xml b/opendaylight/config/threadpool-config-impl/pom.xml
new file mode 100644 (file)
index 0000000..1227978
--- /dev/null
@@ -0,0 +1,76 @@
+<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">
+   <parent>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-subsystem</artifactId>
+      <version>0.2.2-SNAPSHOT</version>
+   </parent>
+   <modelVersion>4.0.0</modelVersion>
+   <artifactId>threadpool-config-impl</artifactId>
+   <name>${project.artifactId}</name>
+   <packaging>bundle</packaging>
+   <prerequisites>
+      <maven>3.0.4</maven>
+   </prerequisites>
+
+   <dependencies>
+      <dependency>
+         <groupId>${project.groupId}</groupId>
+         <artifactId>config-api</artifactId>
+      </dependency>
+      <dependency>
+         <groupId>${project.groupId}</groupId>
+         <artifactId>threadpool-config-api</artifactId>
+         <version>${project.version}</version>
+      </dependency>
+      <dependency>
+         <groupId>com.google.guava</groupId>
+         <artifactId>guava</artifactId>
+      </dependency>
+      <dependency>
+         <groupId>org.slf4j</groupId>
+         <artifactId>slf4j-api</artifactId>
+      </dependency>
+   </dependencies>
+
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>maven-bundle-plugin</artifactId>
+            <configuration>
+               <instructions>
+                  <Private-Package>
+                     org.opendaylight.controller.config.threadpool.util,
+                     javax.annotation.*,
+                     org.opendaylight.controller.config.yang.threadpool.impl,
+                  </Private-Package>
+                  <Import-Package>
+                     org.opendaylight.controller.config.api.*,
+                     org.opendaylight.controller.config.spi.*,
+                     org.opendaylight.controller.config.threadpool,
+                     org.opendaylight.controller.config.yang.threadpool,
+                     javax.management,
+                     org.osgi.framework,
+                     org.slf4j,
+                     com.google.common.*
+                  </Import-Package>
+                  <Export-Package>
+                     org.opendaylight.controller.config.threadpool.util
+                  </Export-Package>
+               </instructions>
+            </configuration>
+         </plugin>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-jar-plugin</artifactId>
+         </plugin>
+
+         <plugin>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-maven-plugin</artifactId>
+         </plugin>
+      </plugins>
+   </build>
+
+</project>
\ No newline at end of file
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableAsyncEventBus.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableAsyncEventBus.java
new file mode 100644 (file)
index 0000000..93a08da
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.threadpool.util;
+
+import com.google.common.eventbus.AsyncEventBus;
+import com.google.common.eventbus.DeadEvent;
+import com.google.common.eventbus.Subscribe;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.opendaylight.controller.config.threadpool.ThreadPool;
+import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusRuntimeMXBean;
+import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusRuntimeRegistration;
+import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusRuntimeRegistrator;
+
+/**
+ * Closeable version of {@link AsyncEventBus}.
+ */
+public class CloseableAsyncEventBus extends AsyncEventBus implements Closeable {
+    private final ThreadPool threadPool;
+    private final AsyncEventBusRuntimeRegistration rootRegistration;
+
+    public CloseableAsyncEventBus(String identifier, ThreadPool threadPool,
+            AsyncEventBusRuntimeRegistrator rootRegistrator) {
+        super(identifier, threadPool.getExecutor());
+        this.threadPool = threadPool;
+        rootRegistration = rootRegistrator.register(new AsyncEventBusRuntimeMXBean() {
+            private long deadEventsCounter = 0;
+
+            @Subscribe
+            public void increaseDeadEvents(DeadEvent deadEvent) {
+                deadEventsCounter++;
+            }
+
+            @Override
+            public Long countDeadEvents() {
+                return deadEventsCounter;
+            }
+
+        });
+    }
+
+    public ThreadPool getThreadPool() {
+        return threadPool;
+    }
+
+    @Override
+    public void close() throws IOException {
+        rootRegistration.close();
+    }
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableEventBus.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/CloseableEventBus.java
new file mode 100644 (file)
index 0000000..b6dd77d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.threadpool.util;
+
+import java.io.Closeable;
+
+import org.opendaylight.controller.config.yang.threadpool.impl.EventBusRuntimeMXBean;
+import org.opendaylight.controller.config.yang.threadpool.impl.EventBusRuntimeRegistration;
+import org.opendaylight.controller.config.yang.threadpool.impl.EventBusRuntimeRegistrator;
+
+import com.google.common.eventbus.DeadEvent;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+/**
+ * Closeable {@link EventBus}.
+ */
+public class CloseableEventBus extends EventBus implements Closeable {
+
+    private final EventBusRuntimeRegistration rootRegistration;
+
+    public CloseableEventBus(String identifier, EventBusRuntimeRegistrator rootRegistrator) {
+        super(identifier);
+        rootRegistration = rootRegistrator.register(new EventBusRuntimeMXBean() {
+            private long deadEventsCounter = 0;
+
+            @Subscribe
+            public void increaseDeadEvents(DeadEvent deadEvent) {
+                deadEventsCounter++;
+            }
+
+            @Override
+            public Long countDeadEvents() {
+                return deadEventsCounter;
+            }
+        });
+
+    }
+
+    @Override
+    public void close() {
+        rootRegistration.close();
+
+    }
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FixedThreadPoolWrapper.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FixedThreadPoolWrapper.java
new file mode 100644 (file)
index 0000000..ca03443
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.threadpool.util;
+
+import java.io.Closeable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.opendaylight.controller.config.threadpool.ThreadPool;
+
+/**
+ * Implementation of {@link ThreadPool} using fixed number of threads wraps
+ * {@link ExecutorService}.
+ */
+public class FixedThreadPoolWrapper implements ThreadPool, Closeable {
+
+    private final ThreadPoolExecutor executor;
+
+    public FixedThreadPoolWrapper(int threadCount, ThreadFactory factory) {
+        this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(threadCount, factory);
+        executor.prestartAllCoreThreads();
+    }
+
+    @Override
+    public ExecutorService getExecutor() {
+        return Executors.unconfigurableExecutorService(executor);
+    }
+
+    @Override
+    public void close() {
+        executor.shutdown();
+    }
+
+    @Override
+    public int getMaxThreadCount() {
+        return executor.getMaximumPoolSize();
+    }
+
+    public void setMaxThreadCount(int maxThreadCount) {
+        executor.setCorePoolSize(maxThreadCount);
+        executor.setMaximumPoolSize(maxThreadCount);
+    }
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/FlexibleThreadPoolWrapper.java
new file mode 100644 (file)
index 0000000..3dfa6e2
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.threadpool.util;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.config.threadpool.ThreadPool;
+
+/**
+ * Implementation of {@link ThreadPool} using flexible number of threads wraps
+ * {@link ExecutorService}.
+ */
+public class FlexibleThreadPoolWrapper implements ThreadPool, Closeable {
+    private final ThreadPoolExecutor executor;
+
+    public FlexibleThreadPoolWrapper(int minThreadCount, int maxThreadCount, long keepAlive, TimeUnit timeUnit,
+            ThreadFactory threadFactory) {
+
+        executor = new ThreadPoolExecutor(minThreadCount, maxThreadCount, keepAlive, timeUnit,
+                new SynchronousQueue<Runnable>(), threadFactory);
+        executor.prestartAllCoreThreads();
+    }
+
+    @Override
+    public ExecutorService getExecutor() {
+        return Executors.unconfigurableExecutorService(executor);
+    }
+
+    public int getMinThreadCount() {
+        return executor.getCorePoolSize();
+    }
+
+    public void setMinThreadCount(int minThreadCount) {
+        executor.setCorePoolSize(minThreadCount);
+    }
+
+    @Override
+    public int getMaxThreadCount() {
+        return executor.getMaximumPoolSize();
+    }
+
+    public void setMaxThreadCount(int maxThreadCount) {
+        executor.setMaximumPoolSize(maxThreadCount);
+    }
+
+    public long getKeepAliveMillis() {
+        return executor.getKeepAliveTime(TimeUnit.MILLISECONDS);
+    }
+
+    public void setKeepAliveMillis(long keepAliveMillis) {
+        executor.setKeepAliveTime(keepAliveMillis, TimeUnit.MILLISECONDS);
+    }
+
+    public void setThreadFactory(ThreadFactory threadFactory) {
+        executor.setThreadFactory(threadFactory);
+    }
+
+    public void prestartAllCoreThreads() {
+        executor.prestartAllCoreThreads();
+    }
+
+    @Override
+    public void close() throws IOException {
+        executor.shutdown();
+    }
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/NamingThreadPoolFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/NamingThreadPoolFactory.java
new file mode 100644 (file)
index 0000000..2e27d6c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.threadpool.util;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Implementation of {@link ThreadFactory}.
+ */
+@ThreadSafe
+public class NamingThreadPoolFactory implements ThreadFactory, Closeable {
+
+    private final ThreadGroup group;
+    private final String namePrefix;
+    private final AtomicLong threadName = new AtomicLong();
+
+    public NamingThreadPoolFactory(String namePrefix) {
+        Preconditions.checkNotNull(namePrefix);
+        this.group = new ThreadGroup(namePrefix);
+        this.namePrefix = namePrefix;
+    }
+
+    @Override
+    public Thread newThread(Runnable r) {
+        return new Thread(group, r, String.format("%s-%d", group.getName(), threadName.incrementAndGet()));
+    }
+
+    @Override
+    public void close() throws IOException {
+    }
+
+    public String getNamePrefix() {
+        return namePrefix;
+    }
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/ScheduledThreadPoolWrapper.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/threadpool/util/ScheduledThreadPoolWrapper.java
new file mode 100644 (file)
index 0000000..ee3399e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.threadpool.util;
+
+import java.io.Closeable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+
+import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
+
+/**
+ * Implementation of {@link ScheduledThreadPool} wraps
+ * {@link ScheduledExecutorService}.
+ */
+public class ScheduledThreadPoolWrapper implements ScheduledThreadPool, Closeable {
+
+    private final ScheduledThreadPoolExecutor executor;
+    private final int threadCount;
+
+    public ScheduledThreadPoolWrapper(int threadCount, ThreadFactory factory) {
+        this.threadCount = threadCount;
+        this.executor = new ScheduledThreadPoolExecutor(threadCount, factory);
+        executor.prestartAllCoreThreads();
+    }
+
+    @Override
+    public ScheduledExecutorService getExecutor() {
+        return Executors.unconfigurableScheduledExecutorService(executor);
+    }
+
+    @Override
+    public void close() {
+        executor.shutdown();
+    }
+
+    @Override
+    public int getMaxThreadCount() {
+        return threadCount;
+    }
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModule.java
new file mode 100644 (file)
index 0000000..f108303
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: async-eventbus
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Tue Nov 05 15:40:46 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+import org.opendaylight.controller.config.threadpool.util.CloseableAsyncEventBus;
+
+/**
+*
+*/
+public final class AsyncEventBusModule extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractAsyncEventBusModule {
+
+    public AsyncEventBusModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public AsyncEventBusModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            AsyncEventBusModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+        // Add custom validation for module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new CloseableAsyncEventBus(getIdentifier().toString(), getThreadpoolDependency(),
+                getRootRuntimeBeanRegistratorWrapper());
+    }
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/AsyncEventBusModuleFactory.java
new file mode 100644 (file)
index 0000000..14fcf41
--- /dev/null
@@ -0,0 +1,18 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: async-eventbus
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Tue Nov 05 15:40:46 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+/**
+*
+*/
+public class AsyncEventBusModuleFactory extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractAsyncEventBusModuleFactory {
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModule.java
new file mode 100644 (file)
index 0000000..92eaee5
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: eventbus
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Tue Nov 05 15:40:46 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+import org.opendaylight.controller.config.threadpool.util.CloseableEventBus;
+
+/**
+*
+*/
+public final class EventBusModule extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractEventBusModule {
+
+    public EventBusModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public EventBusModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, EventBusModule oldModule,
+            java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+        // Add custom validation for module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new CloseableEventBus(getIdentifier().toString(), getRootRuntimeBeanRegistratorWrapper());
+    }
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/EventBusModuleFactory.java
new file mode 100644 (file)
index 0000000..e909998
--- /dev/null
@@ -0,0 +1,18 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: eventbus
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Tue Nov 05 15:40:46 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+/**
+*
+*/
+public class EventBusModuleFactory extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractEventBusModuleFactory {
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModule.java
new file mode 100644 (file)
index 0000000..a0a9add
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: threadpool-fixed
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Wed Nov 06 16:19:33 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.controller.config.threadpool.util.FixedThreadPoolWrapper;
+
+/**
+*
+*/
+public final class FixedThreadPoolModule extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractFixedThreadPoolModule {
+
+    public FixedThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public FixedThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            FixedThreadPoolModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+
+        JmxAttributeValidationException.checkNotNull(getMaxThreadCount(), maxThreadCountJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getMaxThreadCount() > 0, "must be greater than zero",
+                maxThreadCountJmxAttribute);
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new FixedThreadPoolWrapper(getMaxThreadCount(), getThreadFactoryDependency());
+    }
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FixedThreadPoolModuleFactory.java
new file mode 100644 (file)
index 0000000..2803448
--- /dev/null
@@ -0,0 +1,18 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: threadpool-fixed
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Wed Nov 06 16:19:33 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+/**
+*
+*/
+public class FixedThreadPoolModuleFactory extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractFixedThreadPoolModuleFactory {
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModule.java
new file mode 100644 (file)
index 0000000..47b4eec
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: threadpool-flexible
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Wed Nov 06 16:19:33 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.controller.config.threadpool.util.FlexibleThreadPoolWrapper;
+
+/**
+*
+*/
+public final class FlexibleThreadPoolModule extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractFlexibleThreadPoolModule {
+
+    public FlexibleThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public FlexibleThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            FlexibleThreadPoolModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+        JmxAttributeValidationException.checkNotNull(getKeepAliveMillis(), keepAliveMillisJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getKeepAliveMillis() > 0, "must be greater than zero",
+                keepAliveMillisJmxAttribute);
+
+        JmxAttributeValidationException.checkNotNull(getMinThreadCount(), minThreadCountJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getMinThreadCount() > 0, "must be greater than zero",
+                minThreadCountJmxAttribute);
+
+        JmxAttributeValidationException.checkNotNull(getMaxThreadCount(), maxThreadCountJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getMaxThreadCount() > 0, "must be greater than zero",
+                maxThreadCountJmxAttribute);
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new FlexibleThreadPoolWrapper(getMinThreadCount(), getMaxThreadCount(), getKeepAliveMillis(),
+                TimeUnit.MILLISECONDS, getThreadFactoryDependency());
+    }
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/FlexibleThreadPoolModuleFactory.java
new file mode 100644 (file)
index 0000000..ef6ebd2
--- /dev/null
@@ -0,0 +1,18 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: threadpool-flexible
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Wed Nov 06 16:19:33 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+/**
+*
+*/
+public class FlexibleThreadPoolModuleFactory extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractFlexibleThreadPoolModuleFactory {
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModule.java
new file mode 100644 (file)
index 0000000..a761727
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: threadfactory-naming
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Wed Nov 06 16:19:33 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.controller.config.threadpool.util.NamingThreadPoolFactory;
+
+/**
+*
+*/
+public final class NamingThreadFactoryModule extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractNamingThreadFactoryModule {
+
+    public NamingThreadFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public NamingThreadFactoryModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            NamingThreadFactoryModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+        JmxAttributeValidationException.checkNotNull(getNamePrefix(), namePrefixJmxAttribute);
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new NamingThreadPoolFactory(getNamePrefix());
+    }
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/NamingThreadFactoryModuleFactory.java
new file mode 100644 (file)
index 0000000..5e70afb
--- /dev/null
@@ -0,0 +1,18 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: threadfactory-naming
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Wed Nov 06 16:19:33 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+/**
+*
+*/
+public class NamingThreadFactoryModuleFactory extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractNamingThreadFactoryModuleFactory {
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModule.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModule.java
new file mode 100644 (file)
index 0000000..42739b4
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: threadpool-scheduled
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Wed Nov 06 16:19:33 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
+import org.opendaylight.controller.config.threadpool.util.ScheduledThreadPoolWrapper;
+
+/**
+*
+*/
+public final class ScheduledThreadPoolModule extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractScheduledThreadPoolModule {
+
+    public ScheduledThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public ScheduledThreadPoolModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            ScheduledThreadPoolModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+        JmxAttributeValidationException.checkNotNull(getMaxThreadCount(), maxThreadCountJmxAttribute);
+        JmxAttributeValidationException.checkCondition(getMaxThreadCount() > 0, "must be greater than zero",
+                maxThreadCountJmxAttribute);
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new ScheduledThreadPoolWrapper(getMaxThreadCount(), getThreadFactoryDependency());
+    }
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModuleFactory.java b/opendaylight/config/threadpool-config-impl/src/main/java/org/opendaylight/controller/config/yang/threadpool/impl/ScheduledThreadPoolModuleFactory.java
new file mode 100644 (file)
index 0000000..489af82
--- /dev/null
@@ -0,0 +1,18 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: threadpool-impl  yang module local name: threadpool-scheduled
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Wed Nov 06 16:19:33 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.threadpool.impl;
+
+/**
+*
+*/
+public class ScheduledThreadPoolModuleFactory extends
+        org.opendaylight.controller.config.yang.threadpool.impl.AbstractScheduledThreadPoolModuleFactory {
+
+}
diff --git a/opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl.yang b/opendaylight/config/threadpool-config-impl/src/main/yang/threadpool-impl.yang
new file mode 100644 (file)
index 0000000..a2366f2
--- /dev/null
@@ -0,0 +1,195 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module threadpool-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl";
+    prefix "th-java";
+
+    import threadpool { prefix th; revision-date 2013-04-09; }
+    import config { prefix config; revision-date 2013-04-05; }
+    import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+
+    organization "Cisco Systems, Inc.";
+
+    contact "Robert Varga <rovarga@cisco.com>";
+
+    description
+        "This module contains the base YANG definitions for
+         thread services pure Java implementation.
+
+        Copyright (c)2013 Cisco Systems, Inc. All rights reserved.;
+        
+        This program and the accompanying materials are made available
+               under the terms of the Eclipse Public License v1.0 which
+               accompanies this distribution, and is available at
+               http://www.eclipse.org/legal/epl-v10.html";
+
+    revision "2013-04-05" {
+        description
+            "Updated to work with new anchors.";
+    }
+
+    revision "2013-04-03" {
+        description
+            "Initial revision by Anton Tkacik, Tomas Olvecky and
+             Robert Varga.";
+    }
+
+    identity eventbus {
+        base config:module-type;
+        config:provided-service th:eventbus;
+        config:java-name-prefix EventBus;
+    }
+
+       augment "/config:modules/config:module/config:configuration" {
+               case eventbus {
+                       when "/config:modules/config:module/config:type = 'eventbus'";
+                       // No real configuration
+        }
+    }
+
+       augment "/config:modules/config:module/config:state" {
+               case eventbus {
+                       when "/config:modules/config:module/config:type = 'eventbus'";
+                       rpcx:rpc-context-instance "event-bus-rpc";
+        }
+    }
+
+       identity event-bus-rpc;
+
+    identity async-eventbus {
+        base config:module-type;
+        config:provided-service th:eventbus;
+        config:java-name-prefix AsyncEventBus;
+    }
+
+       augment "/config:modules/config:module/config:configuration" {
+               case async-eventbus {
+                       when "/config:modules/config:module/config:type = 'async-eventbus'";
+                       container threadpool {
+                               uses config:service-ref {
+                                       refine type {
+                                               //mandatory true;
+                                               config:required-identity th:threadpool;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       augment "/config:modules/config:module/config:state" {
+               case async-eventbus {
+                       when "/config:modules/config:module/config:type = 'async-eventbus'";
+                       rpcx:rpc-context-instance "event-bus-rpc";
+        }
+    }
+
+       rpc get-dead-events-count {
+               config:java-name-prefix countDeadEvents;
+               input {
+                       uses rpcx:rpc-context-ref {
+                               refine context-instance {
+                                       rpcx:rpc-context-instance event-bus-rpc;
+                               }
+                       }
+               }
+               output {
+                       leaf result {
+                               type uint32;
+                       }
+               }
+       }
+       
+       identity threadfactory-naming {
+        base config:module-type;
+               config:provided-service th:threadfactory;
+        config:java-name-prefix NamingThreadFactory;
+    }
+
+       augment "/config:modules/config:module/config:configuration" {
+               case threadfactory-naming {
+                       when "/config:modules/config:module/config:type = 'threadfactory-naming'";
+                       leaf name-prefix {
+                               type string;
+                       }
+        }
+    }
+
+    identity threadpool-fixed {
+       base config:module-type;
+       config:provided-service th:threadpool;
+       config:java-name-prefix FixedThreadPool;
+    }
+
+       augment "/config:modules/config:module/config:configuration" {
+               case threadpool-fixed {
+                       when "/config:modules/config:module/config:type = 'threadpool-fixed'";
+                       leaf max-thread-count {
+                               type uint16;
+                       }
+
+                       container threadFactory {
+                               uses config:service-ref {
+                                       refine type {
+                                               //mandatory true;
+                                               config:required-identity th:threadfactory;
+                                       }
+                               }
+                       }
+        }
+       }
+
+       identity threadpool-flexible {
+               base config:module-type;
+               config:provided-service th:threadpool;
+               config:java-name-prefix FlexibleThreadPool;
+       }
+
+       augment "/config:modules/config:module/config:configuration" {
+               case threadpool-flexible {
+                       when "/config:modules/config:module/config:type = 'threadpool-flexible'";
+                       leaf max-thread-count {
+                               type uint16;
+                       }
+                       leaf minThreadCount {
+                               type uint16;
+                       }
+                       leaf keepAliveMillis {
+                               type uint32;
+                       }
+
+                       container threadFactory {
+                               uses config:service-ref {
+                                       refine type {
+                                          // mandatory true;
+                                               config:required-identity th:threadfactory;
+                                       }
+                               }
+                       }
+        }
+       }
+
+    identity threadpool-scheduled {
+               base config:module-type;
+               config:provided-service th:scheduled-threadpool;
+               config:java-name-prefix ScheduledThreadPool;
+       }
+
+       augment "/config:modules/config:module/config:configuration" {
+               case threadpool-scheduled {
+                       when "/config:modules/config:module/config:type = 'threadpool-scheduled'";
+                       leaf max-thread-count {
+                               type uint16;
+                       }
+
+                       container threadFactory {
+                               uses config:service-ref {
+                                       refine type {
+                                        //   mandatory true;
+                                               config:required-identity th:threadfactory;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
index 4482df07805cd852b73f1a9130f30e1a9cde9c9b..9b07f75c6dc315ce97cfec342599f4136b126e9d 100644 (file)
@@ -81,7 +81,7 @@
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal-compability</artifactId>
+          <artifactId>sal-compatibility</artifactId>
           <version>${mdsal.version}</version>
         </dependency>
         <dependency>
similarity index 94%
rename from opendaylight/md-sal/flow-management-compatibility/pom.xml
rename to opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml
index 5c24baa65038e14b9e25869c902d2b49703a8ad5..3c8bf979614082dcc257e0e0ff82e8c44190c9ec 100644 (file)
@@ -2,8 +2,8 @@
   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>
+     <groupId>org.opendaylight.controller</groupId>
+    <artifactId>compatibility-parent</artifactId>
     <version>1.0-SNAPSHOT</version>
   </parent>
   <artifactId>flow-management-compatibility</artifactId>
@@ -81,7 +81,7 @@
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-compability</artifactId>
+      <artifactId>sal-compatibility</artifactId>
       <version>1.0-SNAPSHOT</version>
     </dependency>
 
@@ -15,7 +15,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows
 import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager
 import static com.google.common.base.Preconditions.*;
 import static extension org.opendaylight.controller.md.frm.compatibility.FlowConfigMapping.*;
-import static extension org.opendaylight.controller.sal.compability.NodeMapping.*;
+import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*;
 import org.opendaylight.controller.sal.common.util.Arguments
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
 import org.opendaylight.yangtools.yang.common.RpcResult
@@ -3,9 +3,9 @@ package org.opendaylight.controller.md.frm.compatibility
 import org.opendaylight.controller.forwardingrulesmanager.FlowConfig
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder
 
-import static extension org.opendaylight.controller.sal.compability.NodeMapping.*
-import static org.opendaylight.controller.sal.compability.MDFlowMapping.*
-import static org.opendaylight.controller.sal.compability.ToSalConversionsUtils.*
+import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
+import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.*
+import static org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.*
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow
diff --git a/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java b/opendaylight/md-sal/compatibility/flow-management-compatibility/src/main/java/org/opendaylight/controller/md/frm/compatibility/SampleConsumer.java
new file mode 100644 (file)
index 0000000..a82eedc
--- /dev/null
@@ -0,0 +1,38 @@
+package org.opendaylight.controller.md.frm.compatibility;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SampleConsumer {
+
+    ConsumerContext context;
+
+    void addFlowExample() {
+
+        DataBrokerService dataService = context.getSALService(DataBrokerService.class);
+
+        DataModificationTransaction transaction = dataService.beginTransaction();
+        Flow flow = createSampleFlow("foo", null);
+        InstanceIdentifier<Flow> path = InstanceIdentifier.builder().node(Flows.class).node(Flow.class, flow.getKey())
+                .toInstance();
+        transaction.putConfigurationData(path, flow);
+
+        transaction.commit();
+
+        dataService.readConfigurationData(path);
+    }
+
+    Flow createSampleFlow(String name, NodeRef node) {
+        FlowBuilder ret = new FlowBuilder();
+        FlowKey key = new FlowKey(name, node);
+        ret.setKey(key);
+        return ret.build();
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml
new file mode 100644 (file)
index 0000000..d9fb18f
--- /dev/null
@@ -0,0 +1,109 @@
+<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>compatibility-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>inventory-topology-compatibility</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>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>Forwarding Rules Manager Adapter
+                            for MD-SAL</Bundle-Name>
+                    </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>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </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>switchmanager</artifactId>
+            <version>0.6.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>topologymanager</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </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>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </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-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-topology</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>forwardingrulesmanager</artifactId>
+            <version>0.4.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-compatibility</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/inventory/InventoryReader.xtend
new file mode 100644 (file)
index 0000000..262e848
--- /dev/null
@@ -0,0 +1,83 @@
+package org.opendaylight.controller.md.compatibility.inventory
+
+import org.opendaylight.controller.switchmanager.ISwitchManager
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
+import java.util.ArrayList
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector
+import static extension org.opendaylight.controller.sal.compatibility.InventoryMapping.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder
+
+class InventoryReader implements RuntimeDataProvider {
+
+    @Property
+    var ISwitchManager switchManager;
+
+    override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+
+        // Topology and Inventory are operational only
+        return null;
+    }
+
+    override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+        val type = path.targetType;
+        var DataObject data = null;
+        switch (type) {
+            case Nodes:
+                data = readNodes(path as InstanceIdentifier<Nodes>)
+            case Node:
+                data = readNode(path as InstanceIdentifier<Node>)
+            case NodeConnector:
+                data = readNodeConnector(path as InstanceIdentifier<NodeConnector>)
+        }
+        return data;
+    }
+
+    def DataObject readNodeConnector(InstanceIdentifier<NodeConnector> identifier) {
+        val nodeConnector = identifier.toAdNodeConnector();
+        return constructNodeConnector(nodeConnector)
+    }
+
+    def DataObject readNode(InstanceIdentifier<Node> identifier) {
+        val node = identifier.toAdNode();
+        return constructNode(node);
+    }
+
+
+    def Node constructNode(org.opendaylight.controller.sal.core.Node node) {
+        val connectors = switchManager.getNodeConnectors(node)
+
+        val tpList = new ArrayList<NodeConnector>(connectors.size)
+        for (connector : connectors) {
+            tpList.add(constructNodeConnector(connector));
+        }
+
+        val it = new NodeBuilder()
+        key = node.toNodeKey();
+        nodeConnector = tpList
+        return build();
+    }
+
+    def NodeConnector constructNodeConnector(org.opendaylight.controller.sal.core.NodeConnector connector) {
+        val it = new NodeConnectorBuilder()
+        key = connector.toNodeConnectorKey()
+        return build();
+    }
+
+    def readNodes(InstanceIdentifier<Nodes> identifier) {
+        val nodes = switchManager.nodes
+        val nodeList = new ArrayList<Node>(nodes.size)
+        for (node : nodes) {
+            nodeList.add(constructNode(node))
+        }
+        val it = new NodesBuilder();
+        node = nodeList
+        return build()
+
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/CompatibleSwitchManager.xtend
new file mode 100644 (file)
index 0000000..430b595
--- /dev/null
@@ -0,0 +1,289 @@
+package org.opendaylight.controller.md.compatibility.switchmanager
+
+import org.opendaylight.controller.switchmanager.ISwitchManager
+import org.opendaylight.controller.sal.core.NodeConnector
+import org.opendaylight.controller.sal.core.Property
+import java.util.List
+import org.opendaylight.controller.sal.core.Node
+import java.net.InetAddress
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
+import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
+import org.opendaylight.controller.sal.core.Description
+import org.opendaylight.controller.sal.core.Tier
+import org.opendaylight.controller.sal.core.Bandwidth
+import org.opendaylight.controller.sal.core.ForwardingMode
+import org.opendaylight.controller.sal.core.MacAddress
+
+import org.slf4j.LoggerFactory
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import java.net.NetworkInterface
+import java.net.SocketException
+import java.util.Collections
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
+import java.util.ArrayList
+import org.opendaylight.controller.switchmanager.Switch
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
+import java.util.Map
+import java.util.HashSet
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortState
+
+class CompatibleSwitchManager extends ConfigurableSwitchManager implements ISwitchManager {
+
+    private static val log = LoggerFactory.getLogger(CompatibleSwitchManager)
+
+    @org.eclipse.xtend.lib.Property
+    var DataBrokerService dataService;
+
+    override addNodeConnectorProp(NodeConnector nodeConnector, Property prop) {
+        val it = dataService.beginTransaction
+        val path = nodeConnector.toNodeConnectorRef
+
+        // TODO: Update FlowCapableNode
+        return null;
+    }
+
+    override createProperty(String propName, String propValue) {
+        try {
+            if (propName.equalsIgnoreCase(Description.propertyName)) {
+                return new Description(propValue);
+            } else if (propName.equalsIgnoreCase(Tier.TierPropName)) {
+                val tier = Integer.parseInt(propValue);
+                return new Tier(tier);
+            } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) {
+                val bw = Long.parseLong(propValue);
+                return new Bandwidth(bw);
+            } else if (propName.equalsIgnoreCase(ForwardingMode.name)) {
+                val mode = Integer.parseInt(propValue);
+                return new ForwardingMode(mode);
+            } else if (propName.equalsIgnoreCase(MacAddress.name)) {
+                return new MacAddress(propValue);
+            } else {
+                log.debug("Not able to create {} property", propName);
+            }
+        } catch (Exception e) {
+            log.debug("createProperty caught exception {}", e.getMessage());
+        }
+        return null;
+    }
+
+    override doesNodeConnectorExist(NodeConnector nc) {
+        val ref = nc.toNodeConnectorRef
+        return dataService.readOperationalData(ref.value as InstanceIdentifier<? extends DataObject>) !== null
+    }
+
+    override getControllerMAC() {
+        var byte[] macAddress = null;
+
+        try {
+            val nis = NetworkInterface.getNetworkInterfaces();
+            while (nis.hasMoreElements()) {
+                val ni = nis.nextElement();
+                try {
+                    macAddress = ni.getHardwareAddress();
+                    return macAddress;
+                } catch (SocketException e) {
+                    log.error("Failed to acquire controller MAC: ", e);
+                }
+            }
+        } catch (SocketException e) {
+            log.error("Failed to acquire controller MAC: ", e);
+            return macAddress;
+        }
+
+        if (macAddress == null) {
+            log.warn("Failed to acquire controller MAC: No physical interface found");
+
+            // This happens when running controller on windows VM, for example
+            // Try parsing the OS command output
+            }
+            return macAddress;
+        }
+
+    override getControllerProperties() {
+        return Collections.emptyMap()
+    }
+
+    override getControllerProperty(String propertyName) {
+        return null;
+    }
+
+    override getNetworkDevices() {
+        val path = InstanceIdentifier.builder().node(Nodes).toInstance;
+        val data = dataService.readOperationalData(path) as Nodes;
+        val ret = new ArrayList<Switch>();
+        for (node : data.node) {
+            ret.add(node.toSwitch());
+        }
+        return ret;
+    }
+
+    override getNodeConnector(Node node, String nodeConnectorName) {
+        val key = new NodeConnectorKey(new NodeConnectorId(nodeConnectorName));
+        return new NodeConnector(MD_SAL_TYPE, key, node);
+    }
+
+    override getNodeConnectorProp(NodeConnector nodeConnector, String propName) {
+        getNodeConnectorProps(nodeConnector).get(propName);
+    }
+
+    override getNodeConnectorProps(NodeConnector nodeConnector) {
+        val ref = nodeConnector.toNodeConnectorRef
+        val data = readNodeConnector(ref.value);
+        return data.toAdProperties();
+    }
+
+    override getNodeConnectors(Node node) {
+        val ref = node.toNodeRef;
+        val data = readNode(ref.value);
+        val ret = new HashSet();
+        for (nc : data.nodeConnector) {
+
+            val adConnector = new NodeConnector(MD_SAL_TYPE, nc.key, node);
+            ret.add(adConnector);
+        }
+        return ret;
+    }
+
+    override getNodeDescription(Node node) {
+        (getNodeProps(node).get(Description.propertyName) as Description).value;
+    }
+
+    override getNodeMAC(Node node) {
+        (getNodeProps(node).get(MacAddress.name) as MacAddress).macAddress;
+    }
+
+    override getNodeProp(Node node, String propName) {
+        getNodeProps(node).get(propName)
+    }
+
+    override getNodeProps(Node node) {
+        val ref = node.toNodeRef;
+        val data = dataService.readOperationalData(ref.value as InstanceIdentifier<? extends DataObject>) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+        return data.toAdProperties();
+    }
+
+    override getNodes() {
+        val path = InstanceIdentifier.builder().node(Nodes).toInstance;
+        val data = dataService.readOperationalData(path) as Nodes;
+        val ret = new HashSet<Node>();
+        for (node : data.node) {
+            ret.add(new Node(MD_SAL_TYPE, node.key));
+        }
+        return ret;
+    }
+
+    def Switch toSwitch(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node node) {
+        val adNode = new Node(MD_SAL_TYPE, node.key);
+        val sw = new Switch(adNode)
+        return sw;
+    }
+
+    override getPhysicalNodeConnectors(Node node) {
+        val ref = node.toNodeRef;
+        val data = readNode(ref.value);
+        val ret = new HashSet();
+        for (nc : data.nodeConnector) {
+            val flowConnector = nc.getAugmentation(FlowCapableNodeConnector)
+            val adConnector = new NodeConnector(MD_SAL_TYPE, nc.key, node);
+            ret.add(adConnector);
+        }
+        return ret;
+    }
+
+    def Map<String, Property> toAdProperties(
+        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector connector) {
+        return Collections.emptyMap
+    }
+
+    def Map<String, Property> toAdProperties(
+        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node connector) {
+        return Collections.emptyMap
+    }
+
+    def readNode(InstanceIdentifier<?> ref) {
+        dataService.readOperationalData(ref as InstanceIdentifier<? extends DataObject>) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+    }
+
+    def readNodeConnector(InstanceIdentifier<?> ref) {
+        dataService.readOperationalData(ref as InstanceIdentifier<? extends DataObject>) as org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector
+    }
+
+    override getSpanPorts(Node node) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override getSubnetByNetworkAddress(InetAddress networkAddress) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override getUpNodeConnectors(Node node) {
+        val ref = node.toNodeRef
+        val data = readNode(ref.value);
+        val ret = new HashSet<NodeConnector>();
+        for (nc : data.nodeConnector) {
+            val flowConn = nc.getAugmentation(FlowCapableNodeConnector);
+            if (flowConn != null && flowConn.state == PortState.Live) {
+                ret.add(new NodeConnector(MD_SAL_TYPE, nc.key, node));
+            }
+        }
+        return ret;
+    }
+
+    override isNodeConnectorEnabled(NodeConnector nodeConnector) {
+        val ref = nodeConnector.toNodeConnectorRef
+        val data = readNodeConnector(ref.value);
+
+        return true;
+    }
+
+    override isSpecial(NodeConnector p) {
+        val ref = p.toNodeConnectorRef
+        val data = readNodeConnector(ref.value);
+
+        return true;
+    }
+
+    override removeControllerProperty(String propertyName) {
+        // NOOP
+    }
+
+    override removeNodeAllProps(Node node) {
+        // NOOP: not supported node has more properties than AD-SAL is capable to see
+    }
+
+    override removeNodeConnectorAllProps(NodeConnector nodeConnector) {
+        // NOOP: not supported node has more properties than AD-SAL is capable to see
+    }
+
+    override removeNodeConnectorProp(NodeConnector nc, String propName) {
+        // NOOP: not supported node has more properties than AD-SAL is capable to see
+    }
+
+    override removeNodeProp(Node node, String propName) {
+        // NOOP: not supported node has more properties than AD-SAL is capable to see
+    }
+
+    override removePortsFromSubnet(String name, List<String> nodeConnectors) {
+        // NOOP
+    }
+
+    override removeSubnet(String name) {
+        // NOOP
+    }
+
+    override setControllerProperty(Property property) {
+        // NOOP
+    }
+
+    override setNodeProp(Node node, Property prop) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override addPortsToSubnet(String name, List<String> nodeConnectors) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    }
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/switchmanager/ConfigurableSwitchManager.xtend
new file mode 100644 (file)
index 0000000..122aa32
--- /dev/null
@@ -0,0 +1,71 @@
+package org.opendaylight.controller.md.compatibility.switchmanager
+
+import org.opendaylight.controller.switchmanager.ISwitchManager
+import org.opendaylight.controller.switchmanager.SpanConfig
+import org.opendaylight.controller.switchmanager.SwitchConfig
+import org.opendaylight.controller.switchmanager.SubnetConfig
+
+/**
+ * 
+ * THis methods should be backed by config subsystem.
+ * 
+ */
+abstract class ConfigurableSwitchManager implements ISwitchManager {
+
+    override saveSwitchConfig() {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override removeSpanConfig(SpanConfig cfgObject) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override addSubnet(SubnetConfig configObject) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+
+    }
+
+    final override addSpanConfig(SpanConfig configObject) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+
+    }
+
+    final override getSpanConfigList() {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+
+    }
+
+    final override updateSwitchConfig(SwitchConfig cfgObject) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+
+    }
+
+    final override updateNodeConfig(SwitchConfig switchConfig) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+
+    }
+
+    final override getSubnetConfig(String subnet) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    final override removeNodeConfig(String nodeId) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    final override removeSubnet(SubnetConfig configObject) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    final override getSubnetsConfigList() {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    final override getSwitchConfig(String nodeId) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override modifySubnet(SubnetConfig configObject) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyMapping.xtend
new file mode 100644 (file)
index 0000000..5a4aae3
--- /dev/null
@@ -0,0 +1,67 @@
+package org.opendaylight.controller.md.compatibility.topology
+
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.Topology
+import org.opendaylight.controller.sal.core.Edge
+import java.util.Set
+import org.opendaylight.controller.sal.core.Property
+import org.opendaylight.controller.sal.core.NodeConnector
+
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.LinkKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.LinkId
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Node
+import org.opendaylight.controller.sal.compatibility.InventoryMapping
+class TopologyMapping {
+
+    new(TopologyKey path, InstanceIdentifier<Topology> key) {
+        // NOOP
+    }
+
+    def Edge toAdTopologyEdge(InstanceIdentifier<Link> identifier) {
+        val linkKey = (identifier.path.last as IdentifiableItem<Link,LinkKey>).key;
+        val components = linkKey.linkId.value.split("::::");
+        val tail = InventoryMapping.nodeConnectorFromId(components.get(0));
+        val head = InventoryMapping.nodeConnectorFromId(components.get(1));
+        return new Edge(tail, head);
+    }
+
+    def NodeConnector toAdTopologyNodeConnector(InstanceIdentifier<TerminationPoint> identifier) {
+        val tpKey = (identifier.path.last as IdentifiableItem<TerminationPoint,TerminationPointKey>).key;
+        return InventoryMapping.nodeConnectorFromId(tpKey.tpId.value);
+    }
+
+    def org.opendaylight.controller.sal.core.Node toAdTopologyNode(
+        InstanceIdentifier<Node> identifier) {
+        val tpKey = (identifier.path.last as IdentifiableItem<Node,NodeKey>).key;
+        return InventoryMapping.nodeFromNodeId(tpKey.nodeId.value);
+    }
+    
+
+
+    def NodeKey toTopologyNodeKey(org.opendaylight.controller.sal.core.Node node) {
+        val nodeId = new NodeId(InventoryMapping.toNodeId(node));
+        return new NodeKey(nodeId);
+    }
+
+    def TerminationPointKey toTopologyTerminationPointKey(NodeConnector nc) {
+        val node = nc.node;
+        val nodeId = new TpId(InventoryMapping.toNodeConnectorId(nc))
+        return new TerminationPointKey(nodeId);
+    }
+
+    def LinkKey toTopologyLinkKey(Edge edge) {
+        val sourceTp = edge.tailNodeConnector.toTopologyTerminationPointKey;
+        val destTp = edge.headNodeConnector.toTopologyTerminationPointKey;
+        val linkId = new LinkId('''«sourceTp.tpId»::::«destTp.tpId»''')
+        return new LinkKey(linkId);
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topology/TopologyReader.xtend
new file mode 100644 (file)
index 0000000..fb9d2b8
--- /dev/null
@@ -0,0 +1,151 @@
+package org.opendaylight.controller.md.compatibility.topology
+
+import org.opendaylight.controller.switchmanager.ISwitchManager
+import org.opendaylight.controller.topologymanager.ITopologyManager
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.Topology
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Node
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NetworkTopology
+import org.opendaylight.controller.md.compatibility.topology.TopologyMapping
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.LinkBuilder
+
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyBuilder
+import java.util.ArrayList
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeBuilder
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeKey
+import org.opendaylight.controller.sal.core.NodeConnector
+import org.opendaylight.controller.sal.topology.TopoEdgeUpdate
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TopologyId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointBuilder
+import org.opendaylight.controller.sal.core.Edge
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.SourceBuilder
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.DestinationBuilder
+
+class TopologyReader implements RuntimeDataProvider {
+
+    @Property
+    var ISwitchManager switchManager;
+
+    @Property
+    var ITopologyManager topologyManager;
+
+    @Property
+    val TopologyKey topologyKey;
+
+    @Property
+    val InstanceIdentifier<Topology> topologyPath;
+
+    @Property
+    val extension TopologyMapping mapping;
+
+    new() {
+        _topologyKey = new TopologyKey(new TopologyId("compatibility:ad-sal"));
+        _topologyPath = InstanceIdentifier.builder().node(NetworkTopology).child(Topology, topologyKey).toInstance;
+        _mapping = new TopologyMapping(topologyKey, topologyPath);
+    }
+
+    override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+
+        // Topology and Inventory are operational only
+        return null;
+    }
+
+    override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+        val type = path.targetType;
+        var DataObject data = null;
+        if (false == topologyPath.contains(path)) {
+            return null;
+        }
+        switch (type) {
+            case Topology:
+                data = readTopology(path as InstanceIdentifier<Topology>)
+            case Node:
+                data = readNode(path as InstanceIdentifier<Node>)
+            case TerminationPoint:
+                data = readTerminationPoint(path as InstanceIdentifier<TerminationPoint>)
+            case Link:
+                data = readLink(path as InstanceIdentifier<Link>)
+        }
+        return data;
+    }
+
+    def DataObject readLink(InstanceIdentifier<Link> identifier) {
+        val edge = identifier.toAdTopologyEdge();
+        val properties = topologyManager?.edges?.get(edge);
+
+        return constructLink(edge);
+    }
+
+    def DataObject readTerminationPoint(InstanceIdentifier<TerminationPoint> identifier) {
+        val nodeConnector = identifier.toAdTopologyNodeConnector();
+        return constructTerminationPoint(nodeConnector)
+    }
+
+    def DataObject readNode(InstanceIdentifier<Node> identifier) {
+        val node = identifier.toAdTopologyNode();
+        return constructNode(node);
+    }
+
+    def DataObject readTopology(InstanceIdentifier<Topology> identifier) {
+
+        //val nodeConnectors = switchManager.
+        val nodes = switchManager.nodes
+        val edges = topologyManager.edges
+
+        val nodeList = new ArrayList<Node>(nodes.size)
+        for (node : nodes) {
+            nodeList.add(constructNode(node))
+        }
+
+        val linkList = new ArrayList<Link>(edges.size)
+        for (edge : edges.keySet) {
+            linkList.add(constructLink(edge))
+        }
+
+        val it = new TopologyBuilder();
+        key = topologyKey
+        node = nodeList
+        link = linkList
+        return build()
+    }
+
+    def constructLink(Edge edge) {
+        val sourceNc = edge.tailNodeConnector
+        val destNc = edge.headNodeConnector
+
+        val it = new LinkBuilder()
+        key = edge.toTopologyLinkKey();
+        source = new SourceBuilder().setSourceNode(sourceNc.node.toTopologyNodeKey.nodeId).setSourceTp(
+            sourceNc.toTopologyTerminationPointKey.tpId).build()
+        destination = new DestinationBuilder().setDestNode(destNc.node.toTopologyNodeKey.nodeId).setDestTp(
+            destNc.toTopologyTerminationPointKey.tpId).build
+        return build()
+    }
+
+    def Node constructNode(org.opendaylight.controller.sal.core.Node node) {
+        val connectors = switchManager.getNodeConnectors(node)
+
+        val tpList = new ArrayList<TerminationPoint>(connectors.size)
+        for (connector : connectors) {
+            tpList.add(constructTerminationPoint(connector));
+        }
+
+        val it = new NodeBuilder()
+        key = node.toTopologyNodeKey();
+        terminationPoint = tpList
+        return build();
+    }
+
+    def TerminationPoint constructTerminationPoint(NodeConnector connector) {
+        val it = new TerminationPointBuilder()
+        key = connector.toTopologyTerminationPointKey
+        return build();
+    }
+
+}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/AdSalTopologyMapping.xtend
new file mode 100644 (file)
index 0000000..ad7537b
--- /dev/null
@@ -0,0 +1,94 @@
+package org.opendaylight.controller.md.compatibility.topologymanager
+
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyKey
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
+import org.opendaylight.controller.sal.core.NodeConnector
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.Topology
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NetworkTopology
+import java.util.Map
+import org.opendaylight.controller.sal.core.Edge
+import java.util.Set
+import java.util.List
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Node
+import java.util.Collections
+import com.google.common.collect.FluentIterable
+import java.util.HashSet
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
+import org.opendaylight.controller.sal.compatibility.NodeMapping
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.Source
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.link.attributes.Destination
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointKey
+import java.util.HashMap
+
+class AdSalTopologyMapping {
+
+    val TopologyKey topologyMapping;
+    @Property
+    val InstanceIdentifier<Topology> topologyPath;
+
+    new(TopologyKey topology) {
+        topologyMapping = topology;
+        _topologyPath = InstanceIdentifier.builder.node(NetworkTopology).child(Topology, topology).toInstance;
+    }
+
+    def InstanceIdentifier<TerminationPoint> toTerminationPoint(NodeConnector connector) {
+        InstanceIdentifier.builder(topologyPath).node(Node).child(TerminationPoint, connector.toTerminationPointKey()).toInstance;
+    }
+
+    def Map<Edge, Set<org.opendaylight.controller.sal.core.Property>> toEdgePropertiesMap(Iterable<Link> links) {
+        val ret = new HashMap<Edge, Set<org.opendaylight.controller.sal.core.Property>>
+        for (link : links) {
+            ret.put(link.toEdge(), link.toProperties())
+        }
+        return ret;
+    }
+
+    def Set<Edge> toEdges(Iterable<Link> links) {
+        val ret = new HashSet<Edge>
+        for (link : links) {
+            ret.add(link.toEdge)
+        }
+        return ret;
+    }
+
+    def Edge toEdge(Link link) {
+        val tail = link.source.toNodeConnector();
+        val head = link.destination.toNodeConnector();
+        return new Edge(tail, head);
+    }
+
+    def org.opendaylight.controller.sal.core.Node toAdNode(Node node) {
+        return node.nodeId.toAdNode;
+    }
+
+    def org.opendaylight.controller.sal.core.Node toAdNode(
+        org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId node) {
+        val key = new NodeKey(new NodeId(node))
+        return new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, key);
+    }
+
+    def NodeConnector toNodeConnector(Source ref) {
+        val adNode = ref.sourceNode.toAdNode();
+        val key = new NodeConnectorKey(new NodeConnectorId(ref.sourceTp))
+        return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode);
+    }
+
+    def NodeConnector toNodeConnector(Destination ref) {
+        val adNode = ref.destNode.toAdNode();
+        val key = new NodeConnectorKey(new NodeConnectorId(ref.destTp))
+        return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode);
+    }
+
+    def TerminationPointKey toTerminationPointKey(NodeConnector connector) {
+    }
+
+    def Set<org.opendaylight.controller.sal.core.Property> toProperties(Link link) {
+    }
+}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/CompatibleTopologyManager.xtend
new file mode 100644 (file)
index 0000000..c6a4912
--- /dev/null
@@ -0,0 +1,85 @@
+package org.opendaylight.controller.md.compatibility.topologymanager
+
+import org.opendaylight.controller.topologymanager.ITopologyManager
+import org.opendaylight.controller.sal.core.NodeConnector
+import org.opendaylight.controller.sal.core.Host
+import org.opendaylight.controller.sal.core.UpdateType
+import java.util.Set
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
+import java.util.HashMap
+import org.opendaylight.controller.sal.core.Edge
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
+import com.google.common.collect.FluentIterable
+
+class CompatibleTopologyManager extends ConfigurableLinkManager implements ITopologyManager {
+
+    @Property
+    var TypeSafeDataReader dataReader;
+
+    @Property
+    var extension AdSalTopologyMapping topologyMapping;
+
+    override getEdges() {
+        val topology = dataReader.readOperationalData(topologyPath);
+        return topology.link.toEdgePropertiesMap();
+    }
+
+    override getNodeEdges() {
+        val topology = dataReader.readOperationalData(topologyPath);
+        val ret = new HashMap<org.opendaylight.controller.sal.core.Node, Set<Edge>>;
+        for (node : topology.node) {
+            val adNode = node.toAdNode();
+            val adEdges = FluentIterable.from(topology.link).filter[
+                source.sourceNode == node.nodeId || destination.destNode == node.nodeId].toEdges();
+            ret.put(adNode, adEdges)
+        }
+        return ret;
+    }
+
+    /**
+     *   Returns true if point is connected to link
+    */
+    def isInternal(TerminationPoint point) {
+        val topology = dataReader.readConfigurationData(topologyPath);
+        val tpId = point.key.tpId;
+        return FluentIterable.from(topology.link).anyMatch(
+            [
+                source.sourceTp == tpId || destination.destTp == tpId
+            ])
+    }
+
+    override getNodeConnectorWithHost() {
+    }
+
+    override getHostAttachedToNodeConnector(NodeConnector p) {
+        val tpPath = p.toTerminationPoint();
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    override getHostsAttachedToNodeConnector(NodeConnector p) {
+        val topology = dataReader.readOperationalData(topologyPath);
+
+        throw new UnsupportedOperationException("Hosts not mapped yet")
+    }
+
+    override getNodesWithNodeConnectorHost() {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+
+    }
+
+    override isInternal(NodeConnector p) {
+        val tpPath = p.toTerminationPoint();
+        val connector = dataReader.readConfigurationData(tpPath);
+        return connector.isInternal();
+    }
+
+    override updateHostLink(NodeConnector p, Host h, UpdateType t,
+        Set<org.opendaylight.controller.sal.core.Property> props) {
+        // Update app defined topology
+    }
+
+    override saveConfig() {
+        // FIXME: commit configuration
+    }
+
+}
diff --git a/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.xtend b/opendaylight/md-sal/compatibility/inventory-topology-compatibility/src/main/java/org/opendaylight/controller/md/compatibility/topologymanager/ConfigurableLinkManager.xtend
new file mode 100644 (file)
index 0000000..da3bf66
--- /dev/null
@@ -0,0 +1,24 @@
+package org.opendaylight.controller.md.compatibility.topologymanager
+
+import org.opendaylight.controller.topologymanager.ITopologyManager
+import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig
+
+abstract class ConfigurableLinkManager implements ITopologyManager {
+    
+    final override addUserLink(TopologyUserLinkConfig link) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        
+    }
+    
+    
+    final override deleteUserLink(String linkName) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        
+    }
+    
+    
+    final override getUserLinks() {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/compatibility/pom.xml b/opendaylight/md-sal/compatibility/pom.xml
new file mode 100644 (file)
index 0000000..a829380
--- /dev/null
@@ -0,0 +1,101 @@
+<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>
+    <artifactId>compatibility-parent</artifactId>
+    <packaging>pom</packaging>
+    <name>MD-SAL to AD-SAL Adaptation</name>
+    <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>
+
+    <modules>
+        <module>sal-compatibility</module>
+        <module>inventory-topology-compatibility</module>
+        <module>flow-management-compatibility</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal</artifactId>
+            <version>0.5.1-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</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.name}</Bundle-Name>
+                        <Bundle-Activator>org.opendaylight.controller.sal.compability.ComponentActivator</Bundle-Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <configuration>
+                    <includes>org.opendaylight.controller.*</includes>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>pre-test</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>post-test</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
similarity index 65%
rename from opendaylight/md-sal/sal-compability/pom.xml
rename to opendaylight/md-sal/compatibility/sal-compatibility/pom.xml
index 6d992de015d16ad239a9712d47a968df0883e57a..15a9a689b3da5975dc6a6a0f1597cb3990e6a1ea 100644 (file)
@@ -3,10 +3,10 @@
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.opendaylight.controller</groupId>
-    <artifactId>sal-parent</artifactId>
+    <artifactId>compatibility-parent</artifactId>
     <version>1.0-SNAPSHOT</version>
   </parent>
-  <artifactId>sal-compability</artifactId>
+  <artifactId>sal-compatibility</artifactId>
   <name>MD-SAL to AD-SAL Adaptation</name>
   <scm>
     <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
   </scm>
 
   <dependencies>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <version>0.5.1-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-statistics</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-api</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.eclipse.xtend</groupId>
-      <artifactId>org.eclipse.xtend.lib</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
   <packaging>bundle</packaging>
 
@@ -68,7 +35,7 @@
         <configuration>
           <instructions>
             <Bundle-Name>${project.name}</Bundle-Name>
-            <Bundle-Activator>org.opendaylight.controller.sal.compability.ComponentActivator</Bundle-Activator>
+            <Bundle-Activator>org.opendaylight.controller.sal.compatibility.ComponentActivator</Bundle-Activator>
           </instructions>
         </configuration>
       </plugin>
@@ -1,10 +1,10 @@
-package org.opendaylight.controller.sal.compability
+package org.opendaylight.controller.sal.compatibility
 
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
 import org.opendaylight.controller.sal.core.Node
 import org.opendaylight.controller.sal.core.NodeConnector
-import static org.opendaylight.controller.sal.compability.NodeMapping.*
+import static org.opendaylight.controller.sal.compatibility.NodeMapping.*
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
 import org.apache.felix.dm.Component
 import java.util.Arrays
@@ -1,4 +1,4 @@
-package org.opendaylight.controller.sal.compability
+package org.opendaylight.controller.sal.compatibility
 
 import java.util.concurrent.ExecutionException
 import org.opendaylight.controller.sal.core.Node
@@ -15,10 +15,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalF
 import org.opendaylight.yangtools.yang.common.RpcResult
 import org.slf4j.LoggerFactory
 
-import static org.opendaylight.controller.sal.compability.MDFlowMapping.*
+import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.*
 
-import static extension org.opendaylight.controller.sal.compability.NodeMapping.*
-import static extension org.opendaylight.controller.sal.compability.ToSalConversionsUtils.*
+import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
+import static extension org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.*
 
 class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener {
 
@@ -1,4 +1,4 @@
-package org.opendaylight.controller.sal.compability;
+package org.opendaylight.controller.sal.compatibility;
 
 import static org.opendaylight.controller.sal.match.MatchType.DL_DST;
 import static org.opendaylight.controller.sal.match.MatchType.DL_SRC;
@@ -12,6 +12,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
 import org.opendaylight.controller.sal.core.NodeConnector;
 
 
@@ -25,7 +26,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetNodeConnectorStatisticsInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetNodeConnectorStatisticsInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.Address;
@@ -57,18 +57,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
-
 import com.google.common.net.InetAddresses;
-
-
-
-
-
-
-
-
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.*;
-import static org.opendaylight.controller.sal.compability.NodeMapping.*;
+import static org.opendaylight.controller.sal.compatibility.NodeMapping.*;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.*;
 
 public class FromSalConversionsUtils {
 
@@ -1,4 +1,4 @@
-package org.opendaylight.controller.sal.compability
+package org.opendaylight.controller.sal.compatibility
 
 import org.opendaylight.controller.sal.reader.IPluginInReadService
 import org.opendaylight.controller.sal.core.NodeConnector
@@ -8,8 +8,8 @@ import org.opendaylight.controller.sal.core.NodeTable
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
 
 import static extension org.opendaylight.controller.sal.common.util.Arguments.*
-import static extension org.opendaylight.controller.sal.compability.NodeMapping.*
-import static org.opendaylight.controller.sal.compability.MDFlowMapping.*
+import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
+import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.*
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend
new file mode 100644 (file)
index 0000000..0ea9918
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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.compatibility
+
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
+
+class InventoryMapping {
+
+    static def org.opendaylight.controller.sal.core.NodeConnector toAdNodeConnector(
+        InstanceIdentifier<NodeConnector> identifier) {
+        val tpKey = (identifier.path.last as IdentifiableItem<NodeConnector,NodeConnectorKey>).key;
+        return nodeConnectorFromId(tpKey.id.value);
+    }
+
+    static def org.opendaylight.controller.sal.core.Node toAdNode(InstanceIdentifier<Node> identifier) {
+        val tpKey = (identifier.path.last as IdentifiableItem<Node,NodeKey>).key;
+        return nodeFromNodeId(tpKey.id.value);
+    }
+    
+    
+     static def NodeRef toNodeRef(org.opendaylight.controller.sal.core.Node node) {
+        val nodeId = new NodeKey(new NodeId(node.toNodeId))
+        val path = InstanceIdentifier.builder().node(Nodes).child(Node,nodeId).toInstance;
+        return new NodeRef(path);
+    }
+
+    static def NodeKey toNodeKey(org.opendaylight.controller.sal.core.Node node) {
+        val nodeId = new NodeId(node.toNodeId)
+        return new NodeKey(nodeId);
+    }
+
+    static def NodeConnectorKey toNodeConnectorKey(org.opendaylight.controller.sal.core.NodeConnector nc) {
+        val nodeId = new NodeConnectorId(nc.toNodeConnectorId)
+        return new NodeConnectorKey(nodeId);
+    }
+
+    static def String toNodeId(org.opendaylight.controller.sal.core.Node node) {
+        '''ad-sal:«node.type»::«node.nodeIDString»'''
+    }
+
+    static def String toNodeConnectorId(org.opendaylight.controller.sal.core.NodeConnector nc) {
+        '''«nc.node.toNodeId»::«nc.nodeConnectorIDString»'''
+    }
+
+    static def org.opendaylight.controller.sal.core.Node nodeFromNodeId(String nodeId) {
+        return nodeFromString(nodeId.split("::"))
+    }
+
+    static def nodeConnectorFromId(String invId) {
+        return nodeConnectorFromString(invId.split("::"));
+    }
+
+    private static def org.opendaylight.controller.sal.core.NodeConnector nodeConnectorFromString(String[] string) {
+        val node = nodeFromString(string.subList(0, 1));
+        return org.opendaylight.controller.sal.core.NodeConnector.fromStringNoNode(string.get(2), node);
+    }
+
+    private static def org.opendaylight.controller.sal.core.Node nodeFromString(String[] strings) {
+        val type = strings.get(0).substring(6);
+        org.opendaylight.controller.sal.core.Node.fromString(type, strings.get(1))
+    }
+
+}
@@ -1,4 +1,4 @@
-package org.opendaylight.controller.sal.compability;
+package org.opendaylight.controller.sal.compatibility;
 
 import com.google.common.net.InetAddresses
 import java.math.BigInteger
@@ -73,8 +73,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherTyp
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp
 
-import static extension org.opendaylight.controller.sal.compability.FromSalConversionsUtils.*
-import static extension org.opendaylight.controller.sal.compability.NodeMapping.*
+import static extension org.opendaylight.controller.sal.compatibility.FromSalConversionsUtils.*
+import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions
@@ -1,6 +1,7 @@
-package org.opendaylight.controller.sal.compability;
+package org.opendaylight.controller.sal.compatibility;
 
 import com.google.common.net.InetAddresses;
+
 import org.opendaylight.controller.sal.action.Controller;
 import org.opendaylight.controller.sal.action.Drop;
 import org.opendaylight.controller.sal.action.Flood;
@@ -91,10 +92,10 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.ETHERNET_ARP;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.SCTP;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.TCP;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.UDP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.SCTP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
 import static org.opendaylight.controller.sal.match.MatchType.DL_DST;
 import static org.opendaylight.controller.sal.match.MatchType.DL_SRC;
 import static org.opendaylight.controller.sal.match.MatchType.DL_TYPE;
@@ -1,6 +1,6 @@
-package org.opendaylight.controller.sal.compability.adsal;
+package org.opendaylight.controller.sal.compatibility.adsal;
 
-import org.opendaylight.controller.sal.compability.NodeMapping;
+import org.opendaylight.controller.sal.compatibility.NodeMapping;
 import org.opendaylight.controller.sal.packet.IPluginInDataPacketService;
 import org.opendaylight.controller.sal.packet.RawPacket;
 import org.opendaylight.controller.sal.packet.RawPacket;
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/adsal/FlowServiceAdapter.java
new file mode 100644 (file)
index 0000000..ae42745
--- /dev/null
@@ -0,0 +1,84 @@
+package org.opendaylight.controller.sal.compatibility.adsal;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.common.util.Futures;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.compatibility.InventoryMapping;
+import org.opendaylight.controller.sal.compatibility.NodeMapping;
+import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(FlowServiceAdapter.class);
+
+    private IFlowProgrammerService delegate;
+
+    private NotificationProviderService publish;
+
+    @Override
+    public void flowRemoved(org.opendaylight.controller.sal.core.Node node, Flow flow) {
+        FlowRemovedBuilder flowRemovedBuilder = new FlowRemovedBuilder();
+        flowRemovedBuilder.setNode(InventoryMapping.toNodeRef(node));
+        publish.publish(flowRemovedBuilder.build());
+    }
+
+    @Override
+    public void flowErrorReported(org.opendaylight.controller.sal.core.Node node, long rid, Object err) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public Future<RpcResult<Void>> addFlow(AddFlowInput input) {
+
+        Flow flow = ToSalConversionsUtils.toFlow(input);
+        @SuppressWarnings("unchecked")
+        org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier<Node>) input
+                .getNode().getValue());
+        Status status = delegate.addFlowAsync(node, flow);
+        Void rpcResultType = null;
+        return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
+    }
+
+    @Override
+    public Future<RpcResult<Void>> removeFlow(RemoveFlowInput input) {
+
+        Flow flow = ToSalConversionsUtils.toFlow(input);
+        @SuppressWarnings("unchecked")
+        org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier<Node>) input
+                .getNode().getValue());
+        Status status = delegate.removeFlowAsync(node, flow);
+        Void rpcResultType = null;
+        return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
+
+    }
+
+    @Override
+    public Future<RpcResult<Void>> updateFlow(UpdateFlowInput input) {
+        @SuppressWarnings("unchecked")
+        org.opendaylight.controller.sal.core.Node node = InventoryMapping.toAdNode((InstanceIdentifier<Node>) input
+                .getNode().getValue());
+        Flow originalFlow = ToSalConversionsUtils.toFlow(input.getOriginalFlow());
+        Flow updatedFlow = ToSalConversionsUtils.toFlow(input.getUpdatedFlow());
+        Status status = delegate.modifyFlowAsync(node, originalFlow, updatedFlow);
+        Void rpcResultType = null;
+        return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
+    }
+}
@@ -1,4 +1,4 @@
-package org.opendaylight.controller.sal.compability.adsal;
+package org.opendaylight.controller.sal.compatibility.adsal;
 
 import java.math.BigInteger;
 import java.util.ArrayList;
@@ -8,8 +8,8 @@ import java.util.concurrent.Future;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.controller.sal.common.util.Futures;
 import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.controller.sal.compability.NodeMapping;
-import org.opendaylight.controller.sal.compability.ToSalConversionsUtils;
+import org.opendaylight.controller.sal.compatibility.NodeMapping;
+import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
 import org.opendaylight.controller.sal.core.ConstructionException;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
@@ -1,60 +1,32 @@
-package org.opendaylight.controller.sal.compability;
+/*
+ * 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.compatibility.test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.ETHERNET_ARP;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.SCTP;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.TCP;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.UDP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.SCTP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
 
 import java.util.ArrayList;
 import java.util.List;
 
 import org.junit.Test;
-import org.opendaylight.controller.sal.action.Action;
-import org.opendaylight.controller.sal.action.Flood;
-import org.opendaylight.controller.sal.action.FloodAll;
-import org.opendaylight.controller.sal.action.HwPath;
-import org.opendaylight.controller.sal.action.Loopback;
-import org.opendaylight.controller.sal.action.PopVlan;
-import org.opendaylight.controller.sal.action.PushVlan;
-import org.opendaylight.controller.sal.action.SetDlDst;
-import org.opendaylight.controller.sal.action.SetDlSrc;
-import org.opendaylight.controller.sal.action.SetDlType;
-import org.opendaylight.controller.sal.action.SetNextHop;
-import org.opendaylight.controller.sal.action.SetNwDst;
-import org.opendaylight.controller.sal.action.SetNwSrc;
-import org.opendaylight.controller.sal.action.SetNwTos;
-import org.opendaylight.controller.sal.action.SetTpDst;
-import org.opendaylight.controller.sal.action.SetTpSrc;
-import org.opendaylight.controller.sal.action.SetVlanCfi;
-import org.opendaylight.controller.sal.action.SetVlanId;
-import org.opendaylight.controller.sal.action.SetVlanPcp;
-import org.opendaylight.controller.sal.action.SwPath;
+import org.opendaylight.controller.sal.action.*;
+import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
+import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
 import org.opendaylight.controller.sal.match.Match;
 import org.opendaylight.controller.sal.match.MatchType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.FloodAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.FloodAllAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.HwPathAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.LoopbackAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PopVlanAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PushVlanAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlTypeAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNextHopAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwTosAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetTpDstAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetTpSrcAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanCfiAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanIdAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanPcpAction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SwPathAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.address.Ipv4;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
@@ -1,77 +1,43 @@
-package org.opendaylight.controller.sal.compability;
+/*
+ * 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.compatibility.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
-import com.google.common.net.InetAddresses;
 import org.junit.Test;
-import org.opendaylight.controller.sal.action.Flood;
-import org.opendaylight.controller.sal.action.FloodAll;
-import org.opendaylight.controller.sal.action.HwPath;
-import org.opendaylight.controller.sal.action.Loopback;
-import org.opendaylight.controller.sal.action.Output;
-import org.opendaylight.controller.sal.action.PopVlan;
-import org.opendaylight.controller.sal.action.PushVlan;
-import org.opendaylight.controller.sal.action.SetDlDst;
-import org.opendaylight.controller.sal.action.SetDlSrc;
-import org.opendaylight.controller.sal.action.SetDlType;
-import org.opendaylight.controller.sal.action.SetNextHop;
-import org.opendaylight.controller.sal.action.SetNwDst;
-import org.opendaylight.controller.sal.action.SetNwSrc;
-import org.opendaylight.controller.sal.action.SetNwTos;
-import org.opendaylight.controller.sal.action.SetTpDst;
-import org.opendaylight.controller.sal.action.SetTpSrc;
-import org.opendaylight.controller.sal.action.SetVlanCfi;
-import org.opendaylight.controller.sal.action.SetVlanId;
-import org.opendaylight.controller.sal.action.SetVlanPcp;
-import org.opendaylight.controller.sal.action.SwPath;
+import org.opendaylight.controller.sal.action.*;
+import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
 import org.opendaylight.controller.sal.flowprogrammer.Flow;
 import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.VlanCfi;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.ControllerActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.DropActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.FloodActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.FloodAllActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.HwPathActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.LoopbackActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.OutputActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PopMplsActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PopVlanActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PushMplsActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PushPbbActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.PushVlanActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlDstActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlSrcActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetDlTypeActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetMplsTtlActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNextHopActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwDstActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwSrcActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwTosActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetNwTtlActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetQueueActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetTpDstActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetTpSrcActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanCfiActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanIdActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SetVlanPcpActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.SwPathActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.action.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.address.Ipv4Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.address.address.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
@@ -79,20 +45,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestination;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSource;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
@@ -100,21 +54,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsBuilder;
 
-import java.math.BigInteger;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import com.google.common.net.InetAddresses;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.ETHERNET_ARP;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.SCTP;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.TCP;
-import static org.opendaylight.controller.sal.compability.ProtocolConstants.UDP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.SCTP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
 
 public class TestToSalConversionsUtils {
     // prefix:
diff --git a/opendaylight/md-sal/model/model-topology/pom.xml b/opendaylight/md-sal/model/model-topology/pom.xml
new file mode 100644 (file)
index 0000000..c91b9dd
--- /dev/null
@@ -0,0 +1,31 @@
+<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">
+
+    <parent>
+        <artifactId>model-parent</artifactId>
+        <groupId>org.opendaylight.controller.model</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </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:MD-SAL</url>
+    </scm>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>model-topology</artifactId>
+    <packaging>bundle</packaging>
+    
+    <dependencies>
+    <dependency>
+        <groupId>org.opendaylight.controller.model</groupId>
+        <artifactId>model-inventory</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <artifactId>ietf-topology</artifactId>
+        <version>2013.07.12.2-SNAPSHOT</version>
+    </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology-inventory.yang
new file mode 100644 (file)
index 0000000..33c03ba
--- /dev/null
@@ -0,0 +1,34 @@
+module opendaylight-topology-inventory {
+    yang-version 1;
+    namespace "urn:opendaylight:model:topology:inventory";
+    // replace with IANA namespace when assigned
+    prefix "nt";
+
+    import yang-ext { prefix "ext"; }
+    import ietf-inet-types { prefix "inet"; }
+    import opendaylight-inventory {prefix "inv";}
+    import opendaylight-topology {prefix "odt";}
+    import network-topology {prefix "topo";}
+
+    organization "TBD";
+
+    contact "WILL-BE-DEFINED-LATER";
+
+    revision 2013-10-30 {
+        description
+            "Initial revision.";
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:node" {
+        ext:augment-identifier "inventory-node";
+        uses inv:node-context-ref;
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:node/topo:termination-point" {
+        ext:augment-identifier "inventory-node-connector";
+        leaf node-connector {
+            ext:context-reference "inv:node-connector-context";
+            type inv:node-connector-ref;
+        }
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang b/opendaylight/md-sal/model/model-topology/src/main/yang/opendaylight-topology.yang
new file mode 100644 (file)
index 0000000..038a1b7
--- /dev/null
@@ -0,0 +1,64 @@
+module opendaylight-topology {
+    yang-version 1;
+    namespace "urn:opendaylight:model:topology:general";
+    // replace with IANA namespace when assigned
+    prefix "nt";
+
+    import yang-ext { prefix "ext"; }
+    import ietf-inet-types { prefix "inet"; }
+    import opendaylight-inventory {prefix "inv";}
+    import network-topology {prefix "topo";}
+
+    organization "TBD";
+
+    contact "WILL-BE-DEFINED-LATER";
+
+    revision 2013-10-30 {
+        description
+            "Initial revision.";
+    }
+
+    identity node-type {
+    
+    }
+    
+    typedef node-type-ref {
+        type identityref {
+            base node-type;
+       }
+    }
+    
+    identity topology-context {
+    
+    }
+    
+    identity topology-node-context {
+        
+    }
+
+    grouping node-identifiers {
+        list node-identifier {
+            key "type identifier";
+            leaf type {
+                type node-type-ref;
+            }
+            leaf identifier {
+                type inet:uri;
+            }
+        }
+    }
+
+    augment "/topo:network-topology/topo:topology" {
+        ext:context-instance "topology-context";
+    }
+
+    /* Inventory Augmentations */
+    augment "/topo:network-topology/topo:topology/topo:node" {
+        ext:context-instance "topology-node-context";
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:node" {
+        ext:augment-identifier "identifiable-node";
+        uses node-identifiers;
+    }
+}
diff --git a/opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang b/opendaylight/md-sal/model/model-topology/src/main/yang/topology-view.yang
new file mode 100644 (file)
index 0000000..2fecb32
--- /dev/null
@@ -0,0 +1,48 @@
+module opendaylight-topology-view  {
+    yang-version 1;
+    namespace "urn:opendaylight:model:topology:view";
+    // replace with IANA namespace when assigned
+    prefix "nt";
+
+    import yang-ext { prefix "ext"; }
+    import ietf-inet-types { prefix "inet"; }
+    import network-topology {prefix "topo";}
+    import opendaylight-topology {prefix "odl";}
+
+    organization "TBD";
+
+    contact "WILL-BE-DEFINED-LATER";
+
+    revision 2013-10-30 {
+        description
+            "Initial revision.";
+    }
+    
+
+    grouping aggregate-topology {
+        leaf-list original-topology {
+            type topo:topology-ref;    
+        }
+    }
+
+    grouping aggregate-node {
+        list original-node {
+            leaf topology {
+                type topo:topology-ref;
+            }
+            leaf node {
+                type topo:node-ref;
+            }
+        }
+    }
+
+    augment "/topo:network-topology/topo:topology" {
+        ext:augment-identifier "aggregated-topology";
+        uses aggregate-topology;
+    }
+
+    augment "/topo:network-topology/topo:topology/topo:node" {
+        ext:augment-identifier "aggregated-node";
+        uses aggregate-node;
+    }
+}
\ No newline at end of file
index ca97232cfb66393d579a0ac83514037aae42e339..eccb691fa72b3b3f1390d71a97b757b78cfc0fd6 100644 (file)
@@ -28,6 +28,7 @@
         <module>model-flow-service</module>
         <module>model-flow-statistics</module>
         <module>model-flow-management</module>
+        <module>model-topology</module>
     </modules>
 
     <build>
index a6740fabac158248dbd86892613a5942812d1f7a..fd89da4dd0c0e2b7876e8e0adcf6f90d87fc6cff 100644 (file)
@@ -27,7 +27,8 @@
         <module>sal-binding-api</module>
         <module>sal-binding-config</module>
         <module>sal-binding-broker</module>
-        <module>sal-binding-it</module>
+
+        <module>sal-binding-util</module>
 
         <!-- Samples -->
         <module>samples</module>
         <!-- Base Models -->
         <module>model</module>
 
-        <!-- Compability Packages -->
-        <module>sal-compability</module>
 
         <!-- Connectors -->
         <module>sal-connector-api</module>
         <module>sal-rest-connector</module>
-        <module>flow-management-compatibility</module>
 
         <!-- Clustered Data Store -->
         <module>clustered-data-store/implementation</module>
-        <module>clustered-data-store/integrationtest</module>
 
+        <module>inventory-manager</module>
+        <!-- Compability Packages -->
+        <module>compatibility</module>
+
+        <module>sal-zeromq-connector</module>
+        <module>test</module>
     </modules>
 
+
+    <profiles>
+        <profile>
+           <id>integrationtests</id>
+           <activation>
+               <activeByDefault>false</activeByDefault>
+           </activation>
+            <modules>
+                <module>sal-binding-it</module>
+                <module>clustered-data-store/integrationtest</module>
+            </modules>
+        </profile>
+    </profiles>
+
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
                     <artifactId>jacoco-maven-plugin</artifactId>
                     <version>${jacoco.version}</version>
                 </plugin>
-                <!--This plugin's configuration is used to store Eclipse
-                    m2e settings only. It has no influence on the Maven build itself. -->
+                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
                 <plugin>
                     <groupId>org.eclipse.m2e</groupId>
                     <artifactId>lifecycle-mapping</artifactId>
                                         <ignore></ignore>
                                     </action>
                                 </pluginExecution>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>org.jacoco</groupId>
+                                        <artifactId>
+                                            jacoco-maven-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [0.5.3.201107060350,)
+                                        </versionRange>
+                                        <goals>
+                                            <goal>prepare-agent</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
                             </pluginExecutions>
                         </lifecycleMappingMetadata>
                     </configuration>
index c1dccdf5320a488a6b4c38a7464eb10e4d53af24..cfbd4f7b719e0f5217fbee4dba444b38ca0e9c7a 100644 (file)
@@ -38,6 +38,7 @@
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
             <version>${osgi.core.version}</version>
+            <scope>provided</scope>
         </dependency>
     </dependencies>
 </project>
index b8b37af58ee42eec8f1ca2b50763013f20c935f8..9ca025b393911d11ede993899a32e2488939c8a2 100644 (file)
                 <configuration>
                     <instructions>
                         <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Export-package>
+                            org.opendaylight.controller.sal.binding.spi.*,
+                        </Export-package>
                         <Private-Package>
                             org.opendaylight.controller.config.yang.md.sal.binding.impl,
-                            org.opendaylight.controller.sal.binding.spi,
-                            org.opendaylight.controller.sal.binding.spi.*,
                             org.opendaylight.controller.sal.binding.impl,
                             org.opendaylight.controller.sal.binding.impl.*,
+                            org.opendaylight.controller.sal.binding.codegen,
                             org.opendaylight.controller.sal.binding.codegen.*,
                         </Private-Package>
                     </instructions>
index 75655419b057028510282bb170235e3c55021a2e..d9a3dd547f67a1cc448272f7d0a67c2284fb9ddb 100644 (file)
@@ -186,7 +186,7 @@ class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable {
     def <T extends RpcService> registerRpcImplementation(Class<T> type, T service, OsgiProviderContext context,
         Hashtable<String, String> properties) {
         val proxy = getManagedDirectProxy(type)
-        checkState(proxy.delegate === null, "The Service for type {} is already registered", type)
+        checkState(proxy.delegate === null, "The Service for type %s is already registered", type)
 
         val osgiReg = context.bundleContext.registerService(type, service, properties);
         proxy.delegate = service;
index 9356ecda88315a0d055d2279070e407321422f38..6ed63b21ddb4a67d3485c008c4417d19131367c9 100644 (file)
@@ -5,23 +5,13 @@ import org.opendaylight.controller.sal.binding.api.data.DataChangeListener
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService
 import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus
-import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification
 import org.opendaylight.controller.md.sal.common.api.data.DataReader
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
 import org.opendaylight.yangtools.concepts.ListenerRegistration
-import static extension org.opendaylight.controller.sal.binding.impl.util.MapUtils.*;
-import java.util.Collection
-import java.util.Map.Entry
-import java.util.HashSet
-import java.util.Set
 import com.google.common.collect.Multimap
 import static com.google.common.base.Preconditions.*;
 import java.util.List
-import java.util.LinkedList
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
 import com.google.common.collect.HashMultimap
 import java.util.concurrent.ExecutorService
 import java.util.concurrent.Callable
@@ -30,15 +20,17 @@ import org.opendaylight.controller.sal.common.util.Rpcs
 import java.util.Collections
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
 import java.util.ArrayList
-import org.opendaylight.controller.sal.common.util.RpcErrors
+import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter
+import org.opendaylight.yangtools.concepts.CompositeObjectRegistration
+import java.util.Arrays
 
 class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderService {
 
     @Property
     var ExecutorService executor;
 
-    Multimap<InstanceIdentifier, DataReaderRegistration> configReaders = HashMultimap.create();
-    Multimap<InstanceIdentifier, DataReaderRegistration> operationalReaders = HashMultimap.create();
+    val dataReadRouter = new BindingAwareDataReaderRouter;
+
     Multimap<InstanceIdentifier, DataChangeListenerRegistration> listeners = HashMultimap.create();
     Multimap<InstanceIdentifier, DataCommitHandlerRegistration> commitHandlers = HashMultimap.create();
 
@@ -47,13 +39,11 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer
     }
 
     override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
-        val readers = configReaders.getAllChildren(path);
-        return readers.readConfiguration(path);
+        return dataReadRouter.readConfigurationData(path);
     }
 
     override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
-        val readers = operationalReaders.getAllChildren(path);
-        return readers.readOperational(path);
+        return dataReadRouter.readOperationalData(path);
     }
 
     override registerCommitHandler(InstanceIdentifier<? extends DataObject> path,
@@ -69,20 +59,12 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer
         return reg;
     }
 
-    override registerDataReader(InstanceIdentifier<? extends DataObject> path,
-        DataReader<InstanceIdentifier<? extends DataObject>, DataObject> provider) {
-        val ret = new DataReaderRegistration(provider, this);
-        ret.paths.add(path);
-        configReaders.put(path, ret);
-        operationalReaders.put(path, ret);
-        return ret;
-    }
-
-    protected def removeReader(DataReaderRegistration reader) {
-        for (path : reader.paths) {
-            operationalReaders.remove(path, reader);
-            configReaders.remove(path, reader);
-        }
+    override registerDataReader(InstanceIdentifier<? extends DataObject> path,DataReader<InstanceIdentifier<? extends DataObject>,DataObject> reader) {
+        
+        val confReg = dataReadRouter.registerConfigurationReader(path,reader);
+        val dataReg = dataReadRouter.registerOperationalReader(path,reader);
+        
+        return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg));
     }
 
     protected def removeListener(DataChangeListenerRegistration registration) {
@@ -92,39 +74,8 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer
     protected def removeCommitHandler(DataCommitHandlerRegistration registration) {
         commitHandlers.remove(registration.path, registration);
     }
-
-    protected def DataObject readConfiguration(
-        Collection<Entry<? extends InstanceIdentifier, ? extends DataReaderRegistration>> entries,
-        InstanceIdentifier<? extends DataObject> path) {
-
-        val List<DataObject> partialResults = new LinkedList();
-        for (entry : entries) {
-            partialResults.add(entry.value.instance.readConfigurationData(path))
-        }
-        return merge(path, partialResults);
-    }
-
-    protected def DataObject readOperational(
-        Collection<Entry<? extends InstanceIdentifier, ? extends DataReaderRegistration>> entries,
-        InstanceIdentifier<? extends DataObject> path) {
-
-        val List<DataObject> partialResults = new LinkedList();
-        for (entry : entries) {
-            partialResults.add(entry.value.instance.readOperationalData(path))
-        }
-        return merge(path, partialResults);
-    }
-
-    protected def DataObject merge(InstanceIdentifier<? extends DataObject> identifier, List<DataObject> objects) {
-
-        // FIXME: implement real merge
-        if (objects.size > 0) {
-            return objects.get(0);
-        }
-    }
     
     protected def getActiveCommitHandlers() {
-        
         return commitHandlers.entries.map[ value.instance].toSet
     }
 
@@ -137,26 +88,6 @@ class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderSer
 
 }
 
-package class DataReaderRegistration extends //
-AbstractObjectRegistration<DataReader<InstanceIdentifier<? extends DataObject>, DataObject>> {
-
-    DataBrokerImpl dataBroker;
-
-    @Property
-    val Set<InstanceIdentifier<? extends DataObject>> paths;
-
-    new(DataReader<InstanceIdentifier<? extends DataObject>, DataObject> instance, DataBrokerImpl broker) {
-        super(instance)
-        dataBroker = broker;
-        _paths = new HashSet();
-    }
-
-    override protected removeRegistration() {
-        dataBroker.removeReader(this);
-    }
-
-}
-
 package class DataChangeListenerRegistration extends AbstractObjectRegistration<DataChangeListener> implements ListenerRegistration<DataChangeListener> {
 
     DataBrokerImpl dataBroker;
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend
deleted file mode 100644 (file)
index 398a219..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.impl
-
-import org.opendaylight.controller.sal.common.DataStoreIdentifier
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
-
-class DataProviderContext {
-
-    @Property
-    var DataStoreIdentifier identifier;
-    @Property
-    var RuntimeDataProvider provider;
-}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend
new file mode 100644 (file)
index 0000000..f586a8b
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opendaylight.controller.sal.binding.impl.util
+
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+
+class BindingAwareDataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier<? extends DataObject>, DataObject> {
+    
+    override protected merge(InstanceIdentifier<? extends DataObject> path, Iterable<DataObject> data) {
+        return data.iterator.next;
+    }
+    
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-util/pom.xml b/opendaylight/md-sal/sal-binding-util/pom.xml
new file mode 100644 (file)
index 0000000..26041ea
--- /dev/null
@@ -0,0 +1,33 @@
+<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>
+    <artifactId>sal-binding-util</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>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.dependencymanager</artifactId>
+            <version>3.1.0</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/sal-binding-util/src/main/java/org/opendaylight/controller/md/sal/binding/util/TypeSafeDataReader.java b/opendaylight/md-sal/sal-binding-util/src/main/java/org/opendaylight/controller/md/sal/binding/util/TypeSafeDataReader.java
new file mode 100644 (file)
index 0000000..738a14a
--- /dev/null
@@ -0,0 +1,38 @@
+package org.opendaylight.controller.md.sal.binding.util;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class TypeSafeDataReader {
+
+    
+    private final DataReader<InstanceIdentifier<?>,DataObject> delegate;
+    
+    
+    
+    public DataReader<InstanceIdentifier<?>, DataObject> getDelegate() {
+        return delegate;
+    }
+
+
+    public TypeSafeDataReader(DataReader<InstanceIdentifier<?>, DataObject> delegate) {
+        this.delegate = delegate;
+    }
+
+
+    @SuppressWarnings("unchecked")
+    public <D extends DataObject> D readConfigurationData(InstanceIdentifier<D> path) {
+        return (D) delegate.readConfigurationData(path);
+    }
+    
+    
+    @SuppressWarnings("unchecked")
+    public <D extends DataObject> D  readOperationalData(InstanceIdentifier<D> path) {
+        return (D) delegate.readOperationalData(path);
+    }
+    
+    public static TypeSafeDataReader forReader(DataReader<InstanceIdentifier<?>, DataObject> delegate) {
+        return new TypeSafeDataReader(delegate);
+    }
+}
index 0fea50b777f14dc31275f9b75c7d1bf4622f6ece..55565252a2b7a408579f46e05b9794cbe707d81a 100644 (file)
@@ -13,19 +13,102 @@ import java.util.Set;
 // FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
 // import org.opendaylight.yangtools.concepts.Path;
 
+public interface DataChange<P/* extends Path<P> */, D> {
 
-public interface DataChange<P/* extends Path<P> */,D> {
+    /**
+     * Returns a map of paths and newly created objects
+     * 
+     * @return map of paths and newly created objects
+     */
+    Map<P, D> getCreatedOperationalData();
 
-    Map<P,D> getCreatedOperationalData();
+    /**
+     * Returns a map of paths and newly created objects
+     * 
+     * @return map of paths and newly created objects
+     */
+    Map<P, D> getCreatedConfigurationData();
 
-    Map<P,D> getUpdatedOperationalData();
+    /**
+     * Returns a map of paths and respective updated objects after update.
+     * 
+     * Original state of the object is in
+     * {@link #getOriginalOperationalData()}
+     * 
+     * @return map of paths and newly created objects
+     */
+    Map<P, D> getUpdatedOperationalData();
 
+    /**
+     * Returns a map of paths and respective updated objects after update.
+     * 
+     * Original state of the object is in
+     * {@link #getOriginalConfigurationData()}
+     * 
+     * @return map of paths and newly created objects
+     */
+    Map<P, D> getUpdatedConfigurationData();
+
+    /**
+     * Returns a set of paths of removed objects.
+     * 
+     * Original state of the object is in
+     * {@link #getOriginalConfigurationData()}
+     * 
+     * @return map of paths and newly created objects
+     */
+    Set<P> getRemovedConfigurationData();
+
+    /**
+     * Returns a set of paths of removed objects.
+     * 
+     * Original state of the object is in
+     * {@link #getOriginalOperationalData()}
+     * 
+     * @return map of paths and newly created objects
+     */
     Set<P> getRemovedOperationalData();
 
-    Map<P,D> getCreatedConfigurationData();
+    /**
+     * Return a map of paths and original state of updated and removed objectd.
+     * 
+     * @return map of paths and original state of updated and removed objectd.
+     */
+    Map<P, D> getOriginalConfigurationData();
 
-    Map<P,D> getUpdatedConfigurationData();
+    /**
+     * Return a map of paths and original state of updated and removed objectd.
+     * 
+     * @return map of paths and original state of updated and removed objectd.
+     */
+    Map<P, D> getOriginalOperationalData();
 
-    Set<P> getRemovedConfigurationData();
+    /**
+     * Returns a original subtree of data, which starts at the path
+     * where listener was registered.
+     * 
+     */
+    D getOriginalConfigurationSubtree();
+
+    /**
+     * Returns a original subtree of data, which starts at the path
+     * where listener was registered.
+     * 
+     */
+    D getOriginalOperationalSubtree();
+
+    /**
+     * Returns a new subtree of data, which starts at the path
+     * where listener was registered.
+     * 
+     */
+    D getUpdatedConfigurationSubtree();
+
+    /**
+     * Returns a new subtree of data, which starts at the path
+     * where listener was registered.
+     * 
+     */
+    D getUpdatedOperationalSubtree();
 
 }
index 85e3d8f57ca4a6a2de3913b4363ba5e1fb0af651..90de13d15e8229238f36c5ec59b1180babcff1ae 100644 (file)
@@ -84,7 +84,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
  */
 public interface DataCommitHandler<P/* extends Path<P> */,D> {
 
-
+    
     DataCommitTransaction<P, D> requestCommit(DataModification<P,D> modification);
 
     public interface DataCommitTransaction<P/* extends Path<P> */,D> {
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java
new file mode 100644 (file)
index 0000000..f448d4e
--- /dev/null
@@ -0,0 +1,16 @@
+package org.opendaylight.controller.md.sal.common.api.data;
+
+public interface DataStore<P, D> extends //
+        DataReader<P, D>, //
+        DataModificationTransactionFactory<P, D> {
+
+    @Override
+    public DataModification<P, D> beginTransaction();
+
+    @Override
+    public D readConfigurationData(P path);
+
+    @Override
+    public D readOperationalData(P path);
+
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Route.java
new file mode 100644 (file)
index 0000000..afe9e99
--- /dev/null
@@ -0,0 +1,10 @@
+package org.opendaylight.controller.md.sal.common.api.routing;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+
+public interface Route<C,P> extends Immutable {
+
+    C getType();
+    
+    P getPath();
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangeListener.java
new file mode 100644 (file)
index 0000000..994f65b
--- /dev/null
@@ -0,0 +1,8 @@
+package org.opendaylight.controller.md.sal.common.api.routing;
+
+import java.util.EventListener;
+
+public interface RouteChangeListener<C,P> extends EventListener {
+
+    void onRouteChange(RouteChange<C, P> change);
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RouteChangePublisher.java
new file mode 100644 (file)
index 0000000..89851c9
--- /dev/null
@@ -0,0 +1,8 @@
+package org.opendaylight.controller.md.sal.common.api.routing;
+
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+public interface RouteChangePublisher<C,P> {
+
+    ListenerRegistration<RouteChangeListener<C,P>> registerRouteChangeListener(RouteChangeListener<C,P> listener);
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/Router.java
new file mode 100644 (file)
index 0000000..8d0a90c
--- /dev/null
@@ -0,0 +1,10 @@
+package org.opendaylight.controller.md.sal.common.api.routing;
+
+import java.util.Map;
+import java.util.Set;
+
+public interface Router<C,P,D> extends //
+        RouteChangePublisher<C, P> {
+
+    Map<C, Set<P>> getAnnouncedPaths();
+}
index 0c2344a23e916e45ab43ace0a9e0cd3866cb266a..3bd51ec7d8b68dabe567857101a098cf2d2f4928 100644 (file)
         <artifactId>maven-bundle-plugin</artifactId>
         <configuration>
           <instructions>
-            <Export-Package>org.opendaylight.controller.md.sal.common.impl</Export-Package>
+            <Export-Package>
+                org.opendaylight.controller.md.sal.common.impl,
+                org.opendaylight.controller.md.sal.common.impl.*
+            </Export-Package>
           </instructions>
         </configuration>
       </plugin>
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java
new file mode 100644 (file)
index 0000000..f83c61f
--- /dev/null
@@ -0,0 +1,187 @@
+package org.opendaylight.controller.md.sal.common.impl.routing;
+
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Registration;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+
+/**
+ * Base abstract implementation of DataReadRouter, which performs
+ * a read operation on multiple data readers and then merges result.
+ * 
+ * @param <P>
+ * @param <D>
+ */
+public abstract class AbstractDataReadRouter<P extends Path<?>, D> implements DataReader<P, D> {
+
+    Multimap<P, DataReaderRegistration<P, D>> configReaders = HashMultimap.create();
+    Multimap<P, DataReaderRegistration<P, D>> operationalReaders = HashMultimap.create();
+
+    @Override
+    public D readConfigurationData(P path) {
+        FluentIterable<D> dataBits = FluentIterable //
+                .from(getReaders(configReaders, path)).transform(configurationRead(path));
+        return merge(path,dataBits);
+    }
+
+    @Override
+    public D readOperationalData(P path) {
+        FluentIterable<D> dataBits = FluentIterable //
+                .from(getReaders(configReaders, path)).transform(operationalRead(path));
+        return merge(path,dataBits);
+
+    }
+
+    /**
+     * Merges data readed by reader instances from specified path
+     * 
+     * @param path Path on which read was performed
+     * @param data Data which was returned by read operation.
+     * @return Merged result.
+     */
+    protected abstract D merge(P path,Iterable<D> data);
+
+    /**
+     * Returns a function which performs configuration read for supplied path
+     * 
+     * @param path
+     * @return function which performs configuration read for supplied path
+     */
+    
+    private Function<DataReader<P, D>, D> configurationRead(final P path) {
+        return new Function<DataReader<P, D>, D>() {
+            @Override
+            public D apply(DataReader<P, D> input) {
+                return input.readConfigurationData(path);
+            }
+        };
+    }
+
+    /**
+     * Returns a function which performs operational read for supplied path
+     * 
+     * @param path
+     * @return function which performs operational read for supplied path
+     */
+    private Function<DataReader<P, D>, D> operationalRead(final P path) {
+        return new Function<DataReader<P, D>, D>() {
+            @Override
+            public D apply(DataReader<P, D> input) {
+                return input.readConfigurationData(path);
+            }
+        };
+    }
+
+    // Registrations
+
+    /**
+     * Register's a reader for operational data.
+     * 
+     * @param path Path which is served by this reader
+     * @param reader Reader instance which is responsible for reading particular subpath.
+     * @return 
+     */
+    public Registration<DataReader<P, D>> registerOperationalReader(P path, DataReader<P, D> reader) {
+        OperationalDataReaderRegistration<P, D> ret = new OperationalDataReaderRegistration<>(path, reader);
+        operationalReaders.put(path, ret);
+        return ret;
+    }
+
+    public Registration<DataReader<P, D>> registerConfigurationReader(P path, DataReader<P, D> reader) {
+        ConfigurationDataReaderRegistration<P, D> ret = new ConfigurationDataReaderRegistration<>(path, reader);
+        configReaders.put(path, ret);
+        return ret;
+    }
+
+    Iterable<DataReader<P, D>> getOperationalReaders(P path) {
+        return getReaders(operationalReaders, path);
+    }
+
+    Iterable<DataReader<P, D>> getConfigurationReaders(P path) {
+        return getReaders(configReaders, path);
+    }
+
+    private Iterable<DataReader<P, D>> getReaders(Multimap<P, DataReaderRegistration<P, D>> readerMap, P path) {
+        return FluentIterable
+            .from(readerMap.entries()) //
+            .filter(affects(path)) //
+            .transform(retrieveInstance());
+    }
+
+    private void removeRegistration(OperationalDataReaderRegistration<?, ?> registration) {
+        operationalReaders.remove(registration.getKey(), registration);
+    }
+
+    private void removeRegistration(ConfigurationDataReaderRegistration<?, ?> registration) {
+        configReaders.remove(registration.getKey(), registration);
+    }
+
+    private Function<? super Entry<P, DataReaderRegistration<P, D>>, DataReader<P, D>> retrieveInstance() {
+        return new Function<Entry<P, DataReaderRegistration<P, D>>, DataReader<P,D>>() {
+            @Override
+            public DataReader<P, D> apply(Entry<P, DataReaderRegistration<P, D>> input) {
+                return input.getValue().getInstance();
+            }
+        };
+    }
+
+    private Predicate<? super Entry<P, DataReaderRegistration<P, D>>> affects(final P path) {
+        
+        return new Predicate<Entry<P, DataReaderRegistration<P, D>>>() {
+            
+            @Override
+            public boolean apply(Entry<P, DataReaderRegistration<P, D>> input) {
+                final Path key = input.getKey();
+                return key.contains(path) || ((Path) path).contains(key);
+            }
+            
+        };
+    }
+
+    private class ConfigurationDataReaderRegistration<P extends Path<?>, D> extends DataReaderRegistration<P, D> {
+
+        public ConfigurationDataReaderRegistration(P key, DataReader<P, D> instance) {
+            super(key, instance);
+        }
+
+        @Override
+        protected void removeRegistration() {
+            AbstractDataReadRouter.this.removeRegistration(this);
+        }
+    }
+
+    private class OperationalDataReaderRegistration<P extends Path<?>, D> extends DataReaderRegistration<P, D> {
+
+        public OperationalDataReaderRegistration(P key, DataReader<P, D> instance) {
+            super(key, instance);
+        }
+
+        @Override
+        protected void removeRegistration() {
+            AbstractDataReadRouter.this.removeRegistration(this);
+        }
+    }
+
+    private abstract static class DataReaderRegistration<P extends Path<?>, D> extends
+            AbstractObjectRegistration<DataReader<P, D>> {
+
+        private final P key;
+
+        public P getKey() {
+            return this.key;
+        }
+
+        public DataReaderRegistration(P key, DataReader<P, D> instance) {
+            super(instance);
+            this.key = key;
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalPropertyClassUtils.java b/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/ToSalPropertyClassUtils.java
new file mode 100644 (file)
index 0000000..08df0a4
--- /dev/null
@@ -0,0 +1,70 @@
+package org.opendaylight.controller.sal.compability;
+
+import org.opendaylight.controller.sal.core.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+
+public class ToSalPropertyClassUtils {
+    public static Bandwidth salAdvertisedBandwidthFrom(NodeConnector nodeConnector) {
+        FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class);        
+        PortFeatures portFeatures = flowCapNodeConn.getAdvertisedFeatures();
+        return new AdvertisedBandwidth(resolveBandwidth(portFeatures));
+    }
+
+    public static Bandwidth salPeerBandwidthFrom(NodeConnector nodeConnector) {
+        FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class);        
+        PortFeatures portFeatures = flowCapNodeConn.getPeerFeatures();
+        return new PeerBandwidth(resolveBandwidth(portFeatures));
+    }
+
+    public static Bandwidth salSupportedBandwidthFrom(NodeConnector nodeConnector) {
+        FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class);        
+        PortFeatures portFeatures = flowCapNodeConn.getSupported();
+        return new SupportedBandwidth(resolveBandwidth(portFeatures));
+    }
+
+    public static MacAddress salMacAddressFrom(NodeConnector nodeConnector) {
+        FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class);        
+        String hwAddress = flowCapNodeConn.getHardwareAddress().getValue();
+        return new MacAddress(bytesFrom(hwAddress));        
+    }
+    
+    
+    public static Name salNameFrom(NodeConnector nodeConnector) {
+        FlowCapableNodeConnector flowCapNodeConn = nodeConnector.getAugmentation(FlowCapableNodeConnector.class);        
+        return new Name(flowCapNodeConn.getName());
+    }
+    
+    
+
+    private static byte[] bytesFrom(String hwAddress) {
+        String[] mac = hwAddress.split(":");
+        byte[] macAddress = new byte[6]; // mac.length == 6 bytes
+        for (int i = 0; i < mac.length; i++) {
+            macAddress[i] = Integer.decode("0x" + mac[i]).byteValue();
+        }
+        return macAddress;
+    }
+
+    private static long resolveBandwidth(PortFeatures portFeatures) {
+        if (portFeatures.is_1tbFd()) {
+            return Bandwidth.BW1Tbps;
+        } else if (portFeatures.is_100gbFd()) {
+            return Bandwidth.BW100Gbps;
+        } else if (portFeatures.is_40gbFd()) {
+            return Bandwidth.BW40Gbps;
+        } else if (portFeatures.is_10gbFd()) {
+            return Bandwidth.BW10Gbps;
+        } else if (portFeatures.is_1gbHd() || portFeatures.is_1gbFd()) {
+            return Bandwidth.BW1Gbps;
+        } else if (portFeatures.is_100mbHd() || portFeatures.is_100mbFd()) {
+            return Bandwidth.BW100Mbps;
+        } else if (portFeatures.is_10mbHd() || portFeatures.is_10mbFd()) {
+            return Bandwidth.BW10Mbps;
+        } else {
+            return Bandwidth.BWUNK;
+        }
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowServiceAdapter.java b/opendaylight/md-sal/sal-compability/src/main/java/org/opendaylight/controller/sal/compability/adsal/FlowServiceAdapter.java
deleted file mode 100644 (file)
index 809ad76..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.opendaylight.controller.sal.compability.adsal;
-
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.Futures;
-import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.controller.sal.compability.NodeMapping;
-import org.opendaylight.controller.sal.compability.ToSalConversionsUtils;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Node;
-import org.opendaylight.controller.sal.flowprogrammer.Flow;
-import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener;
-import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FlowServiceAdapter implements SalFlowService, IFlowProgrammerListener {
-
-    private static final Logger LOG = LoggerFactory.getLogger(FlowServiceAdapter.class);
-
-    private IFlowProgrammerService delegate;
-
-    private NotificationProviderService publish;
-
-    @Override
-    public void flowRemoved(Node node, Flow flow) {
-        FlowRemovedBuilder flowRemovedBuilder = new FlowRemovedBuilder();
-        flowRemovedBuilder.setNode(NodeMapping.toNodeRef(node));
-        publish.publish(flowRemovedBuilder.build());
-    }
-
-    @Override
-    public void flowErrorReported(Node node, long rid, Object err) {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public Future<RpcResult<Void>> addFlow(AddFlowInput input) {
-        try {
-            Flow flow = ToSalConversionsUtils.toFlow(input);
-            Node node = NodeMapping.toADNode(input.getNode());
-            Status status = delegate.addFlowAsync(node, flow);
-            Void rpcResultType = null;
-            return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
-        } catch (ConstructionException e) {
-            LOG.error(e.getMessage());
-        }
-        return null;
-    }
-
-    @Override
-    public Future<RpcResult<Void>> removeFlow(RemoveFlowInput input) {
-        try {
-            Flow flow = ToSalConversionsUtils.toFlow(input);
-            Node node = NodeMapping.toADNode(input.getNode());
-            Status status = delegate.removeFlowAsync(node, flow);
-            Void rpcResultType = null;
-            return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
-        } catch (ConstructionException e) {
-            LOG.error(e.getMessage());
-        }
-        return null;
-    }
-
-    @Override
-    public Future<RpcResult<Void>> updateFlow(UpdateFlowInput input) {
-        try {
-            Node node = NodeMapping.toADNode(input.getNode());
-            Flow originalFlow = ToSalConversionsUtils.toFlow(input.getOriginalFlow());
-            Flow updatedFlow = ToSalConversionsUtils.toFlow(input.getUpdatedFlow());
-            Status status = delegate.modifyFlowAsync(node, originalFlow, updatedFlow);
-            Void rpcResultType = null;
-            return Futures.immediateFuture(Rpcs.getRpcResult(status.isSuccess(), rpcResultType, null));
-        } catch (ConstructionException e) {
-            LOG.error(e.getMessage());
-        }
-        return null;
-    }
-}
index 4807c4e2007279f73bc4f21d89975d0d3d283c52..08fce5783ef691009b336dfc18fd7c6eb8402374 100644 (file)
@@ -11,11 +11,11 @@ import java.util.concurrent.Future;
  * @param <T> Rpc Type
  * @param <D> Data Type
  */
-public interface RpcRouter<C,R,T,D> {
+public interface RpcRouter<C,T,R,D> {
 
     
     
-    Future<RpcReply<D>> sendRpc(RpcRequest<C, R, T, D> input);
+    Future<RpcReply<D>> sendRpc(RpcRequest<C, T, R, D> input);
     
     
     /**
@@ -27,17 +27,17 @@ public interface RpcRouter<C,R,T,D> {
         * @param <T> Rpc Type
         * @param <D> Data Type
      */
-    public interface RpcRequest<C,R,T,D> {
+    public interface RpcRequest<C,T,R,D> {
 
-        RouteIdentifier<C,R,T> getRoutingInformation();
+        RouteIdentifier<C,T,R> getRoutingInformation();
         D getPayload();
     }
     
-    public interface RouteIdentifier<C,R,T> {
+    public interface RouteIdentifier<C,T,R> {
         
         C getContext(); // defines a routing table (e.g. NodeContext)
-        R getRoute(); // e.g. (node identity)
         T getType(); // rpc type
+        R getRoute(); // e.g. (node identity)
     }
     
     public interface RpcReply<D> {
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java
new file mode 100644 (file)
index 0000000..c19ee1a
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.controller.sal.core.api;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface RpcConsumptionRegistry {
+    /**
+     * Sends an RPC to other components registered to the broker.
+     * 
+     * @see RpcImplementation
+     * @param rpc
+     *            Name of RPC
+     * @param input
+     *            Input data to the RPC
+     * @return Result of the RPC call
+     */
+    Future<RpcResult<CompositeNode>> rpc(QName rpc, CompositeNode input);
+
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java
new file mode 100644 (file)
index 0000000..c326bab
--- /dev/null
@@ -0,0 +1,33 @@
+package org.opendaylight.controller.sal.core.api;
+
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public interface RpcProvisionRegistry {
+
+    /**
+     * Registers an implementation of the rpc.
+     * 
+     * <p>
+     * The registered rpc functionality will be available to all other
+     * consumers and providers registered to the broker, which are aware of
+     * the {@link QName} assigned to the rpc.
+     * 
+     * <p>
+     * There is no assumption that rpc type is in the set returned by
+     * invoking {@link RpcImplementation#getSupportedRpcs()}. This allows
+     * for dynamic rpc implementations.
+     * 
+     * @param rpcType
+     *            Name of Rpc
+     * @param implementation
+     *            Provider's Implementation of the RPC functionality
+     * @throws IllegalArgumentException
+     *             If the name of RPC is invalid
+     */
+    RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation)
+            throws IllegalArgumentException;
+
+    RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation);
+}
index 3024c89d615b4723041fe0707f5459a08f698b1b..20fa29dceb7cd807ca78c2650d357f5a30bb0cb1 100644 (file)
@@ -10,8 +10,10 @@ package org.opendaylight.controller.sal.core.api.data;
 import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService;
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
 import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;;
 
 public interface DataProviderService extends 
     DataBrokerService, //
@@ -54,6 +56,11 @@ public interface DataProviderService extends
      */
     void removeRefresher(DataStoreIdentifier store, DataRefresher refresher);
 
+    
+    Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader);
+
+    Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader);
+    
     public interface DataRefresher extends Provider.ProviderFunctionality {
 
         /**
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionInstance.java
new file mode 100644 (file)
index 0000000..8f6a5d0
--- /dev/null
@@ -0,0 +1,8 @@
+package org.opendaylight.controller.sal.core.api.mount;
+
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+
+public interface MountProvisionInstance extends MountInstance, NotificationPublishService, RpcProvisionRegistry {
+
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/mount/MountProvisionService.java
new file mode 100644 (file)
index 0000000..fade7d3
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opendaylight.controller.sal.core.api.mount;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public interface MountProvisionService extends MountService {
+
+    @Override
+    public MountProvisionInstance getMountPoint(InstanceIdentifier path);
+    
+    MountProvisionInstance createMountPoint(InstanceIdentifier path);
+    
+    MountProvisionInstance createOrGetMountPoint(InstanceIdentifier path);
+}
index 678728ab3b86b8d0883dce0f613f2cd42b6e5129..9383a9e2ff50ee2149d1ce034ed6f195dfb0e7e6 100644 (file)
             <groupId>org.opendaylight.controller</groupId>\r
             <artifactId>sal-common-util</artifactId>\r
             <version>1.0-SNAPSHOT</version>\r
+        </dependency>\r
+                <dependency>\r
+            <groupId>org.opendaylight.controller</groupId>\r
+            <artifactId>sal-common-impl</artifactId>\r
+            <version>1.0-SNAPSHOT</version>\r
         </dependency>\r
         <dependency>\r
             <groupId>org.opendaylight.controller</groupId>\r
@@ -60,7 +65,7 @@
                         <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>\r
                         <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>\r
                         <Private-Package>\r
-                            org.opendaylight.controller.sal.dom.broker,\r
+                            org.opendaylight.controller.sal.dom.broker.*\r
                         </Private-Package>\r
                     </instructions>\r
                 </configuration>\r
index 83dda5902dee4e6fd819debabcaecd12ca0413e8..855ad9bd328d19c79b30e09ba4e485e0d1918044 100644 (file)
@@ -7,29 +7,28 @@
  */
 package org.opendaylight.controller.sal.dom.broker;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.controller.sal.core.api.Consumer;
-import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.spi.BrokerModule;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.osgi.framework.BundleContext;
-import org.slf4j.LoggerFactory;
+import java.util.Collections
+import java.util.HashMap
+import java.util.HashSet
+import java.util.Map
+import java.util.Set
+import java.util.concurrent.Callable
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+import java.util.concurrent.Future
+import org.opendaylight.controller.sal.core.api.Broker
+import org.opendaylight.controller.sal.core.api.BrokerService
+import org.opendaylight.controller.sal.core.api.Consumer
+import org.opendaylight.controller.sal.core.api.Provider
+import org.opendaylight.controller.sal.core.spi.BrokerModule
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.common.RpcResult
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.osgi.framework.BundleContext
+import org.slf4j.LoggerFactory
+import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
 import org.opendaylight.yangtools.concepts.ListenerRegistration
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
-import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry
 
 public class BrokerImpl implements Broker {
     private static val log = LoggerFactory.getLogger(BrokerImpl);
@@ -42,17 +41,14 @@ public class BrokerImpl implements Broker {
     private val Map<Class<? extends BrokerService>, BrokerModule> serviceProviders = Collections.
         synchronizedMap(new HashMap<Class<? extends BrokerService>, BrokerModule>());
 
-
-    private val rpcRegistrationListeners = new ListenerRegistry<RpcRegistrationListener>();
-    // RPC Context
-    private val Map<QName, RpcImplementation> rpcImpls = Collections.synchronizedMap(
-        new HashMap<QName, RpcImplementation>());
-
     // Implementation specific
     @Property
     private var ExecutorService executor = Executors.newFixedThreadPool(5);
     @Property
     private var BundleContext bundleContext;
+    
+    @Property
+    private var RpcRouter router;
 
     override registerConsumer(Consumer consumer, BundleContext ctx) {
         checkPredicates(consumer);
@@ -95,42 +91,8 @@ public class BrokerImpl implements Broker {
         return prov.getServiceForSession(service, session);
     }
 
-    // RPC Functionality
-    protected def void addRpcImplementation(QName rpcType, RpcImplementation implementation) {
-        if(rpcImpls.get(rpcType) != null) {
-            throw new IllegalStateException("Implementation for rpc " + rpcType + " is already registered.");
-        }
-
-        
-        rpcImpls.put(rpcType, implementation);
-
-        
-        for(listener : rpcRegistrationListeners.listeners)  {
-            try {
-                listener.instance.onRpcImplementationAdded(rpcType);
-            } catch (Exception e){
-                log.error("Unhandled exception during invoking listener",e);
-            }
-        }
-    }
-
-    protected def void removeRpcImplementation(QName rpcType, RpcImplementation implToRemove) {
-        if(implToRemove == rpcImpls.get(rpcType)) {
-            rpcImpls.remove(rpcType);
-        }
-        
-        for(listener : rpcRegistrationListeners.listeners)  {
-            try {
-                listener.instance.onRpcImplementationRemoved(rpcType);
-            } catch (Exception e){
-                log.error("Unhandled exception during invoking listener",e);
-            }
-        }
-    }
-
     protected def Future<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
-        val impl = rpcImpls.get(rpc);
-        val result = executor.submit([|impl.invokeRpc(rpc, input)] as Callable<RpcResult<CompositeNode>>);
+        val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable<RpcResult<CompositeNode>>);
         return result;
     }
 
@@ -171,12 +133,4 @@ public class BrokerImpl implements Broker {
         sessions.remove(consumerContextImpl);
         providerSessions.remove(consumerContextImpl);
     }
-    
-    protected def getSupportedRpcs() {
-        rpcImpls.keySet;
-    }
-    
-    def ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener) {
-        rpcRegistrationListeners.register(listener);
-    }
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointImpl.java
new file mode 100644 (file)
index 0000000..7037b46
--- /dev/null
@@ -0,0 +1,118 @@
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter;
+import org.opendaylight.controller.sal.dom.broker.impl.NotificationRouterImpl;
+import org.opendaylight.controller.sal.dom.broker.impl.RpcRouterImpl;
+import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter;
+import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class MountPointImpl implements MountProvisionInstance {
+
+    final RpcRouter rpcs;
+    final DataReaderRouter dataReader;
+    final NotificationRouter notificationRouter;
+
+    public MountPointImpl(InstanceIdentifier path) {
+        rpcs = new RpcRouterImpl("");
+        dataReader = new DataReaderRouter();
+        notificationRouter = new NotificationRouterImpl();
+    }
+
+    @Override
+    public void publish(CompositeNode notification) {
+        notificationRouter.publish(notification);
+    }
+
+    @Override
+    public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+        return notificationRouter.addNotificationListener(notification, listener);
+    }
+
+    @Override
+    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        return dataReader.readConfigurationData(path);
+    }
+
+    @Override
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        return dataReader.readOperationalData(path);
+    }
+
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return dataReader.registerOperationalReader(path, reader);
+    }
+
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return dataReader.registerConfigurationReader(path, reader);
+    }
+
+    @Override
+    public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
+        return rpcs.addRoutedRpcImplementation(rpcType, implementation);
+    }
+
+    @Override
+    public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation)
+            throws IllegalArgumentException {
+        return rpcs.addRpcImplementation(rpcType, implementation);
+    }
+
+    public Set<QName> getSupportedRpcs() {
+        return rpcs.getSupportedRpcs();
+    }
+
+    
+    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+        return rpcs.invokeRpc(rpc, input);
+    }
+
+    public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener) {
+        return rpcs.addRpcRegistrationListener(listener);
+    }
+
+
+    @Override
+    public Future<RpcResult<CompositeNode>> rpc(QName type, CompositeNode input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public DataModificationTransaction beginTransaction() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+            DataChangeListener listener) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void sendNotification(CompositeNode notification) {
+        publish(notification);
+        
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/MountPointManagerImpl.xtend
new file mode 100644 (file)
index 0000000..c64d1e5
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.sal.dom.broker
+
+
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import java.util.concurrent.ConcurrentMap
+import java.util.concurrent.ConcurrentHashMap
+import static com.google.common.base.Preconditions.*;
+
+class MountPointManagerImpl implements MountProvisionService {
+    
+    ConcurrentMap<InstanceIdentifier,MountPointImpl> mounts = new ConcurrentHashMap();
+    
+    override createMountPoint(InstanceIdentifier path) {
+        checkState(!mounts.containsKey(path),"Mount already created");
+        val mount = new MountPointImpl(path);
+        mounts.put(path,mount);
+    }
+    
+    
+    override createOrGetMountPoint(InstanceIdentifier path) {
+        val mount = mounts.get(path);
+        if(mount === null) {
+            return createMountPoint(path)
+        }
+        return mount;
+    }
+    
+    
+    override getMountPoint(InstanceIdentifier path) {
+        mounts.get(path);
+    }
+    
+    
+}
index 3fdd7065770dac618a2fa5cc15ebeb1c37cb110a..cf5d220943142ad83c948299aeef3222d882b136 100644 (file)
@@ -1,25 +1,23 @@
 package org.opendaylight.controller.sal.dom.broker
 
-import java.util.Collections
-import java.util.HashMap
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
 import org.opendaylight.controller.sal.core.api.Provider
 import org.opendaylight.controller.sal.core.api.RpcImplementation
 import org.opendaylight.yangtools.yang.common.QName
 import org.osgi.framework.BundleContext
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration
-import static java.util.Collections.*
-import java.util.Collections
-import java.util.HashMap
 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
+import org.opendaylight.yangtools.concepts.Registration
+
+import java.util.Set
+import java.util.HashSet
 
 class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession {
 
     @Property
     private val Provider provider;
 
-    private val rpcImpls = Collections.synchronizedMap(new HashMap<QName, RpcImplementation>());
+    private val Set<Registration<?>> registrations = new HashSet();
 
     new(Provider provider, BundleContext ctx) {
         super(null, ctx);
@@ -27,75 +25,61 @@ class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession
     }
 
     override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException {
-        if(rpcType == null) {
-            throw new IllegalArgumentException("rpcType must not be null");
-        }
-        if(implementation == null) {
-            throw new IllegalArgumentException("Implementation must not be null");
-        }
-        broker.addRpcImplementation(rpcType, implementation);
-        rpcImpls.put(rpcType, implementation);
-        
-        return new RpcRegistrationImpl(rpcType, implementation, this);
+        val origReg = broker.router.addRpcImplementation(rpcType, implementation);
+        val newReg = new RpcRegistrationWrapper(origReg);
+        registrations.add(newReg);
+        return newReg;
     }
 
-    def removeRpcImplementation(RpcRegistrationImpl implToRemove) throws IllegalArgumentException {
-        val localImpl = rpcImpls.get(implToRemove.type);
-        if(localImpl !== implToRemove.instance) {
-            throw new IllegalStateException(
-                "Implementation was not registered in this session");
-        }
-        broker.removeRpcImplementation(implToRemove.type,localImpl);
-        rpcImpls.remove(implToRemove.type);
+    protected def removeRpcImplementation(RpcRegistrationWrapper implToRemove) throws IllegalArgumentException {
+        registrations.remove(implToRemove);
     }
     
     override close() {
-               removeAllRpcImlementations
-       super.close
-    }
-    
-    private def removeAllRpcImlementations() {
-       if (!rpcImpls.empty) {
-               for (entry : rpcImpls.entrySet) {
-                       broker.removeRpcImplementation(entry.key,entry.value);
-               }
-               rpcImpls.clear
-       }
+        
+        for (reg : registrations) {
+            reg.close()
+        }
+        super.close
     }
-    
+
     override addMountedRpcImplementation(QName rpcType, RpcImplementation implementation) {
         throw new UnsupportedOperationException("TODO: auto-generated method stub")
     }
-    
+
     override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
         throw new UnsupportedOperationException("TODO: auto-generated method stub")
     }
-    
+
     override getSupportedRpcs() {
-        broker.getSupportedRpcs();
+        broker.router.supportedRpcs;
     }
-    
+
     override addRpcRegistrationListener(RpcRegistrationListener listener) {
-        broker.addRpcRegistrationListener(listener);
+        broker.router.addRpcRegistrationListener(listener);
     }
 }
 
-class RpcRegistrationImpl extends AbstractObjectRegistration<RpcImplementation> implements RpcRegistration {
-       
-       @Property
-       val QName type
-       
-       private var ProviderContextImpl context
-       
-       new(QName type, RpcImplementation instance, ProviderContextImpl ctx) {
-               super(instance)
-               _type = type
-               context = ctx
-       }
-       
-       override protected removeRegistration() {
-               context.removeRpcImplementation(this)
-               context = null  
-       }
+class RpcRegistrationWrapper implements RpcRegistration {
+
+
+    @Property
+    val RpcRegistration delegate
+
+    new(RpcRegistration delegate) {
+        _delegate = delegate
+    }
+
+    override getInstance() {
+        delegate.instance
+    }
 
+    override close() {
+        delegate.close
+    }
+
+    override getType() {
+        delegate.type
+    }
 }
+
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend
new file mode 100644 (file)
index 0000000..1e0f338
--- /dev/null
@@ -0,0 +1,13 @@
+package org.opendaylight.controller.sal.dom.broker.impl
+
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+
+class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
+
+    override protected merge(InstanceIdentifier path, Iterable<CompositeNode> data) {
+        return data.iterator.next
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/NotificationRouterImpl.java
new file mode 100644 (file)
index 0000000..6d7b600
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.dom.broker.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Consumer.ConsumerFunctionality;
+import org.opendaylight.controller.sal.core.api.Provider.ProviderFunctionality;
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.controller.sal.core.spi.BrokerModule;
+import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+
+public class NotificationRouterImpl implements NotificationRouter {
+    private static Logger log = LoggerFactory.getLogger(NotificationRouterImpl.class);
+
+    private Multimap<QName, Registration<NotificationListener>> listeners = HashMultimap.create();
+
+    private void sendNotification(CompositeNode notification) {
+        QName type = notification.getNodeType();
+        Collection<Registration<NotificationListener>> toNotify = listeners.get(type);
+        log.info("Publishing notification " + type);
+
+        if (toNotify == null) {
+            // No listeners were registered - returns.
+            return;
+        }
+
+        for (Registration<NotificationListener> listener : toNotify) {
+            try {
+                // FIXME: ensure that notification is immutable
+                listener.getInstance().onNotification(notification);
+            } catch (Exception e) {
+                log.error("Uncaught exception in NotificationListener", e);
+            }
+        }
+
+    }
+
+    @Override
+    public void publish(CompositeNode notification) {
+        sendNotification(notification);
+    }
+
+    @Override
+    public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+        ListenerRegistration ret = new ListenerRegistration(notification, listener);
+        return ret;
+    }
+
+    private class ListenerRegistration extends AbstractObjectRegistration<NotificationListener> {
+
+        final QName type;
+
+        public ListenerRegistration(QName type, NotificationListener instance) {
+            super(instance);
+            this.type = type;
+        }
+
+        @Override
+        protected void removeRegistration() {
+            listeners.remove(type, this);
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RpcRouterImpl.xtend
new file mode 100644 (file)
index 0000000..d67697f
--- /dev/null
@@ -0,0 +1,106 @@
+package org.opendaylight.controller.sal.dom.broker.impl
+
+import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
+import org.opendaylight.yangtools.concepts.Identifiable
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.controller.sal.core.api.RpcImplementation
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import static com.google.common.base.Preconditions.*;
+import java.util.Map
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration
+import java.util.concurrent.ConcurrentHashMap
+import java.util.Set
+import java.util.Collections
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
+import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
+import org.slf4j.LoggerFactory
+
+class RpcRouterImpl implements RpcRouter, Identifiable<String> {
+
+    static val log = LoggerFactory.getLogger(RpcRouterImpl)
+
+    Map<QName, RpcRegistration> implementations = new ConcurrentHashMap();
+
+    @Property
+    val Set<QName> supportedRpcs = Collections.unmodifiableSet(implementations.keySet);
+
+    private val rpcRegistrationListeners = new ListenerRegistry<RpcRegistrationListener>();
+
+    @Property
+    val String identifier;
+
+    new(String name) {
+        _identifier = name;
+    }
+
+    override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
+    }
+
+    override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException {
+        checkNotNull(rpcType, "Rpc Type should not be null");
+        checkNotNull(implementation, "Implementation should not be null.");
+        checkState(!implementations.containsKey(rpcType), "Provider for supplied rpc is already registered.");
+        val reg = new RpcRegistrationImpl(rpcType, implementation, this);
+        implementations.put(rpcType, reg)
+
+        for (listener : rpcRegistrationListeners.listeners) {
+            try {
+                listener.instance.onRpcImplementationAdded(rpcType);
+            } catch (Exception e) {
+                log.error("Unhandled exception during invoking listener", e);
+            }
+        }
+
+        return reg;
+
+    }
+
+    override invokeRpc(QName rpc, CompositeNode input) {
+        checkNotNull(rpc, "Rpc Type should not be null");
+
+        val impl = implementations.get(rpc);
+        checkState(impl !== null, "Provider for supplied rpc is not registered.");
+
+        return impl.instance.invokeRpc(rpc, input);
+    }
+
+    def remove(RpcRegistrationImpl impl) {
+        val existing = implementations.get(impl.type);
+        if (existing == impl) {
+            implementations.remove(impl.type);
+        }
+        for (listener : rpcRegistrationListeners.listeners) {
+            try {
+                listener.instance.onRpcImplementationRemoved(impl.type);
+            } catch (Exception e) {
+                log.error("Unhandled exception during invoking listener", e);
+            }
+        }
+    }
+    
+    override addRpcRegistrationListener(RpcRegistrationListener listener) {
+        rpcRegistrationListeners.register(listener);
+    }
+
+}
+
+class RpcRegistrationImpl extends AbstractObjectRegistration<RpcImplementation> implements RpcRegistration {
+
+    @Property
+    val QName type;
+
+    @Property
+    var RpcRouterImpl router;
+
+    new(QName type, RpcImplementation instance, RpcRouterImpl router) {
+        super(instance)
+        _type = type
+        _router = router
+    }
+
+    override protected removeRegistration() {
+        router.remove(this);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/NotificationRouter.java
new file mode 100644 (file)
index 0000000..fc42d2c
--- /dev/null
@@ -0,0 +1,21 @@
+package org.opendaylight.controller.sal.dom.broker.spi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface NotificationRouter {
+
+    void publish(CompositeNode notification);
+
+    /**
+     * Registers a notification listener for supplied notification type.
+     * 
+     * @param notification
+     * @param listener
+     */
+    Registration<NotificationListener> addNotificationListener(QName notification,
+            NotificationListener listener);
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java
new file mode 100644 (file)
index 0000000..97c2a15
--- /dev/null
@@ -0,0 +1,27 @@
+package org.opendaylight.controller.sal.dom.broker.spi;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public interface RoutedRpcProcessor extends RpcImplementation {
+
+    public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation);
+
+    public Set<QName> getSupportedRpcs();
+
+    public QName getRpcType();
+    
+    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input);
+
+    Map<InstanceIdentifier,RpcImplementation> getRoutes();
+    
+    RpcImplementation getDefaultRoute();
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java
new file mode 100644 (file)
index 0000000..6886f89
--- /dev/null
@@ -0,0 +1,31 @@
+package org.opendaylight.controller.sal.dom.broker.spi;
+
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface RpcRouter extends RpcProvisionRegistry, RpcImplementation {
+
+    @Override
+    public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation);
+    
+    @Override
+    public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation)
+            throws IllegalArgumentException;
+    
+    @Override
+    public Set<QName> getSupportedRpcs();
+    
+    @Override
+    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input);
+
+    ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener);
+}
index c8bc71577dea0014e3dd248b88d571b00c399c21..57e4d858c196beee2c9bf5a5d6ac04a7ed0d6d78 100644 (file)
@@ -6,6 +6,9 @@
         <artifactId>sal-parent</artifactId>
         <version>1.0-SNAPSHOT</version>
     </parent>
+    <properties>
+        <netconf.version>0.2.2-SNAPSHOT</netconf.version>
+    </properties>
     <artifactId>sal-netconf-connector</artifactId>
     <scm>
         <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
             <groupId>${project.groupId}</groupId>
             <artifactId>sal-connector-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-client</artifactId>
+            <version>0.2.2-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-test</artifactId>
+            <version>${netconf.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-api</artifactId>
+            <version>${netconf.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-util</artifactId>
+            <version>${netconf.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-store-api</artifactId>
+            <version>${netconf.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-api</artifactId>
+            <version>${netconf.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.bgpcep</groupId>
+            <artifactId>util</artifactId>
+            <scope>test</scope>
+            <version>0.3.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-client</artifactId>
+            <scope>test</scope>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-netconf-connector</artifactId>
+            <scope>test</scope>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-test</artifactId>
+            <scope>test</scope>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-manager</artifactId>
+            <scope>test</scope>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-persister-impl</artifactId>
+            <scope>test</scope>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>config-manager</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-impl</artifactId>
+            <scope>test</scope>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-mapping-api</artifactId>
+            <scope>test</scope>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>netconf-util</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-store-impl</artifactId>
+            <scope>test</scope>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-store-impl</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>logback-config</artifactId>
+            <scope>test</scope>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
     </dependencies>
 
     <packaging>bundle</packaging>
index c32e3505097b9d07c9f881935ab336604b7b8c4c..b4cf6c985b6aa8a9995ccb43ed4c27fe6f494166 100644 (file)
@@ -45,7 +45,9 @@ final class TestUtils {
         }
         for (int i = 0; i < fileList.length; i++) {
             String fileName = fileList[i];
-            testFiles.add(new File(testDir, fileName));
+            if (new File(testDir, fileName).isDirectory() == false) {
+                testFiles.add(new File(testDir, fileName));
+            }
         }
         return parser.parseYangModels(testFiles);
     }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversion.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversion.java
new file mode 100644 (file)
index 0000000..841f8e5
--- /dev/null
@@ -0,0 +1,273 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.*;
+
+import java.io.*;
+import java.util.Set;
+import java.util.regex.*;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.*;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public class YangAndXmlToJsonConversion {
+
+    @Ignore
+    @Test
+    /**
+     * Test for simple yang types (leaf, list, leaf-list, container and various combination of them)
+     * 
+     */
+    public void simpleYangTypesTest() {
+        String jsonOutput = null;
+
+        jsonOutput = convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+                "/yang-to-json-conversion/simple-yang-types");
+
+//         jsonOutput =
+//         readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/output.json");
+
+        verifyJsonOutputForSimpleYangTypes(jsonOutput);
+
+    }
+
+    private void verifyJsonOutputForSimpleYangTypes(String jsonOutput) {
+
+        assertTrue("First and last character has to be '{' and '}'", Pattern.compile("\\A\\{.*\\}\\z", Pattern.DOTALL)
+                .matcher(jsonOutput).matches());
+
+        String prefix = "\"(smptp:|)";
+
+        // subnodes of cont1
+        String cont1 = prefix + "cont1\":\\{";
+        testLeaf(cont1, "lf11", new String("lf"), jsonOutput, prefix);
+        testLeafList(cont1, "lflst11", jsonOutput, prefix, new Integer(55), new Integer(56), new Integer(57));
+        testLeafList(cont1, "lflst12", jsonOutput, prefix, new String("lflst12 str1"), new String("lflst12 str2"),
+                new String("lflst12 str1"));
+
+        // subnodes of lst111
+        // first object of lst111
+        String lst11 = cont1 + ".*" + prefix + "lst11\":\\[\\{";
+        testLeaf(lst11, "lf111", new Integer(140), jsonOutput, prefix);
+        testLeaf(lst11, "lf112", new String("lf112 str"), jsonOutput, prefix);
+
+        // subnodes of cont111
+        String cont111 = lst11 + ".*" + prefix + "cont111\":\\{";
+        testLeaf(cont111, "lf1111", new String("lf1111 str"), jsonOutput, prefix);
+        testLeafList(cont1, "lflst1111", jsonOutput, prefix, new Integer(2048), new Integer(1024), new Integer(4096));
+
+        // subnodes of lst1111
+        String lst1111 = cont111 + ".*" + prefix + "lst1111\":\\[\\{";
+        testLeaf(lst1111, "lf1111A", new String("lf1111A str11"), jsonOutput, prefix);
+        testLeaf(lst1111, "lf1111B", new Integer(4), jsonOutput, prefix);
+        testLeaf(lst1111, "lf1111A", new String("lf1111A str12"), jsonOutput, prefix);
+        testLeaf(lst1111, "lf1111B", new Integer(7), jsonOutput, prefix);
+        // :subnodes of lst1111
+        // :subnodes of cont111
+        // :first object of lst111
+
+        // second object of lst111
+        testLeaf(lst11, "lf111", new Integer(141), jsonOutput, prefix);
+        testLeaf(lst11, "lf112", new String("lf112 str2"), jsonOutput, prefix);
+
+        // subnodes of cont111
+        testLeaf(cont111, "lf1111", new String("lf1111 str2"), jsonOutput, prefix);
+        testLeafList(cont1, "lflst1111", jsonOutput, prefix, new Integer(2049), new Integer(1025), new Integer(4097));
+
+        // subnodes of lst1111
+        testLeaf(lst1111, "lf1111A", new String("lf1111A str21"), jsonOutput, prefix);
+        testLeaf(lst1111, "lf1111B", new Integer(5), jsonOutput, prefix);
+        testLeaf(lst1111, "lf1111A", new String("lf1111A str22"), jsonOutput, prefix);
+        testLeaf(lst1111, "lf1111B", new Integer(8), jsonOutput, prefix);
+        // :subnodes of lst111
+        // :subnodes of cont111
+        // :second object of lst111
+        // :second object of lst111
+        // :subnodes of cont1
+    }
+
+    private void testLeaf(String prevRegEx, String lstName, Object value, String jsonFile, String elementPrefix) {
+        String newValue = null;
+        if (value instanceof Integer) {
+            newValue = value.toString();
+        } else if (value instanceof String) {
+            newValue = "\"" + value.toString() + "\"";
+        }
+        String lf = elementPrefix + lstName + "\":" + newValue;
+        assertTrue(">>\"" + lstName + "\":" + newValue + "<< is missing",
+                Pattern.compile(".*" + prevRegEx + ".*" + lf + ".*", Pattern.DOTALL).matcher(jsonFile).matches());
+
+    }
+
+    private void testLeafList(String prevRegEx, String lflstName, String jsonFile, String elementPrefix,
+            Object... dataInList) {
+        // order of element in the list isn't defined :(
+        String lflstBegin = elementPrefix + lflstName + "\":\\[";
+        String lflstEnd = ".*\\],";
+        assertTrue(
+                ">>\"" + lflstName + "\": [],<< is missing",
+                Pattern.compile(".*" + prevRegEx + ".*" + lflstBegin + lflstEnd + ".*", Pattern.DOTALL)
+                        .matcher(jsonFile).matches());
+
+        for (Object obj : dataInList) {
+            testValueOfLeafList(prevRegEx, lflstBegin, obj, jsonFile);
+        }
+    }
+
+    private void testValueOfLeafList(String prevRegEx, String lflstPrevRegEx, Object value, String jsonFile) {
+        String lflstData = null;
+        lflstData = regExForDataValueInList(value);
+        assertNotNull(lflstPrevRegEx + ": value doesn't have correct type.", lflstData);
+        assertTrue(
+                prevRegEx + ": data value >" + value + "< is missing.",
+                Pattern.compile(".*" + prevRegEx + ".*" + lflstPrevRegEx + lflstData + ".*", Pattern.DOTALL)
+                        .matcher(jsonFile).matches());
+
+    }
+
+    /**
+     * Data value can be first, inner, last or only one member of list
+     * 
+     * @param dataValue
+     * @return
+     */
+    private String regExForDataValueInList(Object dataValue) {
+        String newDataValue;
+        if (dataValue instanceof Integer) {
+            newDataValue = dataValue.toString();
+            return "(" + newDataValue + "(,[0-9]+)+|([0-9]+,)+" + newDataValue + "(,[0-9]+)+|([0-9]+,)+" + newDataValue
+                    + "|" + newDataValue + ")\\]";
+        } else if (dataValue instanceof String) {
+            newDataValue = "\"" + dataValue.toString() + "\"";
+            return "(" + newDataValue + "(,\".+\")+|(\".+\",)+" + newDataValue + "(,\".+\")+|(\".+\",)+" + newDataValue
+                    + "|" + newDataValue + ")\\]";
+        }
+        return null;
+    }
+
+    private String readJsonFromFile(String path) {
+        String fullPath = YangAndXmlToJsonConversion.class.getResource(path).getPath();
+        assertNotNull("Path to file can't be null.", fullPath);
+        File file = new File(fullPath);
+        assertNotNull("File can't be null", file);
+        FileReader fileReader = null;
+        try {
+            fileReader = new FileReader(file);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("File reader can't be null.", fileReader);
+
+        StringBuilder strBuilder = new StringBuilder();
+        char[] buffer = new char[1000];
+
+        while (true) {
+            int loadedCharNum;
+            try {
+                loadedCharNum = fileReader.read(buffer);
+            } catch (IOException e) {
+                break;
+            }
+            if (loadedCharNum == -1) {
+                break;
+            }
+            strBuilder.append(buffer, 0, loadedCharNum);
+        }
+        try {
+            fileReader.close();
+        } catch (IOException e) {
+            System.out.println("The file wasn't closed");
+            ;
+        }
+        String rawStr = strBuilder.toString();
+        rawStr = rawStr.replace("\n", "");
+        rawStr = rawStr.replace("\r", "");
+        rawStr = rawStr.replace("\t", "");
+        rawStr = removeSpaces(rawStr);
+
+        return rawStr;
+    }
+
+    private String removeSpaces(String rawStr) {
+        StringBuilder strBuilder = new StringBuilder();
+        int i = 0;
+        int quoteCount = 0;
+        while (i < rawStr.length()) {
+            if (rawStr.substring(i, i + 1).equals("\"")) {
+                quoteCount++;
+            }
+
+            if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
+                strBuilder.append(rawStr.charAt(i));
+            }
+            i++;
+        }
+
+        return strBuilder.toString();
+    }
+
+    private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+        String jsonResult = null;
+        Set<Module> modules = null;
+
+        try {
+            modules = TestUtils.loadModules(YangAndXmlToJsonConversion.class.getResource(yangPath).getPath());
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("modules can't be null.", modules);
+
+        InputStream xmlStream = YangAndXmlToJsonConversion.class.getResourceAsStream(xmlDataPath);
+        CompositeNode compositeNode = null;
+        try {
+            compositeNode = TestUtils.loadCompositeNode(xmlStream);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("Composite node can't be null", compositeNode);
+
+        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+        for (Module module : modules) {
+            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+                try {
+                    structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+                } catch (WebApplicationException | IOException e) {
+                    e.printStackTrace();
+                }
+                assertFalse(
+                        "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+                        byteArrayOS.toString().isEmpty());
+                jsonResult = byteArrayOS.toString();
+                try {
+                    outputToFile(byteArrayOS);
+                } catch (IOException e) {
+                    System.out.println("Output file wasn't cloased sucessfuly.");
+                }
+            }
+        }
+        return jsonResult;
+    }
+
+    private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+        FileOutputStream fileOS = null;
+        try {
+            String path = YangAndXmlToJsonConversion.class.getResource("/yang-to-json-conversion/xml").getPath();
+            File outFile = new File(path + "/data.json");
+            fileOS = new FileOutputStream(outFile);
+            try {
+                fileOS.write(outputStream.toByteArray());
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            fileOS.close();
+        } catch (FileNotFoundException e1) {
+            e1.printStackTrace();
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/simple-yang-types.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/simple-yang-types.yang
new file mode 100644 (file)
index 0000000..760dbd7
--- /dev/null
@@ -0,0 +1,47 @@
+module simple-yang-types {
+  namespace "simple:yang:types";  
+
+  prefix "smptp";
+   revision 2013-11-5 {
+    description  "Initial revision.";
+  }
+  
+  container cont1 {
+         leaf lf11 {
+               type string;
+         }
+         leaf-list lflst11 {
+               type int32;
+         }
+         leaf-list lflst12 {
+               type string;
+         }
+         list lst11 {
+               key lf111;
+               leaf lf111 {
+                       type uint8;
+               }
+               leaf lf112 {
+                       type string;
+               }               
+               container cont111 {
+                       leaf lf1111 {
+                               type string;
+                       }
+                       leaf-list lflst1111 {
+                               type int32;
+                       }
+                       list lst1111 {
+                               leaf lf1111A {
+                                       type string;
+                               }
+                               leaf lf1111B {
+                                       type uint8;
+                               }
+                       }
+               }
+         }
+         
+  }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json
new file mode 100644 (file)
index 0000000..e76e7bd
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    "smptp:cont1": {
+        "lf11":"lf",
+        "lflst11": [55,56,57],
+        "lflst12": ["lflst12 str1", "lflst12 str2", "lflst12 str3"],
+        "lst11": [
+            {
+                "lf111":140,
+                "lf112":"lf112 str",
+                "cont111": {
+                    "lf1111":"lf1111 str",
+                    "lflst1111": [2048, 1024, 4096],
+                    "lst1111": [
+                    {
+                        "lf1111A": "lf1111A str11",
+                        "lf1111B": 4
+                    },
+                    {
+                        "lf1111A": "lf1111A str12",
+                        "lf1111B": 7
+                    }
+                    ]
+                }
+            },
+            {
+                "lf111":141,
+                "lf112":"lf112 str2",
+                "cont111": {
+                    "lf1111":"lf1111 str2",
+                    "lflst1111": [2049, 1025, 4097],
+                    "lst1111": [
+                    {
+                        "lf1111A": "lf1111A str21",
+                        "lf1111B": 5
+                    },
+                    {
+                        "lf1111A": "lf1111A str22",
+                        "lf1111B": 8
+                    }
+                    ]
+                }
+            }        
+        ]
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/data.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/data.xml
new file mode 100644 (file)
index 0000000..b47987c
--- /dev/null
@@ -0,0 +1,45 @@
+<cont1>
+       <lf11>lf</lf11>
+       <lflst11>55</lflst11>
+       <lflst11>56</lflst11>
+       <lflst11>57</lflst11>
+       <lflst12>lflst12 str1</lflst12>
+       <lflst12>lflst12 str2</lflst12>
+       <lflst12>lflst12 str3</lflst12>
+       <lst11>
+               <lf111>140</lf111>
+               <lf112>lf112 str</lf112>
+               <cont111>
+                       <lf1111>lf1111 str</lf1111>
+                       <lflst1111>2048</lflst1111>
+                       <lflst1111>1024</lflst1111>
+                       <lflst1111>4096</lflst1111>
+                       <lst1111>
+                               <lf1111A>lf1111A str11</lf1111A>
+                               <lf1111B>4</lf1111B>
+                       </lst1111>
+                       <lst1111>
+                               <lf1111A>lf1111A str12</lf1111A>
+                               <lf1111B>7</lf1111B>
+                       </lst1111>
+               </cont111>
+       </lst11>
+       <lst11>
+               <lf111>141</lf111>
+               <lf112>lf112 str2</lf112>
+               <cont111>
+                       <lf1111>lf1111 str2</lf1111>
+                       <lflst1111>2049</lflst1111>
+                       <lflst1111>1025</lflst1111>
+                       <lflst1111>4097</lflst1111>
+                       <lst1111>
+                               <lf1111A>lf1111A str21</lf1111A>
+                               <lf1111B>5</lf1111B>
+                       </lst1111>
+                       <lst1111>
+                               <lf1111A>lf1111A str22</lf1111A>
+                               <lf1111B>8</lf1111B>
+                       </lst1111>
+               </cont111>      
+       </lst11>
+</cont1>
diff --git a/opendaylight/md-sal/sal-zeromq-connector/pom.xml b/opendaylight/md-sal/sal-zeromq-connector/pom.xml
new file mode 100644 (file)
index 0000000..3db4a65
--- /dev/null
@@ -0,0 +1,96 @@
+<?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>
+    </parent>
+
+
+    <artifactId>sal-zeromq-connector</artifactId>
+    <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>
+                        org.opendaylight.controller.sal.connector.api,
+                        org.opendaylight.controller.sal.core.api,
+                        org.opendaylight.yangtools.concepts;version="[0.1,1)",
+                        org.opendaylight.yangtools.yang.common;version="[0.5,1)",
+                        org.opendaylight.yangtools.yang.data.api;version="[0.5,1)",
+                        org.zeromq;version="[0.3,1)"
+                        </Import-Package>
+                        <Bundle-Activator>org.opendaylight.controller.sal.connector.zeromq.Activator</Bundle-Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>containermanager</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>commons.northbound</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.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>
+        </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.jeromq</groupId>
+            <artifactId>jeromq</artifactId>
+            <version>0.3.0-SNAPSHOT</version>
+        </dependency>
+
+    </dependencies>
+    <repositories>
+        <repository>
+            <id>sonatype-nexus-snapshots</id>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+</project>
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Activator.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Activator.java
new file mode 100644 (file)
index 0000000..b8933ec
--- /dev/null
@@ -0,0 +1,23 @@
+package org.opendaylight.controller.sal.connector.zeromq;
+
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.osgi.framework.BundleContext;
+
+public class Activator extends AbstractProvider {
+    
+    ZeroMqRpcRouter router;
+    
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+        router = ZeroMqRpcRouter.getInstance();
+        router.setBrokerSession(session);
+        router.start();
+    }
+    
+    @Override
+    protected void stopImpl(BundleContext context) {
+       router.stop();
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Message.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/Message.java
new file mode 100644 (file)
index 0000000..dd87646
--- /dev/null
@@ -0,0 +1,150 @@
+package org.opendaylight.controller.sal.connector.zeromq;
+
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+
+import java.io.*;
+import java.util.Arrays;
+
+public class Message implements Serializable {
+
+ public enum MessageType {
+    ANNOUNCE((byte) 0),
+    HEARTBEAT((byte) 1),
+    REQUEST((byte) 2),
+    RESPONSE((byte) 3);
+
+    private final byte type;
+
+    MessageType(byte type) {
+      this.type = type;
+    }
+
+    public byte getType(){
+      return this.type;
+    }
+  }
+
+  private MessageType type;
+  private String sender;
+  private RpcRouter.RouteIdentifier route;
+  private Object payload;
+
+  public MessageType getType() {
+    return type;
+  }
+
+  public void setType(MessageType type) {
+    this.type = type;
+  }
+
+  public String getSender() {
+    return sender;
+  }
+
+  public void setSender(String sender) {
+    this.sender = sender;
+  }
+
+  public RpcRouter.RouteIdentifier getRoute() {
+    return route;
+  }
+
+  public void setRoute(RpcRouter.RouteIdentifier route) {
+    this.route = route;
+  }
+
+  public Object getPayload() {
+    return payload;
+  }
+
+  public void setPayload(Object payload) {
+    this.payload = payload;
+  }
+
+  @Override
+  public String toString() {
+    return "Message{" +
+        "type=" + type +
+        ", sender='" + sender + '\'' +
+        ", route=" + route +
+        ", payload=" + payload +
+        '}';
+  }
+
+  /**
+   * Converts any {@link Serializable} object to byte[]
+   *
+   * @param obj
+   * @return
+   * @throws IOException
+   */
+  public static byte[] serialize(Object obj) throws IOException {
+    ByteArrayOutputStream b = new ByteArrayOutputStream();
+    ObjectOutputStream o = new ObjectOutputStream(b);
+    o.writeObject(obj);
+    return b.toByteArray();
+  }
+
+  /**
+   * Converts byte[] to a java object
+   *
+   * @param bytes
+   * @return
+   * @throws IOException
+   * @throws ClassNotFoundException
+   */
+  public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
+    ByteArrayInputStream b = new ByteArrayInputStream(bytes);
+    ObjectInputStream o = new ObjectInputStream(b);
+    return o.readObject();
+  }
+
+  public static byte[] toJsonBytes(Message m){
+    ObjectMapper o = new ObjectMapper();
+    try {
+      System.out.println(o.writeValueAsString(m));
+      return o.writeValueAsBytes(m);
+    } catch (IOException e) {
+      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+    }
+    return null;
+  }
+
+  public static Message fromJsonBytes(byte [] bytes){
+
+    ObjectMapper o = new ObjectMapper();
+    Message m = null;
+    try {
+      m = o.readValue(bytes, Message.class);
+    } catch (IOException e) {
+      e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+    }
+    return m;
+  }
+
+  public static class Response extends Message implements RpcRouter.RpcReply {
+    private ResponseCode code; // response code
+
+    public static enum ResponseCode {
+      SUCCESS(200), BADREQUEST(400), TIMEOUT(408), GONE(410), SERVERERROR(500), SERVICEUNAVAILABLE(503);
+
+      private int code;
+
+      ResponseCode(int code) {
+        this.code = code;
+      }
+    }
+
+    public ResponseCode getCode() {
+      return code;
+    }
+
+    public void setCode(ResponseCode code) {
+      this.code = code;
+    }
+  }
+
+}
+
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RouteIdentifierImpl.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RouteIdentifierImpl.java
new file mode 100644 (file)
index 0000000..8eab01b
--- /dev/null
@@ -0,0 +1,53 @@
+package org.opendaylight.controller.sal.connector.zeromq;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import java.io.Serializable;
+
+/**
+ * User: abhishk2
+ */
+public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>,Serializable {
+
+  private QName context;
+  private QName type;
+  private InstanceIdentifier route;
+
+  @Override
+  public QName getContext() {
+    return this.context;
+  }
+
+  @Override
+  public QName getType() {
+    return this.type;
+  }
+
+  @Override
+  public InstanceIdentifier getRoute() {
+    return this.route;
+  }
+
+  public void setContext(QName context) {
+    this.context = context;
+  }
+
+  public void setType(QName type) {
+    this.type = type;
+  }
+
+  public void setRoute(InstanceIdentifier route) {
+    this.route = route;
+  }
+
+  @Override
+  public String toString() {
+    return "RouteIdentifierImpl{" +
+        "context=" + context +
+        ", type=" + type +
+        ", route=" + route +
+        '}';
+  }
+}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcReplyImpl.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcReplyImpl.java
new file mode 100644 (file)
index 0000000..66ff714
--- /dev/null
@@ -0,0 +1,26 @@
+package org.opendaylight.controller.sal.connector.zeromq;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+
+import java.io.Serializable;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: abhishk2
+ * Date: 10/24/13
+ * Time: 4:25 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class RpcReplyImpl implements RpcRouter.RpcReply<Object>,Serializable {
+
+  private Object payload;
+
+  @Override
+  public Object getPayload() {
+    return payload;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+
+  public void setPayload(Object payload){
+    this.payload = payload;
+  }
+}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcRequestImpl.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/RpcRequestImpl.java
new file mode 100644 (file)
index 0000000..2361ab7
--- /dev/null
@@ -0,0 +1,39 @@
+package org.opendaylight.controller.sal.connector.zeromq;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import java.io.Serializable;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: abhishk2
+ * Date: 10/25/13
+ * Time: 12:32 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class RpcRequestImpl implements RpcRouter.RpcRequest<QName, QName, InstanceIdentifier, Object>,Serializable {
+
+  private RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier;
+  private Object payload;
+
+  @Override
+  public RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> getRoutingInformation() {
+    return routeIdentifier;
+  }
+
+  public void setRouteIdentifier(RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier) {
+    this.routeIdentifier = routeIdentifier;
+  }
+
+  @Override
+  public Object getPayload() {
+    return payload;
+  }
+
+  public void setPayload(Object payload) {
+    this.payload = payload;
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/ZeroMqRpcRouter.java b/opendaylight/md-sal/sal-zeromq-connector/src/main/java/org/opendaylight/controller/sal/connector/zeromq/ZeroMqRpcRouter.java
new file mode 100644 (file)
index 0000000..7e5efda
--- /dev/null
@@ -0,0 +1,337 @@
+package org.opendaylight.controller.sal.connector.zeromq;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.zeromq.ZMQ;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.*;
+import java.util.concurrent.*;
+
+public class ZeroMqRpcRouter implements RpcRouter<QName, QName, InstanceIdentifier, Object> {
+
+  private ExecutorService serverPool;
+  private static ExecutorService handlersPool;
+
+  private Map<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
+
+  private ProviderSession brokerSession;
+
+  private ZMQ.Context context;
+  private ZMQ.Socket publisher;
+  private ZMQ.Socket subscriber;
+  private ZMQ.Socket replySocket;
+
+  private static ZeroMqRpcRouter _instance = new ZeroMqRpcRouter();
+
+  private final RpcFacade facade = new RpcFacade();
+  private final RpcListener listener = new RpcListener();
+
+  private String pubPort = System.getProperty("pub.port");//port on which announcements are sent
+  private String subPort = System.getProperty("sub.port");//other controller's pub port
+  private String pubIp = System.getProperty("pub.ip");    //other controller's ip
+  private String rpcPort = System.getProperty("rpc.port");//port on which RPC messages are received
+
+
+  private ZeroMqRpcRouter() {
+  }
+
+  public static ZeroMqRpcRouter getInstance() {
+    return _instance;
+  }
+
+  public void start() {
+    context = ZMQ.context(2);
+    serverPool = Executors.newSingleThreadExecutor();
+    handlersPool = Executors.newCachedThreadPool();
+    routingTable = new ConcurrentHashMap<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
+
+    // Start listening for announce and rpc messages
+    serverPool.execute(receive());
+
+    
+    brokerSession.addRpcRegistrationListener(listener);
+    Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
+    for(QName rpc : currentlySupported) {
+        listener.onRpcImplementationAdded(rpc);
+    }
+
+
+  }
+
+  public void stop() {
+    if (handlersPool != null) handlersPool.shutdown();
+    if (serverPool != null) serverPool.shutdown();
+    if (publisher != null) {
+      publisher.setLinger(0);
+      publisher.close();
+    }
+    if (replySocket != null) {
+      replySocket.setLinger(0);
+      replySocket.close();
+    }
+    if (subscriber != null) {
+      subscriber.setLinger(0);
+      subscriber.close();
+    }
+    if (context != null) context.term();
+
+
+  }
+
+  private Runnable receive() {
+    return new Runnable() {
+      public void run() {
+        try {
+          // Bind to RPC reply socket
+          replySocket = context.socket(ZMQ.REP);
+          replySocket.bind("tcp://*:" + rpcPort);
+
+          // Bind to publishing controller
+          subscriber = context.socket(ZMQ.SUB);
+          subscriber.connect("tcp://" + pubIp + ":" + subPort);
+          System.out.println("Subscribing at[" + "tcp://" + pubIp + ":" + subPort + "]");
+
+          subscriber.subscribe(Message.serialize(Message.MessageType.ANNOUNCE));
+
+          // Initialize poll set
+          ZMQ.Poller poller = new ZMQ.Poller(2);
+          poller.register(replySocket, ZMQ.Poller.POLLIN);
+          poller.register(subscriber, ZMQ.Poller.POLLIN);
+
+          while (!Thread.currentThread().isInterrupted()) {
+
+            poller.poll(250);
+            //TODO: Fix this
+            if (poller.pollin(0)) {
+              //receive rpc request and reply
+              try {
+                Message req = parseMessage(replySocket);
+                Message resp = new Message();
+                //Call broker to process the message then reply
+                Future<RpcResult<CompositeNode>> rpc = brokerSession.rpc((QName) req.getRoute().getType(), (CompositeNode) req.getPayload());
+                RpcResult<CompositeNode> result = rpc.get();
+                resp.setType(Message.MessageType.RESPONSE);
+                resp.setSender(getLocalIpAddress() + ":" + rpcPort);
+                resp.setRoute(req.getRoute());
+                resp.setPayload(result.isSuccessful());
+                replySocket.send(Message.serialize(resp));
+
+              } catch (IOException ex) {// | ClassNotFoundException ex) {
+                System.out.println("Rpc request could not be handled" + ex);
+              }
+            }
+            if (poller.pollin(1)) {
+              //get subscription and update routing table
+              //try {
+              Message.MessageType topic = (Message.MessageType)Message.deserialize(subscriber.recv());
+              System.out.println("Topic:[" + topic + "]");
+
+              if (subscriber.hasReceiveMore()) {
+                try {
+                  Message m = (Message) Message.deserialize(subscriber.recv());
+                  System.out.println(m);
+                  //TODO: check on msg type or topic. Both should be same. Need to normalize.
+                  if (Message.MessageType.ANNOUNCE == m.getType()) updateRoutingTable(m);
+                } catch (IOException | ClassNotFoundException e) {
+                  e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+                }
+              }
+//
+            }
+          }
+        } catch (Exception e) {
+          e.printStackTrace();
+        }
+        replySocket.setLinger(0);
+        replySocket.close();
+        subscriber.setLinger(0);
+        subscriber.close();
+      }
+    };
+  }
+
+  private void updateRoutingTable(Message msg) {
+    routingTable.put(msg.getRoute(), msg.getSender());
+    RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> route = msg.getRoute();
+    QName rpcType = route.getType();
+    System.out.println("Routing Table\n" + routingTable);
+
+    RpcRegistration registration = brokerSession.addRpcImplementation(rpcType, facade);
+  }
+
+  private Message parseMessage(ZMQ.Socket socket) {
+    //Message m = new Message();
+    //socket.setReceiveBufferSize(40000);
+    Message msg = null;
+    try {
+      byte[] bytes = socket.recv();
+      System.out.println("Received bytes:[" + bytes.length + "]");
+      msg = (Message) Message.deserialize(bytes);
+    } catch (Throwable t) {
+      System.out.println("Caught exception");
+      t.printStackTrace();
+    }
+    return msg;
+    /*m.setType((Message.MessageType) Message.deserialize(socket.recv()));
+
+    if (socket.hasReceiveMore()) {
+      m.setSender((String) Message.deserialize(socket.recv()));
+    }
+    if (socket.hasReceiveMore()) {
+      m.setRoute((RouteIdentifier) Message.deserialize(socket.recv()));
+    }
+    if (socket.hasReceiveMore()) {
+      m.setPayload(Message.deserialize(socket.recv()));
+    }
+    return m;*/
+  }
+
+  @Override
+  public Future<RpcReply<Object>> sendRpc(final RpcRequest<QName, QName, InstanceIdentifier, Object> input) {
+
+    return handlersPool.submit(new Callable<RpcReply<Object>>() {
+
+      @Override
+      public RpcReply<Object> call() {
+        ZMQ.Socket requestSocket = context.socket(ZMQ.REQ);
+        Message req = new Message();
+        Message resp = null;
+        RpcReplyImpl reply = new RpcReplyImpl();
+        requestSocket.connect((String) routingTable.get(input.getRoutingInformation().getRoute()));
+
+        req.setType(Message.MessageType.REQUEST);
+        req.setSender(getLocalIpAddress() + ":" + rpcPort);
+        req.setRoute(input.getRoutingInformation());
+        req.setPayload(input.getPayload());
+        try {
+          requestSocket.send(Message.serialize(req));
+          resp = parseMessage(requestSocket);
+          reply.setPayload(resp.getPayload());
+        } catch (IOException ex) {//| ClassNotFoundException ex) {
+          //Log and ignore
+          System.out.println("Error in RPC send. Input could not be serialized[" + input + "]");
+        }
+
+        return reply;
+      }
+    });
+  }
+
+  public void publish(final Message message) {
+    Runnable task = new Runnable() {
+      public void run() {
+        // Bind to publishing port
+        publisher = context.socket(ZMQ.PUB);
+        publisher.bind("tcp://*:" + pubPort);
+        System.out.println("Publisher started at port[" + pubPort + "]");
+        try {
+          Message outMessage =  new Message();
+          outMessage.setType(Message.MessageType.ANNOUNCE);
+          outMessage.setSender("tcp://" + getLocalIpAddress() + ":" + rpcPort);
+          outMessage.setRoute(message.getRoute());
+
+          System.out.println("Sending announcement[" + outMessage + "]");
+          publisher.sendMore(Message.serialize(Message.MessageType.ANNOUNCE));
+          publisher.send(Message.serialize(outMessage));
+
+        } catch (IOException ex) {
+          //Log and ignore
+          System.out.println("Error in publishing");
+          ex.printStackTrace();
+        }
+        System.out.println("Published message[" + message + "]");
+        publisher.close();
+      }
+    };
+    handlersPool.execute(task);
+  }
+
+  private String getLocalIpAddress() {
+    String hostAddress = null;
+    Enumeration e = null;
+    try {
+      e = NetworkInterface.getNetworkInterfaces();
+    } catch (SocketException e1) {
+      e1.printStackTrace();
+    }
+    while (e.hasMoreElements()) {
+
+      NetworkInterface n = (NetworkInterface) e.nextElement();
+      Enumeration ee = n.getInetAddresses();
+      while (ee.hasMoreElements()) {
+        InetAddress i = (InetAddress) ee.nextElement();
+        if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
+          hostAddress = i.getHostAddress();
+      }
+    }
+
+    return hostAddress;
+
+
+  }
+
+
+  private class RpcFacade implements RpcImplementation {
+
+
+    @Override
+    public Set<QName> getSupportedRpcs() {
+      return Collections.emptySet();
+    }
+
+    @Override
+    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+
+      RpcRequestImpl request = new RpcRequestImpl();
+      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+      routeId.setContext(null);
+      routeId.setRoute(null);
+      routeId.setType(rpc);
+
+      request.setRouteIdentifier(routeId);
+      request.setPayload(input);
+      // Create message
+
+      Future<org.opendaylight.controller.sal.connector.api.RpcRouter.RpcReply<Object>> ret = sendRpc(request);
+
+      return null;
+    }
+  }
+
+  private class RpcListener implements RpcRegistrationListener {
+
+    @Override
+    public void onRpcImplementationAdded(QName name) {
+
+      Message msg = new Message();
+      RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+      routeId.setType(name);
+      msg.setRoute(routeId);
+      publish(msg);
+    }
+
+    @Override
+    public void onRpcImplementationRemoved(QName name) {
+      // TODO Auto-generated method stub
+
+    }
+  }
+
+  public void setBrokerSession(ProviderSession session) {
+    this.brokerSession = session;
+
+  }
+
+}
index 7bd9a3a5baf9537bda0f6e38064c5d830caea980..04e0a32ffbe3e93946a31f2a27cdce23d0b800c2 100644 (file)
        <modules>
                <module>toaster</module>
                <module>toaster-consumer</module>
-               <module>toaster-it</module>
                <module>toaster-provider</module>
        </modules>
+
+    <profiles>
+      <profile>
+        <id>integrationtests</id>
+        <activation>
+          <activeByDefault>false</activeByDefault>
+        </activation>
+        <modules>
+          <module>toaster-it</module>
+        </modules>
+      </profile>
+    </profiles>
+
        <groupId>org.opendaylight.controller.samples</groupId>
 </project>
diff --git a/opendaylight/md-sal/test/pom.xml b/opendaylight/md-sal/test/pom.xml
new file mode 100644 (file)
index 0000000..f9e500e
--- /dev/null
@@ -0,0 +1,24 @@
+<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>
+               <artifactId>sal-parent</artifactId>
+               <version>1.0-SNAPSHOT</version>
+               <groupId>org.opendaylight.controller</groupId>
+       </parent>
+       <packaging>pom</packaging>
+       <groupId>org.opendaylight.controller.tests</groupId>
+       <artifactId>sal-test-parent</artifactId>
+    <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>
+
+       <modules>
+               <module>zeromq-test-consumer</module>
+        <module>zeromq-test-it</module>
+        <module>zeromq-test-provider</module>
+       </modules>
+       
+</project>
diff --git a/opendaylight/md-sal/test/zeromq-test-consumer/pom.xml b/opendaylight/md-sal/test/zeromq-test-consumer/pom.xml
new file mode 100644 (file)
index 0000000..7c6bc21
--- /dev/null
@@ -0,0 +1,85 @@
+<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>
+        <artifactId>sal-test-parent</artifactId>
+        <groupId>org.opendaylight.controller.tests</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>zeromq-test-consumer</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.sample.zeromq.consumer.ExampleConsumer</Bundle-Activator>
+                        <Import-Package>
+                            org.opendaylight.controller.sal.core.api,
+                            org.opendaylight.yangtools.yang.common;version="[0.5,1)",
+                            org.opendaylight.yangtools.yang.data.api,
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-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-core-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>containermanager</artifactId>
+            <version>0.5.1-SNAPSHOT</version>
+        </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.yangtools</groupId>
+            <artifactId>yang-data-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/test/zeromq-test-consumer/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java b/opendaylight/md-sal/test/zeromq-test-consumer/src/main/java/org/opendaylight/controller/sample/zeromq/consumer/ExampleConsumer.java
new file mode 100644 (file)
index 0000000..a56a7de
--- /dev/null
@@ -0,0 +1,51 @@
+package org.opendaylight.controller.sample.zeromq.consumer;
+
+import java.net.URI;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.sal.core.api.AbstractConsumer;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.BundleContext;
+
+public class ExampleConsumer extends AbstractConsumer {
+
+    private final URI namespace = URI.create("http://cisco.com/example");
+    private final QName QNAME = new QName(namespace,"heartbeat");
+    
+    ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
+    private ConsumerSession session;
+    
+    
+    @Override
+    public void onSessionInitiated(ConsumerSession session) {
+        this.session = session;
+        executor.scheduleAtFixedRate(new Runnable() {
+            
+            @Override
+            public void run() {
+                int count = 0;
+                try {
+                    Future<RpcResult<CompositeNode>> future = ExampleConsumer.this.session.rpc(QNAME, null);
+                    RpcResult<CompositeNode> result = future.get();
+                    System.out.println("Result received. Status is :" + result.isSuccessful());
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+                
+            }
+        }, 0, 10, TimeUnit.SECONDS);
+    }
+    
+    @Override
+    protected void stopImpl(BundleContext context) {
+        // TODO Auto-generated method stub
+        super.stopImpl(context);
+        executor.shutdown();
+    }
+}
diff --git a/opendaylight/md-sal/test/zeromq-test-it/pom.xml b/opendaylight/md-sal/test/zeromq-test-it/pom.xml
new file mode 100644 (file)
index 0000000..56945d1
--- /dev/null
@@ -0,0 +1,184 @@
+<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>
+        <artifactId>sal-test-parent</artifactId>
+        <groupId>org.opendaylight.controller.tests</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>zeromq-test-it</artifactId>
+    <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>
+
+    <properties>
+        <exam.version>3.0.0</exam.version>
+        <url.version>1.5.0</url.version>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.ops4j.pax.exam</groupId>
+                <artifactId>maven-paxexam-plugin</artifactId>
+                <version>1.2.4</version>
+                <executions>
+                    <execution>
+                        <id>generate-config</id>
+                        <goals>
+                            <goal>generate-depends-file</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <pluginManagement>
+            <plugins>
+                <!--This plugin's configuration is used to store Eclipse m2e settings 
+                    only. It has no influence on the Maven build itself. -->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>
+                                            org.ops4j.pax.exam
+                                        </groupId>
+                                        <artifactId>
+                                            maven-paxexam-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [1.2.4,)
+                                        </versionRange>
+                                        <goals>
+                                            <goal>
+                                                generate-depends-file
+                                            </goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>xtend-lib-osgi</artifactId>
+            <version>2.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.tests</groupId>
+            <artifactId>zeromq-test-provider</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.tests</groupId>
+            <artifactId>zeromq-test-consumer</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-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>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.controller</groupId>
+        <artifactId>sal-binding-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-core-api</artifactId>
+        <version>1.0-SNAPSHOT</version>
+      </dependency>
+
+
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>containermanager</artifactId>
+        <version>0.5.1-SNAPSHOT</version>
+      </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.yangtools</groupId>
+        <artifactId>yang-data-api</artifactId>
+      </dependency>
+
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-common-util</artifactId>
+        <version>1.0-SNAPSHOT</version>
+      </dependency>
+    </dependencies>
+</project>
diff --git a/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceConsumerController.java b/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceConsumerController.java
new file mode 100644 (file)
index 0000000..c17b143
--- /dev/null
@@ -0,0 +1,75 @@
+package org.opendaylight.controller.sample.zeromq.test.it;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.osgi.framework.BundleContext;
+
+import javax.inject.Inject;
+
+import static org.junit.Assert.assertTrue;
+import static org.ops4j.pax.exam.CoreOptions.*;
+
+@RunWith(PaxExam.class)
+public class ServiceConsumerController {
+
+    public static final String ODL = "org.opendaylight.controller";
+    public static final String YANG = "org.opendaylight.yangtools";
+    public static final String SAMPLE = "org.opendaylight.controller.samples";
+
+    @Test
+    public void properInitialized() throws Exception {
+
+        Thread.sleep(30000); // Waiting for services to get wired.
+        assertTrue(true);
+        //assertTrue(consumer.createToast(WhiteBread.class, 5));
+
+    }
+
+//    @Inject
+//    BindingAwareBroker broker;
+
+//    @Inject
+//    ToastConsumer consumer;
+
+    @Inject
+    BundleContext ctx;
+
+    @Configuration
+    public Option[] config() {
+        return options(systemProperty("osgi.console").value("2401"),
+                systemProperty("pub.port").value("5557"),
+                systemProperty("sub.port").value("5556"),
+                systemProperty("rpc.port").value("5555"),
+                systemProperty("pub.ip").value("localhost"),
+                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-binding-broker-impl").versionAsInProject().update(), //
+                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, "sal-core-api").versionAsInProject().update(), //
+                mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
+                mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
+                mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
+                mavenBundle(SAMPLE, "zeromq-test-consumer").versionAsInProject(), //
+                mavenBundle(ODL, "sal-zeromq-connector").versionAsInProject(), //
+                mavenBundle(YANG, "concepts").versionAsInProject(),
+                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
+                mavenBundle(YANG, "yang-common").versionAsInProject(), //
+                mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
+                mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
+                mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
+                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
+                mavenBundle("org.jeromq", "jeromq").versionAsInProject(),
+                junitBundles()
+                );
+    }
+
+}
diff --git a/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceProviderController.java b/opendaylight/md-sal/test/zeromq-test-it/src/test/java/org/opendaylight/controller/sample/zeromq/test/it/ServiceProviderController.java
new file mode 100644 (file)
index 0000000..2d28b0b
--- /dev/null
@@ -0,0 +1,86 @@
+package org.opendaylight.controller.sample.zeromq.test.it;
+
+import static org.junit.Assert.*;
+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;
+import static org.ops4j.pax.exam.CoreOptions.maven;
+
+import java.util.Collection;
+
+import javax.inject.Inject;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+@RunWith(PaxExam.class)
+public class ServiceProviderController {
+
+    public static final String ODL = "org.opendaylight.controller";
+    public static final String YANG = "org.opendaylight.yangtools";
+    public static final String SAMPLE = "org.opendaylight.controller.samples";
+
+    @Test
+    public void properInitialized() throws Exception {
+
+        Thread.sleep(30000); // Waiting for services to get wired.
+        assertTrue(true);
+        //assertTrue(consumer.createToast(WhiteBread.class, 5));
+
+    }
+
+//    @Inject
+//    BindingAwareBroker broker;
+
+//    @Inject
+//    ToastConsumer consumer;
+
+    @Inject
+    BundleContext ctx;
+
+    @Configuration
+    public Option[] config() {
+        return options(systemProperty("osgi.console").value("2401"),
+                systemProperty("pub.port").value("5556"),
+                systemProperty("sub.port").value("5557"),
+                systemProperty("rpc.port").value("5554"),
+                systemProperty("pub.ip").value("localhost"),
+                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-binding-broker-impl").versionAsInProject().update(), //
+                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, "sal-core-api").versionAsInProject().update(), //
+                mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
+                mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
+                mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
+                mavenBundle(SAMPLE, "zeromq-test-provider").versionAsInProject(), //
+                mavenBundle(ODL, "sal-zeromq-connector").versionAsInProject(), //
+                mavenBundle(YANG, "concepts").versionAsInProject(),
+                mavenBundle(YANG, "yang-binding").versionAsInProject(), //
+                mavenBundle(YANG, "yang-common").versionAsInProject(), //
+                mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
+                mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
+                mavenBundle(YANG+".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
+                mavenBundle("com.google.guava", "guava").versionAsInProject(), //
+                mavenBundle("org.jeromq", "jeromq").versionAsInProject(),
+                junitBundles()
+                );
+    }
+
+}
diff --git a/opendaylight/md-sal/test/zeromq-test-provider/pom.xml b/opendaylight/md-sal/test/zeromq-test-provider/pom.xml
new file mode 100644 (file)
index 0000000..10e15aa
--- /dev/null
@@ -0,0 +1,86 @@
+<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>
+        <artifactId>sal-test-parent</artifactId>
+        <groupId>org.opendaylight.controller.tests</groupId>
+        <version>1.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>zeromq-test-provider</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.sample.zeromq.provider.ExampleProvider</Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-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-core-api</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager</artifactId>
+      <version>0.5.1-SNAPSHOT</version>
+    </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.yangtools</groupId>
+      <artifactId>yang-data-api</artifactId>
+    </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-zeromq-connector</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency>
+
+  </dependencies>
+</project>
diff --git a/opendaylight/md-sal/test/zeromq-test-provider/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java b/opendaylight/md-sal/test/zeromq-test-provider/src/main/java/org/opendaylight/controller/sample/zeromq/provider/ExampleProvider.java
new file mode 100644 (file)
index 0000000..ec7d7a8
--- /dev/null
@@ -0,0 +1,67 @@
+package org.opendaylight.controller.sample.zeromq.provider;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.BundleContext;
+
+public class ExampleProvider extends AbstractProvider implements RpcImplementation  {
+
+    private final URI namespace = URI.create("http://cisco.com/example");
+    private final QName QNAME = new QName(namespace,"heartbeat");
+    private RpcRegistration reg;
+    
+    
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+      //Adding heartbeat 10 times just to make sure subscriber get it
+      for (int i=0;i<10;i++){
+        System.out.println("ExampleProvider: Adding " + QNAME + " " + i);
+        reg = session.addRpcImplementation(QNAME, this);
+        try {
+          Thread.sleep(1000);
+        } catch (InterruptedException e) {
+          e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+        }
+      }
+    }
+    
+    @Override
+    public Set<QName> getSupportedRpcs() {
+        return Collections.singleton(QNAME);
+    }
+    
+    @Override
+    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+        if(QNAME.equals(rpc)) {
+            RpcResult<CompositeNode> output = Rpcs.getRpcResult(true, null, Collections.<RpcError>emptySet());
+            return output;
+        }
+        RpcResult<CompositeNode> output = Rpcs.getRpcResult(false, null, Collections.<RpcError>emptySet());
+        return output;
+    }
+    
+    @Override
+    protected void stopImpl(BundleContext context) {
+     if(reg != null) {
+         try {
+            reg.close();
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+     }
+    }
+
+}
index 18c8ce5d1546d974f9b8fe11ac62298ba342217b..123c03e9a18fb4daff3aa8201df8e31f8e135111 100644 (file)
@@ -67,6 +67,8 @@ public class EditConfigTest {
         doNothing().when(provider).abortTestTransaction(any(ObjectName.class));
         doReturn(mockOn).when(provider).getOrCreateTransaction();
 
+        doNothing().when(provider).wipeTestTransaction(any(ObjectName.class));
+
         doReturn(configTransactionClient).when(configRegistry).getConfigTransactionClient(any(ObjectName.class));
         doReturn("mockConfigTransactionClient").when(configTransactionClient).toString();
 
index 8ec1c8c069201f648f09bcaa1adcf87e0d9567dc..8f6ec9c4c2b710cb95a9f7faaf92951c583d4b2a 100644 (file)
@@ -3,7 +3,7 @@
         <target>
             <candidate/>
         </target>
-        <default-operation>replace</default-operation>
+        <default-operation>merge</default-operation>
 
         <config>
         </config>
index 7f0bd4407812e9f3c6451958778c8ce23abea1ed..8f69f8dca066a949a306bd2e98b038bdeb392a5c 100644 (file)
         <module>netconf-impl</module>
         <module>config-netconf-connector</module>
         <module>netconf-util</module>
-        <module>netconf-it</module>
         <module>config-persister-impl</module>
         <module>netconf-mapping-api</module>
         <module>netconf-client</module>
     </modules>
 
+    <profiles>
+        <profile>
+           <id>integrationtests</id>
+           <activation>
+               <activeByDefault>false</activeByDefault>
+           </activation>
+            <modules>
+              <module>netconf-it</module>
+            </modules>
+        </profile>
+    </profiles>
+
     <properties>
         <osgi.version>5.0.0</osgi.version>
         <maven.bundle.version>2.3.7</maven.bundle.version>
index d7919394867b0ef67b43ca7c20498f3a21df6ae7..c6ea9421f9b9d928944ced8e7ceeb7de40a3de6c 100644 (file)
@@ -265,7 +265,6 @@ public class NeutronSubnet {
                 allocationPools = source.splitPool(gatewayIP);\r
             }\r
         } catch (Exception e) {\r
-            ;\r
         }\r
     }\r
 \r
index 5083cf57d759bb0a9f118f484e5b0dde36283604..30f27793dea433b8c07defe6335c709024eb8184 100644 (file)
@@ -52,7 +52,6 @@ public class Bandwidth extends Property {
     private Bandwidth() {
         super(BandwidthPropName);
         this.bandwidthValue = BWUNK;
-        ;
     }
 
     public Bandwidth(long bandwidth) {
index 577c0395308223843e614dfc3aac3dd757b4da72..189476a5d1bb1c1420c683bf4ea6a6c2a07b3d7b 100644 (file)
@@ -127,10 +127,20 @@ public class SubnetConfig implements Cloneable, Serializable {
         return new Status(StatusCode.SUCCESS);
     }
 
+    private Status validateName() {
+        if (name == null || name.trim().isEmpty()) {
+            return new Status(StatusCode.BADREQUEST, "Invalid name");
+        }
+        return new Status(StatusCode.SUCCESS);
+    }
+
     public Status validate() {
-        Status status = validateSubnetAddress();
+        Status status = validateName();
         if (status.isSuccess()) {
-            status = validatePorts(this.nodeConnectors);
+            status = validateSubnetAddress();
+            if (status.isSuccess()) {
+                status = validatePorts(this.nodeConnectors);
+            }
         }
         return status;
     }
diff --git a/pom.xml b/pom.xml
index 5899d563e8dd2d1d5a38e8bc7e0288dbcc39bf4c..b95cdfd62aaf03027969a0b14e0c30a515e3d8cf 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <module>opendaylight/forwarding/staticrouting</module>
     <module>opendaylight/clustering/services</module>
     <module>opendaylight/clustering/services_implementation</module>
-    <module>opendaylight/clustering/integrationtest</module>
     <module>opendaylight/clustering/stub</module>
     <module>opendaylight/clustering/test</module>
     <module>opendaylight/configuration/api</module>
     <module>opendaylight/configuration/implementation</module>
-    <module>opendaylight/configuration/integrationtest</module>
     <module>opendaylight/routing/dijkstra_implementation</module>
     <module>opendaylight/arphandler</module>
     <module>opendaylight/forwardingrulesmanager/api</module>
     <module>opendaylight/forwardingrulesmanager/implementation</module>
-    <module>opendaylight/forwardingrulesmanager/integrationtest</module>
     <module>opendaylight/hosttracker/api</module>
     <module>opendaylight/hosttracker/implementation</module>
-    <module>opendaylight/hosttracker/integrationtest</module>
     <module>opendaylight/hosttracker_new/api</module>
     <module>opendaylight/hosttracker_new/implementation</module>
     <module>opendaylight/containermanager/api</module>
     <module>opendaylight/containermanager/implementation</module>
-    <module>opendaylight/containermanager/it.implementation</module>
     <module>opendaylight/appauth</module>
     <module>opendaylight/switchmanager/api</module>
     <module>opendaylight/switchmanager/implementation</module>
-    <module>opendaylight/switchmanager/integrationtest</module>
     <module>opendaylight/statisticsmanager/api</module>
     <module>opendaylight/statisticsmanager/implementation</module>
-    <module>opendaylight/statisticsmanager/integrationtest</module>
     <module>opendaylight/topologymanager/implementation</module>
-    <module>opendaylight/topologymanager/integrationtest</module>
     <module>opendaylight/usermanager/api</module>
     <module>opendaylight/usermanager/implementation</module>
     <module>opendaylight/connectionmanager/api</module>
@@ -65,6 +57,7 @@
     <!-- <module>third-party/net.sf.jung2</module> -->
     <!-- <module>third-party/jersey-servlet</module> -->
     <!-- <module>third-party/org.apache.catalina.filters.CorsFilter</module> -->
+    <!-- <module>third-party/ganymed</module> -->
 
     <module>third-party/commons/thirdparty</module>
 
     <module>opendaylight/northbound/usermanager</module>
     <module>opendaylight/northbound/controllermanager</module>
 
-    <!-- Northbound integration tests -->
-    <module>opendaylight/northbound/integrationtest</module>
     <!-- Debug and logging -->
     <module>opendaylight/logging/bridge</module>
 
     <module>opendaylight/samples/loadbalancer</module>
     <module>opendaylight/samples/northbound/loadbalancer</module>
 
-    <module>opendaylight/distribution/sanitytest/</module>
-
     <!-- Parents -->
     <module>opendaylight/commons/concepts</module>
     <module>opendaylight/commons/httpclient</module>
-    <module>opendaylight/commons/integrationtest</module>
     <module>opendaylight/commons/checkstyle</module>
     <module>opendaylight/commons/opendaylight</module>
     <module>opendaylight/commons/parent</module>
   </modules>
+
+    <profiles>
+        <profile>
+           <id>integrationtests</id>
+           <activation>
+               <activeByDefault>false</activeByDefault>
+           </activation>
+            <modules>
+                <module>opendaylight/clustering/integrationtest</module>
+                <module>opendaylight/configuration/integrationtest</module>
+                <module>opendaylight/forwardingrulesmanager/integrationtest</module>
+                <module>opendaylight/hosttracker/integrationtest</module>
+                <module>opendaylight/switchmanager/integrationtest</module>
+                <module>opendaylight/topologymanager/integrationtest</module>
+                <!-- Northbound integration tests -->
+                <module>opendaylight/northbound/integrationtest</module>
+                <module>opendaylight/statisticsmanager/integrationtest</module>
+                <module>opendaylight/commons/integrationtest</module>
+                <module>opendaylight/containermanager/it.implementation</module>
+                <module>opendaylight/distribution/sanitytest/</module>
+            </modules>
+        </profile>
+    </profiles>
 </project>
index b69704ff20477e4b41456fb32e1ab3e2d4eeca09..70f3b27873db792522545ff6ccfad09967860058 100644 (file)
@@ -25,6 +25,7 @@
     <compiler.version>2.3.2</compiler.version>
     <surefire.version>2.13</surefire.version>
     <releaseplugin.version>2.3.2</releaseplugin.version>
+    <enforcer.version>1.3.1</enforcer.version>
   </properties>
 
   <pluginRepositories>
diff --git a/third-party/ganymed/pom.xml b/third-party/ganymed/pom.xml
new file mode 100644 (file)
index 0000000..98a6596
--- /dev/null
@@ -0,0 +1,79 @@
+<?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.thirdparty</artifactId>
+        <version>1.1.1-SNAPSHOT</version>
+        <relativePath>../commons/thirdparty</relativePath>
+    </parent>
+
+    <groupId>org.opendaylight.controller.thirdparty</groupId>
+    <artifactId>ganymed</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <ganymed.version>build209</ganymed.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>4.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.ethz.ganymed</groupId>
+            <artifactId>ganymed-ssh2</artifactId>
+            <version>261</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Export-Package>ch.ethz.ssh2</Export-Package>
+                        <Embed-Dependency>ganymed-ssh2;scope=compile</Embed-Dependency>
+                        <Embed-Transitive>true</Embed-Transitive>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <version>${enforcer.version}</version>
+                <executions>
+                    <execution>
+                        <id>enforce-no-snapshots</id>
+                        <goals>
+                            <goal>enforce</goal>
+                        </goals>
+                        <configuration>
+                            <rules>
+                                <bannedDependencies>
+                                    <excludes>
+                                        <exclude>ch.ethz.ganymed:ganymed-ssh2:*</exclude>
+                                    </excludes>
+                                    <includes>
+                                        <include>ch.ethz.ganymed:ganymed-ssh2:[261]</include>
+                                    </includes>
+                                </bannedDependencies>
+                            </rules>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
+
+
diff --git a/third-party/ganymed/src/main/java/ch/ethz/ssh2/Connection.java b/third-party/ganymed/src/main/java/ch/ethz/ssh2/Connection.java
new file mode 100644 (file)
index 0000000..aa13c40
--- /dev/null
@@ -0,0 +1,1424 @@
+/*
+ * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+
+package ch.ethz.ssh2;
+
+import java.io.CharArrayWriter;
+import java.io.File;
+import java.net.Socket;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketTimeoutException;
+import java.security.SecureRandom;
+import java.util.List;
+import java.util.Vector;
+
+import ch.ethz.ssh2.auth.AuthenticationManager;
+import ch.ethz.ssh2.channel.ChannelManager;
+import ch.ethz.ssh2.crypto.CryptoWishList;
+import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory;
+import ch.ethz.ssh2.crypto.digest.MAC;
+import ch.ethz.ssh2.packets.PacketIgnore;
+import ch.ethz.ssh2.transport.KexManager;
+import ch.ethz.ssh2.transport.TransportManager;
+import ch.ethz.ssh2.util.TimeoutService;
+import ch.ethz.ssh2.util.TimeoutService.TimeoutToken;
+
+/**
+ * A <code>Connection</code> is used to establish an encrypted TCP/IP
+ * connection to a SSH-2 server.
+ * <p>
+ * Typically, one
+ * <ol>
+ * <li>creates a {@link #Connection(String) Connection} object.</li>
+ * <li>calls the {@link #connect() connect()} method.</li>
+ * <li>calls some of the authentication methods (e.g., {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}).</li>
+ * <li>calls one or several times the {@link #openSession() openSession()} method.</li>
+ * <li>finally, one must close the connection and release resources with the {@link #close() close()} method.</li>
+ * </ol>
+ *
+ * @author Christian Plattner
+ * @version $Id: Connection.java 69 2013-08-09 06:39:56Z dkocher@sudo.ch $
+ */
+
+public class Connection
+{
+    /**
+     * The identifier presented to the SSH-2 server. This is the same
+     * as the "softwareversion" defined in RFC 4253.
+     * <p/>
+     * <b>NOTE: As per the RFC, the "softwareversion" string MUST consist of printable
+     * US-ASCII characters, with the exception of whitespace characters and the minus sign (-).</b>
+     */
+    private String softwareversion = String.format("Ganymed_%s", Version.getSpecification());
+
+       /* Will be used to generate all random data needed for the current connection.
+        * Note: SecureRandom.nextBytes() is thread safe.
+        */
+
+    private SecureRandom generator;
+
+    private Socket precreatedSocket;
+
+    public Connection(Socket socket) {
+        this.precreatedSocket = socket;
+        this.hostname = socket.getInetAddress().getHostName();
+        this.port = socket.getPort();
+    }
+
+    /**
+     * Unless you know what you are doing, you will never need this.
+     *
+     * @return The list of supported cipher algorithms by this implementation.
+     */
+    public static synchronized String[] getAvailableCiphers()
+    {
+        return BlockCipherFactory.getDefaultCipherList();
+    }
+
+    /**
+     * Unless you know what you are doing, you will never need this.
+     *
+     * @return The list of supported MAC algorthims by this implementation.
+     */
+    public static synchronized String[] getAvailableMACs()
+    {
+        return MAC.getMacList();
+    }
+
+    /**
+     * Unless you know what you are doing, you will never need this.
+     *
+     * @return The list of supported server host key algorthims by this implementation.
+     */
+    public static synchronized String[] getAvailableServerHostKeyAlgorithms()
+    {
+        return KexManager.getDefaultServerHostkeyAlgorithmList();
+    }
+
+    private AuthenticationManager am;
+
+    private boolean authenticated = false;
+    private ChannelManager cm;
+
+    private CryptoWishList cryptoWishList = new CryptoWishList();
+
+    private DHGexParameters dhgexpara = new DHGexParameters();
+
+    private final String hostname;
+
+    private final int port;
+
+    private TransportManager tm;
+
+    private boolean tcpNoDelay = false;
+
+    private ProxyData proxyData = null;
+
+    private List<ConnectionMonitor> connectionMonitors = new Vector<ConnectionMonitor>();
+
+    /**
+     * Prepares a fresh <code>Connection</code> object which can then be used
+     * to establish a connection to the specified SSH-2 server.
+     * <p>
+     * Same as {@link #Connection(String, int) Connection(hostname, 22)}.
+     *
+     * @param hostname the hostname of the SSH-2 server.
+     */
+    public Connection(String hostname)
+    {
+        this(hostname, 22);
+    }
+
+    /**
+     * Prepares a fresh <code>Connection</code> object which can then be used
+     * to establish a connection to the specified SSH-2 server.
+     *
+     * @param hostname
+     *            the host where we later want to connect to.
+     * @param port
+     *            port on the server, normally 22.
+     */
+    public Connection(String hostname, int port)
+    {
+        this.hostname = hostname;
+        this.port = port;
+    }
+
+    /**
+     * Prepares a fresh <code>Connection</code> object which can then be used
+     * to establish a connection to the specified SSH-2 server.
+     *
+     * @param hostname
+     *            the host where we later want to connect to.
+     * @param port
+     *            port on the server, normally 22.
+     * @param softwareversion
+     *                         Allows you to set a custom "softwareversion" string as defined in RFC 4253.
+     *                         <b>NOTE: As per the RFC, the "softwareversion" string MUST consist of printable
+     *          US-ASCII characters, with the exception of whitespace characters and the minus sign (-).</b>
+     */
+    public Connection(String hostname, int port, String softwareversion)
+    {
+        this.hostname = hostname;
+        this.port = port;
+        this.softwareversion = softwareversion;
+    }
+
+    /**
+     * After a successful connect, one has to authenticate oneself. This method
+     * is based on DSA (it uses DSA to sign a challenge sent by the server).
+     * <p>
+     * If the authentication phase is complete, <code>true</code> will be
+     * returned. If the server does not accept the request (or if further
+     * authentication steps are needed), <code>false</code> is returned and
+     * one can retry either by using this or any other authentication method
+     * (use the <code>getRemainingAuthMethods</code> method to get a list of
+     * the remaining possible methods).
+     *
+     * @param user
+     *            A <code>String</code> holding the username.
+     * @param pem
+     *            A <code>String</code> containing the DSA private key of the
+     *            user in OpenSSH key format (PEM, you can't miss the
+     *            "-----BEGIN DSA PRIVATE KEY-----" tag). The string may contain
+     *            linefeeds.
+     * @param password
+     *            If the PEM string is 3DES encrypted ("DES-EDE3-CBC"), then you
+     *            must specify the password. Otherwise, this argument will be
+     *            ignored and can be set to <code>null</code>.
+     *
+     * @return whether the connection is now authenticated.
+     * @throws IOException
+     *
+     * @deprecated You should use one of the {@link #authenticateWithPublicKey(String, File, String) authenticateWithPublicKey()}
+     *                       methods, this method is just a wrapper for it and will
+     *            disappear in future builds.
+     *
+     */
+    public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("Connection is not established!");
+
+        if (authenticated)
+            throw new IllegalStateException("Connection is already authenticated!");
+
+        if (am == null)
+            am = new AuthenticationManager(tm);
+
+        if (cm == null)
+            cm = new ChannelManager(tm);
+
+        if (user == null)
+            throw new IllegalArgumentException("user argument is null");
+
+        if (pem == null)
+            throw new IllegalArgumentException("pem argument is null");
+
+        authenticated = am.authenticatePublicKey(user, pem.toCharArray(), password, getOrCreateSecureRND());
+
+        return authenticated;
+    }
+
+    /**
+     * A wrapper that calls {@link #authenticateWithKeyboardInteractive(String, String[], InteractiveCallback)
+     * authenticateWithKeyboardInteractivewith} a <code>null</code> submethod list.
+     *
+     * @param user
+     *            A <code>String</code> holding the username.
+     * @param cb
+     *            An <code>InteractiveCallback</code> which will be used to
+     *            determine the responses to the questions asked by the server.
+     * @return whether the connection is now authenticated.
+     * @throws IOException
+     */
+    public synchronized boolean authenticateWithKeyboardInteractive(String user, InteractiveCallback cb)
+            throws IOException
+    {
+        return authenticateWithKeyboardInteractive(user, null, cb);
+    }
+
+    /**
+     * After a successful connect, one has to authenticate oneself. This method
+     * is based on "keyboard-interactive", specified in
+     * draft-ietf-secsh-auth-kbdinteract-XX. Basically, you have to define a
+     * callback object which will be feeded with challenges generated by the
+     * server. Answers are then sent back to the server. It is possible that the
+     * callback will be called several times during the invocation of this
+     * method (e.g., if the server replies to the callback's answer(s) with
+     * another challenge...)
+     * <p>
+     * If the authentication phase is complete, <code>true</code> will be
+     * returned. If the server does not accept the request (or if further
+     * authentication steps are needed), <code>false</code> is returned and
+     * one can retry either by using this or any other authentication method
+     * (use the <code>getRemainingAuthMethods</code> method to get a list of
+     * the remaining possible methods).
+     * <p>
+     * Note: some SSH servers advertise "keyboard-interactive", however, any
+     * interactive request will be denied (without having sent any challenge to
+     * the client).
+     *
+     * @param user
+     *            A <code>String</code> holding the username.
+     * @param submethods
+     *            An array of submethod names, see
+     *            draft-ietf-secsh-auth-kbdinteract-XX. May be <code>null</code>
+     *            to indicate an empty list.
+     * @param cb
+     *            An <code>InteractiveCallback</code> which will be used to
+     *            determine the responses to the questions asked by the server.
+     *
+     * @return whether the connection is now authenticated.
+     * @throws IOException
+     */
+    public synchronized boolean authenticateWithKeyboardInteractive(String user, String[] submethods,
+                                                                    InteractiveCallback cb) throws IOException
+    {
+        if (cb == null)
+            throw new IllegalArgumentException("Callback may not ne NULL!");
+
+        if (tm == null)
+            throw new IllegalStateException("Connection is not established!");
+
+        if (authenticated)
+            throw new IllegalStateException("Connection is already authenticated!");
+
+        if (am == null)
+            am = new AuthenticationManager(tm);
+
+        if (cm == null)
+            cm = new ChannelManager(tm);
+
+        if (user == null)
+            throw new IllegalArgumentException("user argument is null");
+
+        authenticated = am.authenticateInteractive(user, submethods, cb);
+
+        return authenticated;
+    }
+
+    /**
+     * After a successful connect, one has to authenticate oneself. This method
+     * sends username and password to the server.
+     * <p>
+     * If the authentication phase is complete, <code>true</code> will be
+     * returned. If the server does not accept the request (or if further
+     * authentication steps are needed), <code>false</code> is returned and
+     * one can retry either by using this or any other authentication method
+     * (use the <code>getRemainingAuthMethods</code> method to get a list of
+     * the remaining possible methods).
+     * <p>
+     * Note: if this method fails, then please double-check that it is actually
+     * offered by the server (use {@link #getRemainingAuthMethods(String) getRemainingAuthMethods()}.
+     * <p>
+     * Often, password authentication is disabled, but users are not aware of it.
+     * Many servers only offer "publickey" and "keyboard-interactive". However,
+     * even though "keyboard-interactive" *feels* like password authentication
+     * (e.g., when using the putty or openssh clients) it is *not* the same mechanism.
+     *
+     * @param user
+     * @param password
+     * @return if the connection is now authenticated.
+     * @throws IOException
+     */
+    public synchronized boolean authenticateWithPassword(String user, String password) throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("Connection is not established!");
+
+        if (authenticated)
+            throw new IllegalStateException("Connection is already authenticated!");
+
+        if (am == null)
+            am = new AuthenticationManager(tm);
+
+        if (cm == null)
+            cm = new ChannelManager(tm);
+
+        if (user == null)
+            throw new IllegalArgumentException("user argument is null");
+
+        if (password == null)
+            throw new IllegalArgumentException("password argument is null");
+
+        authenticated = am.authenticatePassword(user, password);
+
+        return authenticated;
+    }
+
+    /**
+     * After a successful connect, one has to authenticate oneself.
+     * This method can be used to explicitly use the special "none"
+     * authentication method (where only a username has to be specified).
+     * <p>
+     * Note 1: The "none" method may always be tried by clients, however as by
+     * the specs, the server will not explicitly announce it. In other words,
+     * the "none" token will never show up in the list returned by
+     * {@link #getRemainingAuthMethods(String)}.
+     * <p>
+     * Note 2: no matter which one of the authenticateWithXXX() methods
+     * you call, the library will always issue exactly one initial "none"
+     * authentication request to retrieve the initially allowed list of
+     * authentication methods by the server. Please read RFC 4252 for the
+     * details.
+     * <p>
+     * If the authentication phase is complete, <code>true</code> will be
+     * returned. If further authentication steps are needed, <code>false</code>
+     * is returned and one can retry by any other authentication method
+     * (use the <code>getRemainingAuthMethods</code> method to get a list of
+     * the remaining possible methods).
+     *
+     * @param user
+     * @return if the connection is now authenticated.
+     * @throws IOException
+     */
+    public synchronized boolean authenticateWithNone(String user) throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("Connection is not established!");
+
+        if (authenticated)
+            throw new IllegalStateException("Connection is already authenticated!");
+
+        if (am == null)
+            am = new AuthenticationManager(tm);
+
+        if (cm == null)
+            cm = new ChannelManager(tm);
+
+        if (user == null)
+            throw new IllegalArgumentException("user argument is null");
+
+               /* Trigger the sending of the PacketUserauthRequestNone packet */
+               /* (if not already done)                                       */
+
+        authenticated = am.authenticateNone(user);
+
+        return authenticated;
+    }
+
+    /**
+     * After a successful connect, one has to authenticate oneself.
+     * The authentication method "publickey" works by signing a challenge
+     * sent by the server. The signature is either DSA or RSA based - it
+     * just depends on the type of private key you specify, either a DSA
+     * or RSA private key in PEM format. And yes, this is may seem to be a
+     * little confusing, the method is called "publickey" in the SSH-2 protocol
+     * specification, however since we need to generate a signature, you
+     * actually have to supply a private key =).
+     * <p>
+     * The private key contained in the PEM file may also be encrypted ("Proc-Type: 4,ENCRYPTED").
+     * The library supports DES-CBC and DES-EDE3-CBC encryption, as well
+     * as the more exotic PEM encrpytions AES-128-CBC, AES-192-CBC and AES-256-CBC.
+     * <p>
+     * If the authentication phase is complete, <code>true</code> will be
+     * returned. If the server does not accept the request (or if further
+     * authentication steps are needed), <code>false</code> is returned and
+     * one can retry either by using this or any other authentication method
+     * (use the <code>getRemainingAuthMethods</code> method to get a list of
+     * the remaining possible methods).
+     * <p>
+     * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..."
+     * it is not in the expected format. You have to convert it to the OpenSSH
+     * key format by using the "puttygen" tool (can be downloaded from the Putty
+     * website). Simply load your key and then use the "Conversions/Export OpenSSH key"
+     * functionality to get a proper PEM file.
+     *
+     * @param user
+     *            A <code>String</code> holding the username.
+     * @param pemPrivateKey
+     *            A <code>char[]</code> containing a DSA or RSA private key of the
+     *            user in OpenSSH key format (PEM, you can't miss the
+     *            "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----"
+     *            tag). The char array may contain linebreaks/linefeeds.
+     * @param password
+     *            If the PEM structure is encrypted ("Proc-Type: 4,ENCRYPTED") then
+     *            you must specify a password. Otherwise, this argument will be ignored
+     *            and can be set to <code>null</code>.
+     *
+     * @return whether the connection is now authenticated.
+     * @throws IOException
+     */
+    public synchronized boolean authenticateWithPublicKey(String user, char[] pemPrivateKey, String password)
+            throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("Connection is not established!");
+
+        if (authenticated)
+            throw new IllegalStateException("Connection is already authenticated!");
+
+        if (am == null)
+            am = new AuthenticationManager(tm);
+
+        if (cm == null)
+            cm = new ChannelManager(tm);
+
+        if (user == null)
+            throw new IllegalArgumentException("user argument is null");
+
+        if (pemPrivateKey == null)
+            throw new IllegalArgumentException("pemPrivateKey argument is null");
+
+        authenticated = am.authenticatePublicKey(user, pemPrivateKey, password, getOrCreateSecureRND());
+
+        return authenticated;
+    }
+
+    /**
+     * A convenience wrapper function which reads in a private key (PEM format, either DSA or RSA)
+     * and then calls <code>authenticateWithPublicKey(String, char[], String)</code>.
+     * <p>
+     * NOTE PUTTY USERS: Event though your key file may start with "-----BEGIN..."
+     * it is not in the expected format. You have to convert it to the OpenSSH
+     * key format by using the "puttygen" tool (can be downloaded from the Putty
+     * website). Simply load your key and then use the "Conversions/Export OpenSSH key"
+     * functionality to get a proper PEM file.
+     *
+     * @param user
+     *            A <code>String</code> holding the username.
+     * @param pemFile
+     *            A <code>File</code> object pointing to a file containing a DSA or RSA
+     *            private key of the user in OpenSSH key format (PEM, you can't miss the
+     *            "-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----"
+     *            tag).
+     * @param password
+     *            If the PEM file is encrypted then you must specify the password.
+     *            Otherwise, this argument will be ignored and can be set to <code>null</code>.
+     *
+     * @return whether the connection is now authenticated.
+     * @throws IOException
+     */
+    public synchronized boolean authenticateWithPublicKey(String user, File pemFile, String password)
+            throws IOException
+    {
+        if (pemFile == null)
+            throw new IllegalArgumentException("pemFile argument is null");
+
+        char[] buff = new char[256];
+
+        CharArrayWriter cw = new CharArrayWriter();
+
+        FileReader fr = new FileReader(pemFile);
+
+        while (true)
+        {
+            int len = fr.read(buff);
+            if (len < 0)
+                break;
+            cw.write(buff, 0, len);
+        }
+
+        fr.close();
+
+        return authenticateWithPublicKey(user, cw.toCharArray(), password);
+    }
+
+    /**
+     * Add a {@link ConnectionMonitor} to this connection. Can be invoked at any time,
+     * but it is best to add connection monitors before invoking
+     * <code>connect()</code> to avoid glitches (e.g., you add a connection monitor after
+     * a successful connect(), but the connection has died in the mean time. Then,
+     * your connection monitor won't be notified.)
+     * <p>
+     * You can add as many monitors as you like. If a monitor has already been added, then
+     * this method does nothing.
+     *
+     * @see ConnectionMonitor
+     *
+     * @param cmon An object implementing the {@link ConnectionMonitor} interface.
+     */
+    public synchronized void addConnectionMonitor(ConnectionMonitor cmon)
+    {
+        if (cmon == null)
+            throw new IllegalArgumentException("cmon argument is null");
+
+        if (!connectionMonitors.contains(cmon))
+        {
+            connectionMonitors.add(cmon);
+
+            if (tm != null)
+                tm.setConnectionMonitors(connectionMonitors);
+        }
+    }
+
+    /**
+     * Remove a {@link ConnectionMonitor} from this connection.
+     *
+     * @param cmon
+     * @return whether the monitor could be removed
+     */
+    public synchronized boolean removeConnectionMonitor(ConnectionMonitor cmon)
+    {
+        if (cmon == null)
+            throw new IllegalArgumentException("cmon argument is null");
+
+        boolean existed = connectionMonitors.remove(cmon);
+
+        if (tm != null)
+            tm.setConnectionMonitors(connectionMonitors);
+
+        return existed;
+    }
+
+    /**
+     * Close the connection to the SSH-2 server. All assigned sessions will be
+     * closed, too. Can be called at any time. Don't forget to call this once
+     * you don't need a connection anymore - otherwise the receiver thread may
+     * run forever.
+     */
+    public synchronized void close()
+    {
+        Throwable t = new Throwable("Closed due to user request.");
+        close(t, false);
+    }
+
+    public synchronized void close(Throwable t, boolean hard)
+    {
+        if (cm != null)
+            cm.closeAllChannels();
+
+        if (tm != null)
+        {
+            tm.close(t, hard == false);
+            tm = null;
+        }
+        am = null;
+        cm = null;
+        authenticated = false;
+    }
+
+    /**
+     * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(null, 0, 0)}.
+     *
+     * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method.
+     * @throws IOException
+     */
+    public synchronized ConnectionInfo connect() throws IOException
+    {
+        return connect(null, 0, 0);
+    }
+
+    /**
+     * Same as {@link #connect(ServerHostKeyVerifier, int, int) connect(verifier, 0, 0)}.
+     *
+     * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method.
+     * @throws IOException
+     */
+    public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier) throws IOException
+    {
+        return connect(verifier, 0, 0);
+    }
+
+    /**
+     * Connect to the SSH-2 server and, as soon as the server has presented its
+     * host key, use the {@link ServerHostKeyVerifier#verifyServerHostKey(String,
+     * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()}
+     * method of the <code>verifier</code> to ask for permission to proceed.
+     * If <code>verifier</code> is <code>null</code>, then any host key will be
+     * accepted - this is NOT recommended, since it makes man-in-the-middle attackes
+     * VERY easy (somebody could put a proxy SSH server between you and the real server).
+     * <p>
+     * Note: The verifier will be called before doing any crypto calculations
+     * (i.e., diffie-hellman). Therefore, if you don't like the presented host key then
+     * no CPU cycles are wasted (and the evil server has less information about us).
+     * <p>
+     * However, it is still possible that the server presented a fake host key: the server
+     * cheated (typically a sign for a man-in-the-middle attack) and is not able to generate
+     * a signature that matches its host key. Don't worry, the library will detect such
+     * a scenario later when checking the signature (the signature cannot be checked before
+     * having completed the diffie-hellman exchange).
+     * <p>
+     * Note 2: The  {@link ServerHostKeyVerifier#verifyServerHostKey(String,
+     * int, String, byte[]) ServerHostKeyVerifier.verifyServerHostKey()} method
+     * will *NOT* be called from the current thread, the call is being made from a
+     * background thread (there is a background dispatcher thread for every
+     * established connection).
+     * <p>
+     * Note 3: This method will block as long as the key exchange of the underlying connection
+     * has not been completed (and you have not specified any timeouts).
+     * <p>
+     * Note 4: If you want to re-use a connection object that was successfully connected,
+     * then you must call the {@link #close()} method before invoking <code>connect()</code> again.
+     *
+     * @param verifier
+     *            An object that implements the
+     *            {@link ServerHostKeyVerifier} interface. Pass <code>null</code>
+     *            to accept any server host key - NOT recommended.
+     *
+     * @param connectTimeout
+     *            Connect the underlying TCP socket to the server with the given timeout
+     *            value (non-negative, in milliseconds). Zero means no timeout. If a proxy is being
+     *            used (see {@link #setProxyData(ProxyData)}), then this timeout is used for the
+     *            connection establishment to the proxy.
+     *
+     * @param kexTimeout
+     *            Timeout for complete connection establishment (non-negative,
+     *            in milliseconds). Zero means no timeout. The timeout counts from the
+     *            moment you invoke the connect() method and is cancelled as soon as the
+     *            first key-exchange round has finished. It is possible that
+     *            the timeout event will be fired during the invocation of the
+     *            <code>verifier</code> callback, but it will only have an effect after
+     *            the <code>verifier</code> returns.
+     *
+     * @return A {@link ConnectionInfo} object containing the details of
+     *            the established connection.
+     *
+     * @throws IOException
+     *            If any problem occurs, e.g., the server's host key is not
+     *            accepted by the <code>verifier</code> or there is problem during
+     *            the initial crypto setup (e.g., the signature sent by the server is wrong).
+     *            <p>
+     *            In case of a timeout (either connectTimeout or kexTimeout)
+     *            a SocketTimeoutException is thrown.
+     *            <p>
+     *            An exception may also be thrown if the connection was already successfully
+     *            connected (no matter if the connection broke in the mean time) and you invoke
+     *            <code>connect()</code> again without having called {@link #close()} first.
+     *            <p>
+     *            If a HTTP proxy is being used and the proxy refuses the connection,
+     *            then a {@link HTTPProxyException} may be thrown, which
+     *            contains the details returned by the proxy. If the proxy is buggy and does
+     *            not return a proper HTTP response, then a normal IOException is thrown instead.
+     */
+    public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout)
+            throws IOException
+    {
+        final class TimeoutState
+        {
+            boolean isCancelled = false;
+            boolean timeoutSocketClosed = false;
+        }
+
+        if (tm != null)
+            throw new IOException("Connection to " + hostname + " is already in connected state!");
+
+        if (connectTimeout < 0)
+            throw new IllegalArgumentException("connectTimeout must be non-negative!");
+
+        if (kexTimeout < 0)
+            throw new IllegalArgumentException("kexTimeout must be non-negative!");
+
+        final TimeoutState state = new TimeoutState();
+
+        tm = new TransportManager();
+        tm.setSoTimeout(connectTimeout);
+        tm.setConnectionMonitors(connectionMonitors);
+
+               /* Make sure that the runnable below will observe the new value of "tm"
+                * and "state" (the runnable will be executed in a different thread, which
+                * may be already running, that is why we need a memory barrier here).
+                * See also the comment in Channel.java if you
+                * are interested in the details.
+                * 
+                * OKOK, this is paranoid since adding the runnable to the todo list
+                * of the TimeoutService will ensure that all writes have been flushed
+                * before the Runnable reads anything
+                * (there is a synchronized block in TimeoutService.addTimeoutHandler).
+                */
+
+        synchronized (tm)
+        {
+                       /* We could actually synchronize on anything. */
+        }
+
+        try
+        {
+            TimeoutToken token = null;
+
+            if (kexTimeout > 0)
+            {
+                final Runnable timeoutHandler = new Runnable()
+                {
+                    public void run()
+                    {
+                        synchronized (state)
+                        {
+                            if (state.isCancelled)
+                                return;
+                            state.timeoutSocketClosed = true;
+                            tm.close(new SocketTimeoutException("The connect timeout expired"), false);
+                        }
+                    }
+                };
+
+                long timeoutHorizont = System.currentTimeMillis() + kexTimeout;
+
+                token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler);
+            }
+
+            try
+            {
+
+                if (precreatedSocket != null) {
+                    tm.clientInit(precreatedSocket, softwareversion, cryptoWishList, verifier, dhgexpara,
+                            getOrCreateSecureRND());
+                } else {
+                    tm.clientInit(hostname, port, softwareversion, cryptoWishList, verifier, dhgexpara, connectTimeout,
+                            getOrCreateSecureRND(), proxyData);
+                }
+            }
+            catch (SocketTimeoutException se)
+            {
+                throw (SocketTimeoutException) new SocketTimeoutException(
+                        "The connect() operation on the socket timed out.").initCause(se);
+            }
+
+            tm.setTcpNoDelay(tcpNoDelay);
+
+                       /* Wait until first KEX has finished */
+
+            ConnectionInfo ci = tm.getConnectionInfo(1);
+
+                       /* Now try to cancel the timeout, if needed */
+
+            if (token != null)
+            {
+                TimeoutService.cancelTimeoutHandler(token);
+
+                               /* Were we too late? */
+
+                synchronized (state)
+                {
+                    if (state.timeoutSocketClosed)
+                        throw new IOException("This exception will be replaced by the one below =)");
+                                       /* Just in case the "cancelTimeoutHandler" invocation came just a little bit
+                                        * too late but the handler did not enter the semaphore yet - we can
+                                        * still stop it.
+                                        */
+                    state.isCancelled = true;
+                }
+            }
+
+            return ci;
+        }
+        catch (SocketTimeoutException ste)
+        {
+            throw ste;
+        }
+        catch (IOException e1)
+        {
+                       /* This will also invoke any registered connection monitors */
+            close(new Throwable("There was a problem during connect."), false);
+
+            synchronized (state)
+            {
+                               /* Show a clean exception, not something like "the socket is closed!?!" */
+                if (state.timeoutSocketClosed)
+                    throw new SocketTimeoutException("The kexTimeout (" + kexTimeout + " ms) expired.");
+            }
+
+                       /* Do not wrap a HTTPProxyException */
+            if (e1 instanceof HTTPProxyException)
+                throw e1;
+
+            throw (IOException) new IOException("There was a problem while connecting to " + hostname + ":" + port)
+                    .initCause(e1);
+        }
+    }
+
+    /**
+     * Creates a new {@link LocalPortForwarder}.
+     * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local
+     * port via the secure tunnel to another host (which may or may not be
+     * identical to the remote SSH-2 server).
+     * <p>
+     * This method must only be called after one has passed successfully the authentication step.
+     * There is no limit on the number of concurrent forwardings.
+     *
+     * @param local_port the local port the LocalPortForwarder shall bind to.
+     * @param host_to_connect target address (IP or hostname)
+     * @param port_to_connect target port
+     * @return A {@link LocalPortForwarder} object.
+     * @throws IOException
+     */
+    public synchronized LocalPortForwarder createLocalPortForwarder(int local_port, String host_to_connect,
+                                                                    int port_to_connect) throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("Cannot forward ports, you need to establish a connection first.");
+
+        if (!authenticated)
+            throw new IllegalStateException("Cannot forward ports, connection is not authenticated.");
+
+        return new LocalPortForwarder(cm, local_port, host_to_connect, port_to_connect);
+    }
+
+    /**
+     * Creates a new {@link LocalPortForwarder}.
+     * A <code>LocalPortForwarder</code> forwards TCP/IP connections that arrive at a local
+     * port via the secure tunnel to another host (which may or may not be
+     * identical to the remote SSH-2 server).
+     * <p>
+     * This method must only be called after one has passed successfully the authentication step.
+     * There is no limit on the number of concurrent forwardings.
+     *
+     * @param addr specifies the InetSocketAddress where the local socket shall be bound to.
+     * @param host_to_connect target address (IP or hostname)
+     * @param port_to_connect target port
+     * @return A {@link LocalPortForwarder} object.
+     * @throws IOException
+     */
+    public synchronized LocalPortForwarder createLocalPortForwarder(InetSocketAddress addr, String host_to_connect,
+                                                                    int port_to_connect) throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("Cannot forward ports, you need to establish a connection first.");
+
+        if (!authenticated)
+            throw new IllegalStateException("Cannot forward ports, connection is not authenticated.");
+
+        return new LocalPortForwarder(cm, addr, host_to_connect, port_to_connect);
+    }
+
+    /**
+     * Creates a new {@link LocalStreamForwarder}.
+     * A <code>LocalStreamForwarder</code> manages an Input/Outputstream pair
+     * that is being forwarded via the secure tunnel into a TCP/IP connection to another host
+     * (which may or may not be identical to the remote SSH-2 server).
+     *
+     * @param host_to_connect
+     * @param port_to_connect
+     * @return A {@link LocalStreamForwarder} object.
+     * @throws IOException
+     */
+    public synchronized LocalStreamForwarder createLocalStreamForwarder(String host_to_connect, int port_to_connect)
+            throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("Cannot forward, you need to establish a connection first.");
+
+        if (!authenticated)
+            throw new IllegalStateException("Cannot forward, connection is not authenticated.");
+
+        return new LocalStreamForwarder(cm, host_to_connect, port_to_connect);
+    }
+
+    /**
+     * Create a very basic {@link SCPClient} that can be used to copy
+     * files from/to the SSH-2 server.
+     * <p>
+     * Works only after one has passed successfully the authentication step.
+     * There is no limit on the number of concurrent SCP clients.
+     * <p>
+     * Note: This factory method will probably disappear in the future.
+     *
+     * @return A {@link SCPClient} object.
+     * @throws IOException
+     */
+    public synchronized SCPClient createSCPClient() throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("Cannot create SCP client, you need to establish a connection first.");
+
+        if (!authenticated)
+            throw new IllegalStateException("Cannot create SCP client, connection is not authenticated.");
+
+        return new SCPClient(this);
+    }
+
+    /**
+     * Force an asynchronous key re-exchange (the call does not block). The
+     * latest values set for MAC, Cipher and DH group exchange parameters will
+     * be used. If a key exchange is currently in progress, then this method has
+     * the only effect that the so far specified parameters will be used for the
+     * next (server driven) key exchange.
+     * <p>
+     * Note: This implementation will never start a key exchange (other than the initial one)
+     * unless you or the SSH-2 server ask for it.
+     *
+     * @throws IOException
+     *             In case of any failure behind the scenes.
+     */
+    public synchronized void forceKeyExchange() throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("You need to establish a connection first.");
+
+        tm.forceKeyExchange(cryptoWishList, dhgexpara, null, null);
+    }
+
+    /**
+     * Returns the hostname that was passed to the constructor.
+     *
+     * @return the hostname
+     */
+    public synchronized String getHostname()
+    {
+        return hostname;
+    }
+
+    /**
+     * Returns the port that was passed to the constructor.
+     *
+     * @return the TCP port
+     */
+    public synchronized int getPort()
+    {
+        return port;
+    }
+
+    /**
+     * Returns a {@link ConnectionInfo} object containing the details of
+     * the connection. Can be called as soon as the connection has been
+     * established (successfully connected).
+     *
+     * @return A {@link ConnectionInfo} object.
+     * @throws IOException
+     *             In case of any failure behind the scenes.
+     */
+    public synchronized ConnectionInfo getConnectionInfo() throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException(
+                    "Cannot get details of connection, you need to establish a connection first.");
+        return tm.getConnectionInfo(1);
+    }
+
+    /**
+     * After a successful connect, one has to authenticate oneself. This method
+     * can be used to tell which authentication methods are supported by the
+     * server at a certain stage of the authentication process (for the given
+     * username).
+     * <p>
+     * Note 1: the username will only be used if no authentication step was done
+     * so far (it will be used to ask the server for a list of possible
+     * authentication methods by sending the initial "none" request). Otherwise,
+     * this method ignores the user name and returns a cached method list
+     * (which is based on the information contained in the last negative server response).
+     * <p>
+     * Note 2: the server may return method names that are not supported by this
+     * implementation.
+     * <p>
+     * After a successful authentication, this method must not be called
+     * anymore.
+     *
+     * @param user
+     *            A <code>String</code> holding the username.
+     *
+     * @return a (possibly emtpy) array holding authentication method names.
+     * @throws IOException
+     */
+    public synchronized String[] getRemainingAuthMethods(String user) throws IOException
+    {
+        if (user == null)
+            throw new IllegalArgumentException("user argument may not be NULL!");
+
+        if (tm == null)
+            throw new IllegalStateException("Connection is not established!");
+
+        if (authenticated)
+            throw new IllegalStateException("Connection is already authenticated!");
+
+        if (am == null)
+            am = new AuthenticationManager(tm);
+
+        if (cm == null)
+            cm = new ChannelManager(tm);
+
+        return am.getRemainingMethods(user);
+    }
+
+    /**
+     * Determines if the authentication phase is complete. Can be called at any
+     * time.
+     *
+     * @return <code>true</code> if no further authentication steps are
+     *         needed.
+     */
+    public synchronized boolean isAuthenticationComplete()
+    {
+        return authenticated;
+    }
+
+    /**
+     * Returns true if there was at least one failed authentication request and
+     * the last failed authentication request was marked with "partial success"
+     * by the server. This is only needed in the rare case of SSH-2 server setups
+     * that cannot be satisfied with a single successful authentication request
+     * (i.e., multiple authentication steps are needed.)
+     * <p>
+     * If you are interested in the details, then have a look at RFC4252.
+     *
+     * @return if the there was a failed authentication step and the last one
+     *         was marked as a "partial success".
+     */
+    public synchronized boolean isAuthenticationPartialSuccess()
+    {
+        if (am == null)
+            return false;
+
+        return am.getPartialSuccess();
+    }
+
+    /**
+     * Checks if a specified authentication method is available. This method is
+     * actually just a wrapper for {@link #getRemainingAuthMethods(String)
+     * getRemainingAuthMethods()}.
+     *
+     * @param user
+     *            A <code>String</code> holding the username.
+     * @param method
+     *            An authentication method name (e.g., "publickey", "password",
+     *            "keyboard-interactive") as specified by the SSH-2 standard.
+     * @return if the specified authentication method is currently available.
+     * @throws IOException
+     */
+    public synchronized boolean isAuthMethodAvailable(String user, String method) throws IOException
+    {
+        if (method == null)
+            throw new IllegalArgumentException("method argument may not be NULL!");
+
+        String methods[] = getRemainingAuthMethods(user);
+
+        for (int i = 0; i < methods.length; i++)
+        {
+            if (methods[i].compareTo(method) == 0)
+                return true;
+        }
+
+        return false;
+    }
+
+    private SecureRandom getOrCreateSecureRND()
+    {
+        if (generator == null)
+            generator = new SecureRandom();
+
+        return generator;
+    }
+
+    /**
+     * Open a new {@link Session} on this connection. Works only after one has passed
+     * successfully the authentication step. There is no limit on the number of
+     * concurrent sessions.
+     *
+     * @return A {@link Session} object.
+     * @throws IOException
+     */
+    public synchronized Session openSession() throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("Cannot open session, you need to establish a connection first.");
+
+        if (!authenticated)
+            throw new IllegalStateException("Cannot open session, connection is not authenticated.");
+
+        return new Session(cm, getOrCreateSecureRND());
+    }
+
+    /**
+     * Send an SSH_MSG_IGNORE packet. This method will generate a random data attribute
+     * (length between 0 (invlusive) and 16 (exclusive) bytes, contents are random bytes).
+     * <p>
+     * This method must only be called once the connection is established.
+     *
+     * @throws IOException
+     */
+    public synchronized void sendIgnorePacket() throws IOException
+    {
+        SecureRandom rnd = getOrCreateSecureRND();
+
+        byte[] data = new byte[rnd.nextInt(16)];
+        rnd.nextBytes(data);
+
+        sendIgnorePacket(data);
+    }
+
+    /**
+     * Send an SSH_MSG_IGNORE packet with the given data attribute.
+     * <p>
+     * This method must only be called once the connection is established.
+     *
+     * @throws IOException
+     */
+    public synchronized void sendIgnorePacket(byte[] data) throws IOException
+    {
+        if (data == null)
+            throw new IllegalArgumentException("data argument must not be null.");
+
+        if (tm == null)
+            throw new IllegalStateException(
+                    "Cannot send SSH_MSG_IGNORE packet, you need to establish a connection first.");
+
+        PacketIgnore pi = new PacketIgnore();
+        pi.setData(data);
+
+        tm.sendMessage(pi.getPayload());
+    }
+
+    /**
+     * Removes duplicates from a String array, keeps only first occurence
+     * of each element. Does not destroy order of elements; can handle nulls.
+     * Uses a very efficient O(N^2) algorithm =)
+     *
+     * @param list a String array.
+     * @return a cleaned String array.
+     */
+    private String[] removeDuplicates(String[] list)
+    {
+        if ((list == null) || (list.length < 2))
+            return list;
+
+        String[] list2 = new String[list.length];
+
+        int count = 0;
+
+        for (int i = 0; i < list.length; i++)
+        {
+            boolean duplicate = false;
+
+            String element = list[i];
+
+            for (int j = 0; j < count; j++)
+            {
+                if (((element == null) && (list2[j] == null)) || ((element != null) && (element.equals(list2[j]))))
+                {
+                    duplicate = true;
+                    break;
+                }
+            }
+
+            if (duplicate)
+                continue;
+
+            list2[count++] = list[i];
+        }
+
+        if (count == list2.length)
+            return list2;
+
+        String[] tmp = new String[count];
+        System.arraycopy(list2, 0, tmp, 0, count);
+
+        return tmp;
+    }
+
+    /**
+     * Unless you know what you are doing, you will never need this.
+     *
+     * @param ciphers
+     */
+    public synchronized void setClient2ServerCiphers(String[] ciphers)
+    {
+        if ((ciphers == null) || (ciphers.length == 0))
+            throw new IllegalArgumentException();
+        ciphers = removeDuplicates(ciphers);
+        BlockCipherFactory.checkCipherList(ciphers);
+        cryptoWishList.c2s_enc_algos = ciphers;
+    }
+
+    /**
+     * Unless you know what you are doing, you will never need this.
+     *
+     * @param macs
+     */
+    public synchronized void setClient2ServerMACs(String[] macs)
+    {
+        if ((macs == null) || (macs.length == 0))
+            throw new IllegalArgumentException();
+        macs = removeDuplicates(macs);
+        MAC.checkMacList(macs);
+        cryptoWishList.c2s_mac_algos = macs;
+    }
+
+    /**
+     * Sets the parameters for the diffie-hellman group exchange. Unless you
+     * know what you are doing, you will never need this. Default values are
+     * defined in the {@link DHGexParameters} class.
+     *
+     * @param dgp {@link DHGexParameters}, non null.
+     *
+     */
+    public synchronized void setDHGexParameters(DHGexParameters dgp)
+    {
+        if (dgp == null)
+            throw new IllegalArgumentException();
+
+        dhgexpara = dgp;
+    }
+
+    /**
+     * Unless you know what you are doing, you will never need this.
+     *
+     * @param ciphers
+     */
+    public synchronized void setServer2ClientCiphers(String[] ciphers)
+    {
+        if ((ciphers == null) || (ciphers.length == 0))
+            throw new IllegalArgumentException();
+        ciphers = removeDuplicates(ciphers);
+        BlockCipherFactory.checkCipherList(ciphers);
+        cryptoWishList.s2c_enc_algos = ciphers;
+    }
+
+    /**
+     * Unless you know what you are doing, you will never need this.
+     *
+     * @param macs
+     */
+    public synchronized void setServer2ClientMACs(String[] macs)
+    {
+        if ((macs == null) || (macs.length == 0))
+            throw new IllegalArgumentException();
+
+        macs = removeDuplicates(macs);
+        MAC.checkMacList(macs);
+        cryptoWishList.s2c_mac_algos = macs;
+    }
+
+    /**
+     * Define the set of allowed server host key algorithms to be used for
+     * the following key exchange operations.
+     * <p>
+     * Unless you know what you are doing, you will never need this.
+     *
+     * @param algos An array of allowed server host key algorithms.
+     *         SSH-2 defines <code>ssh-dss</code> and <code>ssh-rsa</code>.
+     *         The entries of the array must be ordered after preference, i.e.,
+     *  the entry at index 0 is the most preferred one. You must specify
+     *  at least one entry.
+     */
+    public synchronized void setServerHostKeyAlgorithms(String[] algos)
+    {
+        if ((algos == null) || (algos.length == 0))
+            throw new IllegalArgumentException();
+
+        algos = removeDuplicates(algos);
+        KexManager.checkServerHostkeyAlgorithmsList(algos);
+        cryptoWishList.serverHostKeyAlgorithms = algos;
+    }
+
+    /**
+     * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm) on the underlying socket.
+     * <p>
+     * Can be called at any time. If the connection has not yet been established
+     * then the passed value will be stored and set after the socket has been set up.
+     * The default value that will be used is <code>false</code>.
+     *
+     * @param enable the argument passed to the <code>Socket.setTCPNoDelay()</code> method.
+     * @throws IOException
+     */
+    public synchronized void setTCPNoDelay(boolean enable) throws IOException
+    {
+        tcpNoDelay = enable;
+
+        if (tm != null)
+            tm.setTcpNoDelay(enable);
+    }
+
+    /**
+     * Used to tell the library that the connection shall be established through a proxy server.
+     * It only makes sense to call this method before calling the {@link #connect() connect()}
+     * method.
+     * <p>
+     * At the moment, only HTTP proxies are supported.
+     * <p>
+     * Note: This method can be called any number of times. The {@link #connect() connect()}
+     * method will use the value set in the last preceding invocation of this method.
+     *
+     * @see HTTPProxyData
+     *
+     * @param proxyData Connection information about the proxy. If <code>null</code>, then
+     *                  no proxy will be used (non surprisingly, this is also the default).
+     */
+    public synchronized void setProxyData(ProxyData proxyData)
+    {
+        this.proxyData = proxyData;
+    }
+
+    /**
+     * Request a remote port forwarding.
+     * If successful, then forwarded connections will be redirected to the given target address.
+     * You can cancle a requested remote port forwarding by calling
+     * {@link #cancelRemotePortForwarding(int) cancelRemotePortForwarding()}.
+     * <p>
+     * A call of this method will block until the peer either agreed or disagreed to your request-
+     * <p>
+     * Note 1: this method typically fails if you
+     * <ul>
+     * <li>pass a port number for which the used remote user has not enough permissions (i.e., port
+     * &lt; 1024)</li>
+     * <li>or pass a port number that is already in use on the remote server</li>
+     * <li>or if remote port forwarding is disabled on the server.</li>
+     * </ul>
+     * <p>
+     * Note 2: (from the openssh man page): By default, the listening socket on the server will be
+     * bound to the loopback interface only. This may be overriden by specifying a bind address.
+     * Specifying a remote bind address will only succeed if the server's <b>GatewayPorts</b> option
+     * is enabled (see sshd_config(5)).
+     *
+     * @param bindAddress address to bind to on the server:
+     *                    <ul>
+     *                    <li>"" means that connections are to be accepted on all protocol families
+     *                    supported by the SSH implementation</li>
+     *                    <li>"0.0.0.0" means to listen on all IPv4 addresses</li>
+     *                    <li>"::" means to listen on all IPv6 addresses</li>
+     *                    <li>"localhost" means to listen on all protocol families supported by the SSH
+     *                    implementation on loopback addresses only, [RFC3330] and RFC3513]</li>
+     *                    <li>"127.0.0.1" and "::1" indicate listening on the loopback interfaces for
+     *                    IPv4 and IPv6 respectively</li>
+     *                    </ul>
+     * @param bindPort port number to bind on the server (must be &gt; 0)
+     * @param targetAddress the target address (IP or hostname)
+     * @param targetPort the target port
+     * @throws IOException
+     */
+    public synchronized void requestRemotePortForwarding(String bindAddress, int bindPort, String targetAddress,
+                                                         int targetPort) throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("You need to establish a connection first.");
+
+        if (!authenticated)
+            throw new IllegalStateException("The connection is not authenticated.");
+
+        if ((bindAddress == null) || (targetAddress == null) || (bindPort <= 0) || (targetPort <= 0))
+            throw new IllegalArgumentException();
+
+        cm.requestGlobalForward(bindAddress, bindPort, targetAddress, targetPort);
+    }
+
+    /**
+     * Cancel an earlier requested remote port forwarding.
+     * Currently active forwardings will not be affected (e.g., disrupted).
+     * Note that further connection forwarding requests may be received until
+     * this method has returned.
+     *
+     * @param bindPort the allocated port number on the server
+     * @throws IOException if the remote side refuses the cancel request or another low
+     *         level error occurs (e.g., the underlying connection is closed)
+     */
+    public synchronized void cancelRemotePortForwarding(int bindPort) throws IOException
+    {
+        if (tm == null)
+            throw new IllegalStateException("You need to establish a connection first.");
+
+        if (!authenticated)
+            throw new IllegalStateException("The connection is not authenticated.");
+
+        cm.requestCancelGlobalForward(bindPort);
+    }
+
+    /**
+     * Provide your own instance of SecureRandom. Can be used, e.g., if you
+     * want to seed the used SecureRandom generator manually.
+     * <p>
+     * The SecureRandom instance is used during key exchanges, public key authentication,
+     * x11 cookie generation and the like.
+     *
+     * @param rnd a SecureRandom instance
+     */
+    public synchronized void setSecureRandom(SecureRandom rnd)
+    {
+        if (rnd == null)
+            throw new IllegalArgumentException();
+
+        this.generator = rnd;
+    }
+}
diff --git a/third-party/ganymed/src/main/java/ch/ethz/ssh2/transport/TransportManager.java b/third-party/ganymed/src/main/java/ch/ethz/ssh2/transport/TransportManager.java
new file mode 100644 (file)
index 0000000..9632670
--- /dev/null
@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2006-2013 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+
+package ch.ethz.ssh2.transport;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import java.security.SecureRandom;
+import java.util.List;
+import java.util.Vector;
+
+import ch.ethz.ssh2.ConnectionInfo;
+import ch.ethz.ssh2.ConnectionMonitor;
+import ch.ethz.ssh2.DHGexParameters;
+import ch.ethz.ssh2.HTTPProxyData;
+import ch.ethz.ssh2.HTTPProxyException;
+import ch.ethz.ssh2.ProxyData;
+import ch.ethz.ssh2.ServerHostKeyVerifier;
+import ch.ethz.ssh2.crypto.Base64;
+import ch.ethz.ssh2.crypto.CryptoWishList;
+import ch.ethz.ssh2.crypto.cipher.BlockCipher;
+import ch.ethz.ssh2.crypto.digest.MAC;
+import ch.ethz.ssh2.log.Logger;
+import ch.ethz.ssh2.packets.PacketDisconnect;
+import ch.ethz.ssh2.packets.Packets;
+import ch.ethz.ssh2.packets.TypesReader;
+import ch.ethz.ssh2.server.ServerConnectionState;
+import ch.ethz.ssh2.signature.DSAPrivateKey;
+import ch.ethz.ssh2.signature.RSAPrivateKey;
+import ch.ethz.ssh2.util.StringEncoder;
+import ch.ethz.ssh2.util.Tokenizer;
+
+/*
+ * Yes, the "standard" is a big mess. On one side, the say that arbitary channel
+ * packets are allowed during kex exchange, on the other side we need to blindly
+ * ignore the next _packet_ if the KEX guess was wrong. Where do we know from that
+ * the next packet is not a channel data packet? Yes, we could check if it is in
+ * the KEX range. But the standard says nothing about this. The OpenSSH guys
+ * block local "normal" traffic during KEX. That's fine - however, they assume
+ * that the other side is doing the same. During re-key, if they receive traffic
+ * other than KEX, they become horribly irritated and kill the connection. Since
+ * we are very likely going to communicate with OpenSSH servers, we have to play
+ * the same game - even though we could do better.
+ * 
+ * btw: having stdout and stderr on the same channel, with a shared window, is
+ * also a VERY good idea... =(
+ */
+
+/**
+ * TransportManager.
+ *
+ * @author Christian Plattner
+ * @version $Id: TransportManager.java 47 2013-07-31 23:59:52Z cleondris@gmail.com $
+ */
+public class TransportManager
+{
+    private static final Logger log = Logger.getLogger(TransportManager.class);
+
+    private static class HandlerEntry
+    {
+        MessageHandler mh;
+        int low;
+        int high;
+    }
+
+    private final List<AsynchronousEntry> asynchronousQueue = new Vector<AsynchronousEntry>();
+    private Thread asynchronousThread = null;
+    private boolean asynchronousPending = false;
+
+    class AsynchronousEntry
+    {
+        public byte[] msg;
+        public Runnable run;
+
+        public AsynchronousEntry(byte[] msg, Runnable run)
+        {
+            this.msg = msg;
+            this.run = run;
+        }
+    }
+
+    class AsynchronousWorker extends Thread
+    {
+        @Override
+        public void run()
+        {
+            while (true)
+            {
+                AsynchronousEntry item = null;
+
+                synchronized (asynchronousQueue)
+                {
+                    if (asynchronousQueue.size() == 0)
+                    {
+                                               /* Only now we may reset the flag, since we are sure that all queued items
+                                                * have been sent (there is a slight delay between de-queuing and sending,
+                                                * this is why we need this flag! See code below. Sending takes place outside
+                                                * of this lock, this is why a test for size()==0 (from another thread) does not ensure
+                                                * that all messages have been sent.
+                                                */
+
+                        asynchronousPending = false;
+
+                                               /* Notify any senders that they can proceed, all async messages have been delivered */
+
+                        asynchronousQueue.notifyAll();
+
+                                               /* After the queue is empty for about 2 seconds, stop this thread */
+
+                        try
+                        {
+                            asynchronousQueue.wait(2000);
+                        }
+                        catch (InterruptedException ignore)
+                        {
+                        }
+
+                        if (asynchronousQueue.size() == 0)
+                        {
+                            asynchronousThread = null;
+                            return;
+                        }
+                    }
+
+                    item = asynchronousQueue.remove(0);
+                }
+
+                               /* The following invocation may throw an IOException.
+                                * There is no point in handling it - it simply means
+                                * that the connection has a problem and we should stop
+                                * sending asynchronously messages. We do not need to signal that
+                                * we have exited (asynchronousThread = null): further
+                                * messages in the queue cannot be sent by this or any
+                                * other thread.
+                                * Other threads will sooner or later (when receiving or
+                                * sending the next message) get the same IOException and
+                                * get to the same conclusion.
+                                */
+
+                try
+                {
+                    sendMessageImmediate(item.msg);
+                }
+                catch (IOException e)
+                {
+                    return;
+                }
+
+                if (item.run != null)
+                {
+                    try
+                    {
+                        item.run.run();
+                    }
+                    catch (Exception ignore)
+                    {
+                    }
+
+                }
+            }
+        }
+    }
+
+    private Socket sock = new Socket();
+
+    private final Object connectionSemaphore = new Object();
+
+    private boolean flagKexOngoing = false;
+    private boolean connectionClosed = false;
+
+    private Throwable reasonClosedCause = null;
+
+    private TransportConnection tc;
+    private KexManager km;
+
+    private final List<HandlerEntry> messageHandlers = new Vector<HandlerEntry>();
+
+    private Thread receiveThread;
+
+    private List<ConnectionMonitor> connectionMonitors = new Vector<ConnectionMonitor>();
+    private boolean monitorsWereInformed = false;
+
+    /**
+     * There were reports that there are JDKs which use
+     * the resolver even though one supplies a dotted IP
+     * address in the Socket constructor. That is why we
+     * try to generate the InetAdress "by hand".
+     *
+     * @param host
+     * @return the InetAddress
+     * @throws UnknownHostException
+     */
+    private static InetAddress createInetAddress(String host) throws UnknownHostException
+    {
+               /* Check if it is a dotted IP4 address */
+
+        InetAddress addr = parseIPv4Address(host);
+
+        if (addr != null)
+        {
+            return addr;
+        }
+
+        return InetAddress.getByName(host);
+    }
+
+    private static InetAddress parseIPv4Address(String host) throws UnknownHostException
+    {
+        if (host == null)
+        {
+            return null;
+        }
+
+        String[] quad = Tokenizer.parseTokens(host, '.');
+
+        if ((quad == null) || (quad.length != 4))
+        {
+            return null;
+        }
+
+        byte[] addr = new byte[4];
+
+        for (int i = 0; i < 4; i++)
+        {
+            int part = 0;
+
+            if ((quad[i].length() == 0) || (quad[i].length() > 3))
+            {
+                return null;
+            }
+
+            for (int k = 0; k < quad[i].length(); k++)
+            {
+                char c = quad[i].charAt(k);
+
+                               /* No, Character.isDigit is not the same */
+                if ((c < '0') || (c > '9'))
+                {
+                    return null;
+                }
+
+                part = part * 10 + (c - '0');
+            }
+
+            if (part > 255) /* 300.1.2.3 is invalid =) */
+            {
+                return null;
+            }
+
+            addr[i] = (byte) part;
+        }
+
+        return InetAddress.getByAddress(host, addr);
+    }
+
+    public int getPacketOverheadEstimate()
+    {
+        return tc.getPacketOverheadEstimate();
+    }
+
+    public void setTcpNoDelay(boolean state) throws IOException
+    {
+        sock.setTcpNoDelay(state);
+    }
+
+    public void setSoTimeout(int timeout) throws IOException
+    {
+        sock.setSoTimeout(timeout);
+    }
+
+    public ConnectionInfo getConnectionInfo(int kexNumber) throws IOException
+    {
+        return km.getOrWaitForConnectionInfo(kexNumber);
+    }
+
+    public Throwable getReasonClosedCause()
+    {
+        synchronized (connectionSemaphore)
+        {
+            return reasonClosedCause;
+        }
+    }
+
+    public byte[] getSessionIdentifier()
+    {
+        return km.sessionId;
+    }
+
+    public void close(Throwable cause, boolean useDisconnectPacket)
+    {
+        if (useDisconnectPacket == false)
+        {
+                       /* OK, hard shutdown - do not aquire the semaphore,
+                        * perhaps somebody is inside (and waits until the remote
+                        * side is ready to accept new data). */
+
+            try
+            {
+                sock.close();
+            }
+            catch (IOException ignore)
+            {
+            }
+
+                       /* OK, whoever tried to send data, should now agree that
+                        * there is no point in further waiting =)
+                        * It is safe now to aquire the semaphore.
+                        */
+        }
+
+        synchronized (connectionSemaphore)
+        {
+            if (connectionClosed == false)
+            {
+                if (useDisconnectPacket == true)
+                {
+                    try
+                    {
+                        byte[] msg = new PacketDisconnect(Packets.SSH_DISCONNECT_BY_APPLICATION, cause.getMessage(), "")
+                                .getPayload();
+                        if (tc != null)
+                        {
+                            tc.sendMessage(msg);
+                        }
+                    }
+                    catch (IOException ignore)
+                    {
+                    }
+
+                    try
+                    {
+                        sock.close();
+                    }
+                    catch (IOException ignore)
+                    {
+                    }
+                }
+
+                connectionClosed = true;
+                reasonClosedCause = cause; /* may be null */
+            }
+            connectionSemaphore.notifyAll();
+        }
+
+               /* No check if we need to inform the monitors */
+
+        List<ConnectionMonitor> monitors = new Vector<ConnectionMonitor>();
+
+        synchronized (this)
+        {
+                       /* Short term lock to protect "connectionMonitors"
+                        * and "monitorsWereInformed"
+                        * (they may be modified concurrently)
+                        */
+
+            if (monitorsWereInformed == false)
+            {
+                monitorsWereInformed = true;
+                monitors.addAll(connectionMonitors);
+            }
+        }
+
+        for (ConnectionMonitor cmon : monitors)
+        {
+            try
+            {
+                cmon.connectionLost(reasonClosedCause);
+            }
+            catch (Exception ignore)
+            {
+            }
+        }
+    }
+
+    private static Socket establishConnection(String hostname, int port, ProxyData proxyData, int connectTimeout)
+            throws IOException
+    {
+               /* See the comment for createInetAddress() */
+
+        if (proxyData == null)
+        {
+            InetAddress addr = createInetAddress(hostname);
+            Socket s = new Socket();
+            s.connect(new InetSocketAddress(addr, port), connectTimeout);
+            return s;
+        }
+
+        if (proxyData instanceof HTTPProxyData)
+        {
+            HTTPProxyData pd = (HTTPProxyData) proxyData;
+
+                       /* At the moment, we only support HTTP proxies */
+
+            InetAddress addr = createInetAddress(pd.proxyHost);
+            Socket s = new Socket();
+            s.connect(new InetSocketAddress(addr, pd.proxyPort), connectTimeout);
+
+                       /* OK, now tell the proxy where we actually want to connect to */
+
+            StringBuilder sb = new StringBuilder();
+
+            sb.append("CONNECT ");
+            sb.append(hostname);
+            sb.append(':');
+            sb.append(port);
+            sb.append(" HTTP/1.0\r\n");
+
+            if ((pd.proxyUser != null) && (pd.proxyPass != null))
+            {
+                String credentials = pd.proxyUser + ":" + pd.proxyPass;
+                char[] encoded = Base64.encode(StringEncoder.GetBytes(credentials));
+                sb.append("Proxy-Authorization: Basic ");
+                sb.append(encoded);
+                sb.append("\r\n");
+            }
+
+            if (pd.requestHeaderLines != null)
+            {
+                for (int i = 0; i < pd.requestHeaderLines.length; i++)
+                {
+                    if (pd.requestHeaderLines[i] != null)
+                    {
+                        sb.append(pd.requestHeaderLines[i]);
+                        sb.append("\r\n");
+                    }
+                }
+            }
+
+            sb.append("\r\n");
+
+            OutputStream out = s.getOutputStream();
+
+            out.write(StringEncoder.GetBytes(sb.toString()));
+            out.flush();
+
+                       /* Now parse the HTTP response */
+
+            byte[] buffer = new byte[1024];
+            InputStream in = s.getInputStream();
+
+            int len = ClientServerHello.readLineRN(in, buffer);
+
+            String httpReponse = StringEncoder.GetString(buffer, 0, len);
+
+            if (httpReponse.startsWith("HTTP/") == false)
+            {
+                throw new IOException("The proxy did not send back a valid HTTP response.");
+            }
+
+                       /* "HTTP/1.X XYZ X" => 14 characters minimum */
+
+            if ((httpReponse.length() < 14) || (httpReponse.charAt(8) != ' ') || (httpReponse.charAt(12) != ' '))
+            {
+                throw new IOException("The proxy did not send back a valid HTTP response.");
+            }
+
+            int errorCode = 0;
+
+            try
+            {
+                errorCode = Integer.parseInt(httpReponse.substring(9, 12));
+            }
+            catch (NumberFormatException ignore)
+            {
+                throw new IOException("The proxy did not send back a valid HTTP response.");
+            }
+
+            if ((errorCode < 0) || (errorCode > 999))
+            {
+                throw new IOException("The proxy did not send back a valid HTTP response.");
+            }
+
+            if (errorCode != 200)
+            {
+                throw new HTTPProxyException(httpReponse.substring(13), errorCode);
+            }
+
+                       /* OK, read until empty line */
+
+            while (true)
+            {
+                len = ClientServerHello.readLineRN(in, buffer);
+                if (len == 0)
+                {
+                    break;
+                }
+            }
+            return s;
+        }
+
+        throw new IOException("Unsupported ProxyData");
+    }
+
+    private void startReceiver() throws IOException
+    {
+        receiveThread = new Thread(new Runnable()
+        {
+            public void run()
+            {
+                try
+                {
+                    receiveLoop();
+                }
+                catch (Exception e)
+                {
+                    close(e, false);
+
+                    log.warning("Receive thread: error in receiveLoop: " + e.getMessage());
+                }
+
+                if (log.isDebugEnabled())
+                {
+                    log.debug("Receive thread: back from receiveLoop");
+                }
+
+                               /* Tell all handlers that it is time to say goodbye */
+
+                if (km != null)
+                {
+                    try
+                    {
+                        km.handleMessage(null, 0);
+                    }
+                    catch (IOException ignored)
+                    {
+                    }
+                }
+
+                for (HandlerEntry he : messageHandlers)
+                {
+                    try
+                    {
+                        he.mh.handleMessage(null, 0);
+                    }
+                    catch (Exception ignore)
+                    {
+                    }
+                }
+            }
+        });
+
+        receiveThread.setDaemon(true);
+        receiveThread.start();
+    }
+
+    public void clientInit(Socket socket, String softwareversion, CryptoWishList cwl,
+                           ServerHostKeyVerifier verifier, DHGexParameters dhgex, SecureRandom rnd) throws IOException
+    {
+               /* First, establish the TCP connection to the SSH-2 server */
+
+        sock = socket;
+
+               /* Parse the server line and say hello - important: this information is later needed for the
+                * key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object
+                * for later use.
+                */
+
+        ClientServerHello csh = ClientServerHello.clientHello(softwareversion, sock.getInputStream(),
+                sock.getOutputStream());
+
+        tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), rnd);
+        String hostname = sock.getInetAddress().getHostName();
+        int port = sock.getPort();
+
+        km = new ClientKexManager(this, csh, cwl, hostname, port, verifier, rnd);
+        km.initiateKEX(cwl, dhgex, null, null);
+
+        startReceiver();
+    }
+
+    public void clientInit(String hostname, int port, String softwareversion, CryptoWishList cwl,
+                           ServerHostKeyVerifier verifier, DHGexParameters dhgex, int connectTimeout, SecureRandom rnd,
+                           ProxyData proxyData) throws IOException
+    {
+               /* First, establish the TCP connection to the SSH-2 server */
+
+        sock = establishConnection(hostname, port, proxyData, connectTimeout);
+
+               /* Parse the server line and say hello - important: this information is later needed for the
+                * key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object
+                * for later use.
+                */
+
+        ClientServerHello csh = ClientServerHello.clientHello(softwareversion, sock.getInputStream(),
+                sock.getOutputStream());
+
+        tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), rnd);
+
+        km = new ClientKexManager(this, csh, cwl, hostname, port, verifier, rnd);
+        km.initiateKEX(cwl, dhgex, null, null);
+
+        startReceiver();
+    }
+
+    public void serverInit(ServerConnectionState state) throws IOException
+    {
+               /* TCP connection is already established */
+
+        this.sock = state.s;
+
+               /* Parse the client line and say hello - important: this information is later needed for the
+                * key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object
+                * for later use.
+                */
+
+        state.csh = ClientServerHello.serverHello(state.softwareversion, sock.getInputStream(), sock.getOutputStream());
+
+        tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), state.generator);
+
+        km = new ServerKexManager(state);
+        km.initiateKEX(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key);
+
+        startReceiver();
+    }
+
+    public void registerMessageHandler(MessageHandler mh, int low, int high)
+    {
+        HandlerEntry he = new HandlerEntry();
+        he.mh = mh;
+        he.low = low;
+        he.high = high;
+
+        synchronized (messageHandlers)
+        {
+            messageHandlers.add(he);
+        }
+    }
+
+    public void removeMessageHandler(MessageHandler mh, int low, int high)
+    {
+        synchronized (messageHandlers)
+        {
+            for (int i = 0; i < messageHandlers.size(); i++)
+            {
+                HandlerEntry he = messageHandlers.get(i);
+                if ((he.mh == mh) && (he.low == low) && (he.high == high))
+                {
+                    messageHandlers.remove(i);
+                    break;
+                }
+            }
+        }
+    }
+
+    public void sendKexMessage(byte[] msg) throws IOException
+    {
+        synchronized (connectionSemaphore)
+        {
+            if (connectionClosed)
+            {
+                throw (IOException) new IOException("Sorry, this connection is closed.").initCause(reasonClosedCause);
+            }
+
+            flagKexOngoing = true;
+
+            try
+            {
+                tc.sendMessage(msg);
+            }
+            catch (IOException e)
+            {
+                close(e, false);
+                throw e;
+            }
+        }
+    }
+
+    public void kexFinished() throws IOException
+    {
+        synchronized (connectionSemaphore)
+        {
+            flagKexOngoing = false;
+            connectionSemaphore.notifyAll();
+        }
+    }
+
+    /**
+     *
+     * @param cwl
+     * @param dhgex
+     * @param dsa may be null if this is a client connection
+     * @param rsa may be null if this is a client connection
+     * @throws IOException
+     */
+    public void forceKeyExchange(CryptoWishList cwl, DHGexParameters dhgex, DSAPrivateKey dsa, RSAPrivateKey rsa)
+            throws IOException
+    {
+        synchronized (connectionSemaphore)
+        {
+            if (connectionClosed)
+                               /* Inform the caller that there is no point in triggering a new kex */
+                throw (IOException) new IOException("Sorry, this connection is closed.").initCause(reasonClosedCause);
+        }
+
+        km.initiateKEX(cwl, dhgex, dsa, rsa);
+    }
+
+    public void changeRecvCipher(BlockCipher bc, MAC mac)
+    {
+        tc.changeRecvCipher(bc, mac);
+    }
+
+    public void changeSendCipher(BlockCipher bc, MAC mac)
+    {
+        tc.changeSendCipher(bc, mac);
+    }
+
+    public void sendAsynchronousMessage(byte[] msg) throws IOException
+    {
+        sendAsynchronousMessage(msg, null);
+    }
+
+    public void sendAsynchronousMessage(byte[] msg, Runnable run) throws IOException
+    {
+        synchronized (asynchronousQueue)
+        {
+            asynchronousQueue.add(new AsynchronousEntry(msg, run));
+            asynchronousPending = true;
+
+                       /* This limit should be flexible enough. We need this, otherwise the peer
+                        * can flood us with global requests (and other stuff where we have to reply
+                        * with an asynchronous message) and (if the server just sends data and does not
+                        * read what we send) this will probably put us in a low memory situation
+                        * (our send queue would grow and grow and...) */
+
+            if (asynchronousQueue.size() > 100)
+            {
+                throw new IOException("Error: the peer is not consuming our asynchronous replies.");
+            }
+
+                       /* Check if we have an asynchronous sending thread */
+
+            if (asynchronousThread == null)
+            {
+                asynchronousThread = new AsynchronousWorker();
+                asynchronousThread.setDaemon(true);
+                asynchronousThread.start();
+
+                               /* The thread will stop after 2 seconds of inactivity (i.e., empty queue) */
+            }
+
+            asynchronousQueue.notifyAll();
+        }
+    }
+
+    public void setConnectionMonitors(List<ConnectionMonitor> monitors)
+    {
+        synchronized (this)
+        {
+            connectionMonitors = new Vector<ConnectionMonitor>();
+            connectionMonitors.addAll(monitors);
+        }
+    }
+
+    /**
+     * True if no response message expected.
+     */
+    private boolean idle;
+
+    /**
+     * Send a message but ensure that all queued messages are being sent first.
+     *
+     * @param msg
+     * @throws IOException
+     */
+    public void sendMessage(byte[] msg) throws IOException
+    {
+        synchronized (asynchronousQueue)
+        {
+            while (asynchronousPending)
+            {
+                try
+                {
+                    asynchronousQueue.wait(1000);
+                }
+                catch (InterruptedException e)
+                {
+                }
+            }
+        }
+
+        sendMessageImmediate(msg);
+    }
+
+    /**
+     * Send message, ignore queued async messages that have not been delivered yet.
+     * Will be called directly from the asynchronousThread thread.
+     *
+     * @param msg
+     * @throws IOException
+     */
+    public void sendMessageImmediate(byte[] msg) throws IOException
+    {
+        if (Thread.currentThread() == receiveThread)
+        {
+            throw new IOException("Assertion error: sendMessage may never be invoked by the receiver thread!");
+        }
+
+        boolean wasInterrupted = false;
+
+        try
+        {
+            synchronized (connectionSemaphore)
+            {
+                while (true)
+                {
+                    if (connectionClosed)
+                    {
+                        throw (IOException) new IOException("Sorry, this connection is closed.")
+                                .initCause(reasonClosedCause);
+                    }
+
+                    if (flagKexOngoing == false)
+                    {
+                        break;
+                    }
+
+                    try
+                    {
+                        connectionSemaphore.wait();
+                    }
+                    catch (InterruptedException e)
+                    {
+                        wasInterrupted = true;
+                    }
+                }
+
+                try
+                {
+                    tc.sendMessage(msg);
+                    idle = false;
+                }
+                catch (IOException e)
+                {
+                    close(e, false);
+                    throw e;
+                }
+            }
+        }
+        finally
+        {
+            if (wasInterrupted)
+                Thread.currentThread().interrupt();
+        }
+    }
+
+    public void receiveLoop() throws IOException
+    {
+        byte[] msg = new byte[35000];
+
+        while (true)
+        {
+            int msglen;
+            try
+            {
+                msglen = tc.receiveMessage(msg, 0, msg.length);
+            }
+            catch (SocketTimeoutException e)
+            {
+                // Timeout in read
+                if (idle)
+                {
+                    log.debug("Ignoring socket timeout");
+                    continue;
+                }
+                throw e;
+            }
+            idle = true;
+
+            int type = msg[0] & 0xff;
+
+            if (type == Packets.SSH_MSG_IGNORE)
+            {
+                continue;
+            }
+
+            if (type == Packets.SSH_MSG_DEBUG)
+            {
+                if (log.isDebugEnabled())
+                {
+                    TypesReader tr = new TypesReader(msg, 0, msglen);
+                    tr.readByte();
+                    tr.readBoolean();
+                    StringBuilder debugMessageBuffer = new StringBuilder();
+                    debugMessageBuffer.append(tr.readString("UTF-8"));
+
+                    for (int i = 0; i < debugMessageBuffer.length(); i++)
+                    {
+                        char c = debugMessageBuffer.charAt(i);
+
+                        if ((c >= 32) && (c <= 126))
+                        {
+                            continue;
+                        }
+                        debugMessageBuffer.setCharAt(i, '\uFFFD');
+                    }
+
+                    log.debug("DEBUG Message from remote: '" + debugMessageBuffer.toString() + "'");
+                }
+                continue;
+            }
+
+            if (type == Packets.SSH_MSG_UNIMPLEMENTED)
+            {
+                throw new IOException("Peer sent UNIMPLEMENTED message, that should not happen.");
+            }
+
+            if (type == Packets.SSH_MSG_DISCONNECT)
+            {
+                TypesReader tr = new TypesReader(msg, 0, msglen);
+                tr.readByte();
+                int reason_code = tr.readUINT32();
+                StringBuilder reasonBuffer = new StringBuilder();
+                reasonBuffer.append(tr.readString("UTF-8"));
+
+                               /*
+                                * Do not get fooled by servers that send abnormal long error
+                                * messages
+                                */
+
+                if (reasonBuffer.length() > 255)
+                {
+                    reasonBuffer.setLength(255);
+                    reasonBuffer.setCharAt(254, '.');
+                    reasonBuffer.setCharAt(253, '.');
+                    reasonBuffer.setCharAt(252, '.');
+                }
+
+                               /*
+                                * Also, check that the server did not send characters that may
+                                * screw up the receiver -> restrict to reasonable US-ASCII
+                                * subset -> "printable characters" (ASCII 32 - 126). Replace
+                                * all others with 0xFFFD (UNICODE replacement character).
+                                */
+
+                for (int i = 0; i < reasonBuffer.length(); i++)
+                {
+                    char c = reasonBuffer.charAt(i);
+
+                    if ((c >= 32) && (c <= 126))
+                    {
+                        continue;
+                    }
+                    reasonBuffer.setCharAt(i, '\uFFFD');
+                }
+
+                throw new IOException("Peer sent DISCONNECT message (reason code " + reason_code + "): "
+                        + reasonBuffer.toString());
+            }
+
+                       /*
+                        * Is it a KEX Packet?
+                        */
+
+            if ((type == Packets.SSH_MSG_KEXINIT) || (type == Packets.SSH_MSG_NEWKEYS)
+                    || ((type >= 30) && (type <= 49)))
+            {
+                km.handleMessage(msg, msglen);
+                continue;
+            }
+
+            MessageHandler mh = null;
+
+            for (int i = 0; i < messageHandlers.size(); i++)
+            {
+                HandlerEntry he = messageHandlers.get(i);
+                if ((he.low <= type) && (type <= he.high))
+                {
+                    mh = he.mh;
+                    break;
+                }
+            }
+
+            if (mh == null)
+            {
+                throw new IOException("Unexpected SSH message (type " + type + ")");
+            }
+
+            mh.handleMessage(msg, msglen);
+        }
+    }
+}