Merge "Channel initializer class hierarchy refactor"
authorEd Warnicke <eaw@cisco.com>
Tue, 12 Nov 2013 14:05:41 +0000 (14:05 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 12 Nov 2013 14:05:41 +0000 (14:05 +0000)
90 files changed:
opendaylight/arphandler/pom.xml
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/Activator.java
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java
opendaylight/clustering/services_implementation/pom.xml
opendaylight/commons/logback_settings/pom.xml [new file with mode: 0644]
opendaylight/commons/logback_settings/src/main/resources/logback.xml [moved from opendaylight/commons/opendaylight/logback.xml with 100% similarity]
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/parent/logback.xml [deleted file]
opendaylight/commons/parent/space_and_tabs_checks.xml [deleted file]
opendaylight/distribution/opendaylight/pom.xml
opendaylight/hosttracker/implementation/pom.xml
opendaylight/hosttracker/implementation/src/test/resources/logback.xml [deleted file]
opendaylight/hosttracker_new/implementation/pom.xml
opendaylight/hosttracker_new/implementation/src/test/resources/logback.xml [deleted file]
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend
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.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentRpcConnector.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/Constants.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java [moved from opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/ClassLoaderUtils.java with 56% similarity]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-it/pom.xml
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/AbstractTest.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java
opendaylight/md-sal/sal-binding-it/src/test/resources/logback.xml [moved from opendaylight/statisticsmanager/implementation/src/test/resources/logback.xml with 100% similarity]
opendaylight/md-sal/sal-common-impl/pom.xml
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/AbstractDataModification.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend [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/BrokerActivator.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend [moved from opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/HashMapDataStore.xtend with 50% similarity]
opendaylight/md-sal/sal-netconf-connector/pom.xml
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/InventoryUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceManager.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfInventoryUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfProvider.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/XmlDocumentUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connector/netconf/test/MountTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/samples/toaster-it/pom.xml
opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java
opendaylight/md-sal/samples/toaster-it/src/test/resources/logback.xml [moved from opendaylight/clustering/services_implementation/src/test/resources/logback.xml with 99% similarity]
opendaylight/md-sal/test/sal-rest-connector-it/pom.xml
opendaylight/md-sal/test/sal-rest-connector-it/src/test/java/org/opendaylight/controller/test/restconf/it/ServiceProviderController.java
opendaylight/netconf/config-netconf-connector/pom.xml
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-it/pom.xml
opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java
opendaylight/northbound/java-client/enunciate.xml [new file with mode: 0644]
opendaylight/northbound/java-client/pom.xml [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/pom.xml
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/MessageReadWriteService.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SecureMessageReadWriteService.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java [new file with mode: 0644]
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SupportedFlowActions.java [new file with mode: 0644]
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Actions.java
opendaylight/statisticsmanager/implementation/pom.xml
opendaylight/switchmanager/implementation/pom.xml
opendaylight/switchmanager/implementation/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManager.java
opendaylight/switchmanager/implementation/src/test/resources/logback.xml [deleted file]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/DaylightWebAdmin.java
opendaylight/web/root/src/main/resources/js/open.js
pom.xml

index 4c22b4a74b08a8bf23793dd8ba4f7a6496fbbddf..8f1f4d5d2e7a85da93715a1ebba4cb66e3137a78 100644 (file)
@@ -32,6 +32,7 @@
               org.opendaylight.controller.sal.core,
               org.opendaylight.controller.sal.utils,
               org.opendaylight.controller.sal.packet,
+              org.opendaylight.controller.sal.routing,
               org.opendaylight.controller.switchmanager,
               org.opendaylight.controller.topologymanager,
               org.opendaylight.controller.clustering.services,
index f4edf6c74e989d6ce45fe6be27ca9c0d3fb44a0b..b253179c87185d50834240f654a524409a0fa392 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.controller.hosttracker.hostAware.IHostFinder;
 import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
 import org.opendaylight.controller.sal.packet.IDataPacketService;
 import org.opendaylight.controller.sal.packet.IListenDataPacket;
+import org.opendaylight.controller.sal.routing.IRouting;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.slf4j.Logger;
@@ -99,6 +100,10 @@ public class Activator extends ComponentActivatorAbstractBase {
                    "setClusterContainerService", "unsetClusterContainerService")
                    .setRequired(true));
 
+            c.add(createContainerServiceDependency(containerName).setService(
+                   IRouting.class).setCallbacks("setRouting","unsetRouting")
+                   .setRequired(false));
+
             // the Host Listener is optional
             c.add(createContainerServiceDependency(containerName).setService(
                     IfHostListener.class).setCallbacks("setHostListener",
index 7925c05f59466a5c3de3e4fa517f12e4d8368db8..abe104a40638f1a58e47fdcc5f91eda6b1f87359 100644 (file)
@@ -53,6 +53,7 @@ import org.opendaylight.controller.sal.packet.IPv4;
 import org.opendaylight.controller.sal.packet.Packet;
 import org.opendaylight.controller.sal.packet.PacketResult;
 import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.controller.sal.routing.IRouting;
 import org.opendaylight.controller.sal.utils.EtherTypes;
 import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.NetUtils;
@@ -69,6 +70,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
     private ISwitchManager switchManager;
     private ITopologyManager topologyManager;
     private IDataPacketService dataPacketService;
+    private IRouting routing;
     private IClusterContainerServices clusterContainerService;
     private IConnectionManager connectionManager;
     private Set<IfHostListener> hostListeners = new CopyOnWriteArraySet<IfHostListener>();
@@ -108,6 +110,16 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
         }
     }
 
+    void setRouting(IRouting r) {
+        this.routing = r;
+    }
+
+    void unsetRouting(IRouting r) {
+        if (this.routing == r) {
+            this.routing = null;
+        }
+    }
+
     void setHostListener(IfHostListener s) {
         if (this.hostListeners != null) {
             this.hostListeners.add(s);
@@ -460,21 +472,36 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA
 
         if (host == null) {
             // if we don't, know about the host, try to find it
-            log.trace("Punted IP pkt from {}, sending bcast ARP event...",
+            log.trace("Punted IP pkt to {}, sending bcast ARP event...",
                       dIP);
             /*
              * unknown destination host, initiate bcast ARP request
              */
             arpRequestReplyEvent.put(new ARPRequest(dIP, subnet), false);
-        }else{
 
-            // we know about the host, send the packet the right place
+        } else if (routing == null ||
+                   routing.getRoute(p.getNode(), host.getnodeconnectorNode()) != null) {
+            /* if IRouting is available, make sure that this packet can get it's
+             * destination normally before teleporting it there. If it's not
+             * available, then assume it's reachable.
+             *
+             * TODO: come up with a way to do this in the absence of IRouting
+             */
+
+            log.trace("forwarding punted IP pkt to {} received at {}", dIP, p);
+
+            /* if we know where the host is and there's a path from where this
+             * packet was punted to where the host is, then deliver it to the
+             * host for now */
             NodeConnector nc = host.getnodeConnector();
 
             // re-encode the Ethernet packet (the parent of the IPv4 packet)
             RawPacket rp = this.dataPacketService.encodeDataPacket(pkt.getParent());
             rp.setOutgoingNodeConnector(nc);
             this.dataPacketService.transmitDataPacket(rp);
+        } else {
+            log.trace("ignoring punted IP pkt to {} because there is no route from {}",
+                      dIP, p);
         }
     }
 
index e4bdc218dbc2c9a1f96812afa587c6476d14c5fa..ab75eb8dd1414f777c41adb985ac475097c0cd2b 100644 (file)
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/opendaylight/commons/logback_settings/pom.xml b/opendaylight/commons/logback_settings/pom.xml
new file mode 100644 (file)
index 0000000..c1ce36e
--- /dev/null
@@ -0,0 +1,17 @@
+<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/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>commons.logback_settings</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+    <tag>HEAD</tag>
+  </scm>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.parent</artifactId>
+    <version>1.0.1-SNAPSHOT</version>
+    <relativePath>../parent</relativePath>
+  </parent>
+</project>
index f86a0b7e78a841e040deb6ef51a435d33ff0001b..2a818067cec223101b907c90a79d4a4f84cea622 100644 (file)
         <artifactId>jolokia-osgi</artifactId>
         <version>${jolokia.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>commons.logback_settings</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 
 
   <build>
     <plugins>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>properties-maven-plugin</artifactId>
-        <version>${propertymavenplugin.version}</version>
-        <executions>
-          <execution>
-            <goals>
-              <goal>set-system-properties</goal>
-            </goals>
-            <configuration>
-              <properties>
-                <property>
-                  <name>logback.configurationFile</name>
-                  <value>${project.parent.basedir}/logback.xml</value>
-                </property>
-              </properties>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
-        <artifactId>maven-java-formatter-plugin</artifactId>
-        <version>0.3.1</version>
-        <configuration>
-          <compilerSource>1.6</compilerSource>
-          <compilerCompliance>1.6</compilerCompliance>
-          <compilerTargetPlatform>1.6</compilerTargetPlatform>
-          <configFile>${project.parent.basedir}/sun_coding_style.xml</configFile>
-        </configuration>
-      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
         <version>${failsafe.version}</version>
         <configuration>
           <argLine>${testvm.argLine}</argLine>
+          <systemProperties>
+            <property>
+              <name>logback.configurationFile</name>
+              <value>logback.xml</value>
+            </property>
+          </systemProperties>
         </configuration>
         <executions>
           <execution>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <version>${surefire.version}</version>
+        <configuration>
+          <systemProperties>
+            <property>
+              <name>logback.configurationFile</name>
+              <value>logback.xml</value>
+            </property>
+          </systemProperties>
+        </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
               </goals>
             </execution>
           </executions>
+          <dependencies>
+            <dependency>
+              <groupId>org.opendaylight.controller</groupId>
+              <artifactId>commons.logback_settings</artifactId>
+              <version>0.0.1-SNAPSHOT</version>
+            </dependency>
+          </dependencies>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
diff --git a/opendaylight/commons/parent/logback.xml b/opendaylight/commons/parent/logback.xml
deleted file mode 100644 (file)
index 05e6075..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<configuration scan="true">
-
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-    <encoder>
-      <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</pattern>
-    </encoder>
-  </appender>
-
-  <root level="error">
-    <appender-ref ref="STDOUT" />
-  </root>
-</configuration>
diff --git a/opendaylight/commons/parent/space_and_tabs_checks.xml b/opendaylight/commons/parent/space_and_tabs_checks.xml
deleted file mode 100644 (file)
index 49a5802..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0"?>\r
-<!DOCTYPE module PUBLIC\r
-    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"\r
-    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">\r
-\r
-<module name="Checker">\r
-    <module name="FileTabCharacter">\r
-        <property name="eachLine" value="true"/>\r
-    </module>\r
-\r
-    <module name="RegexpSingleline">\r
-        <!-- \s matches whitespace character, $ matches end of line. -->\r
-        <property name="format" value="\s+$"/>\r
-        <property name="message" value="Line has trailing spaces."/>\r
-    </module>\r
-\r
-</module>\r
index 1ebab9b03adefcf245319388a6f290ce0c759949..db4efef0300bf0271b513fd2d5c5d1201e0ab66e 100644 (file)
           <artifactId>model-flow-management</artifactId>
           <version>${mdsal.version}</version>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller.md</groupId>
+          <artifactId>inventory-manager</artifactId>
+          <version>${mdsal.version}</version>
+        </dependency>
 
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>yang-jmx-generator-plugin</artifactId>
           <version>${config.version}</version>
         </dependency>
-        <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>yang-jmx-generator-it</artifactId>
-          <version>${config.version}</version>
-        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>yang-store-api</artifactId>
           <artifactId>yang-store-impl</artifactId>
           <version>${config.version}</version>
         </dependency>
-        <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>yang-test</artifactId>
-          <version>${config.version}</version>
-        </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>logback-config</artifactId>
          </dependency>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>binding-generator-util</artifactId>
+          <artifactId>binding-generator-spi</artifactId>
           <version>${yangtools.binding.version}</version>
          </dependency>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>binding-model-api</artifactId>
+          <artifactId>binding-generator-api</artifactId>
           <version>${yangtools.binding.version}</version>
          </dependency>
          <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>binding-generator-spi</artifactId>
+          <artifactId>binding-generator-impl</artifactId>
+          <version>${yangtools.binding.version}</version>
+         </dependency>
+         <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>binding-generator-util</artifactId>
+          <version>${yangtools.binding.version}</version>
+         </dependency>
+         <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>binding-model-api</artifactId>
           <version>${yangtools.binding.version}</version>
          </dependency>
          <dependency>
         </dependency>
       </dependencies>
     </profile>
+    <profile>
+      <id>integrationtests</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-dependency-plugin</artifactId>
+            <version>2.8</version>
+            <executions>
+              <execution>
+                <id>copy</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.opendaylight.controller</groupId>
+                  <artifactId>sanitytest</artifactId>
+                  <version>${controller.version}</version>
+                  <type>jar</type>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </plugin>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>exec-maven-plugin</artifactId>
+            <version>1.2.1</version>
+            <executions>
+              <execution>
+                <id>sanity-test</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>exec</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <executable>${java.home}/bin/java</executable>
+              <arguments>
+                <argument>-cp</argument>
+                <argument>./target/dependency/*</argument>
+                <argument>org.opendaylight.controller.distribution.Sanity</argument>
+              </arguments>
+              <environmentVariables>
+                <JAVA_HOME>
+                  ${java.home}
+                </JAVA_HOME>
+              </environmentVariables>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
   </profiles>
 
   <artifactId>distribution.opendaylight</artifactId>
           </execution>
         </executions>
       </plugin>
-
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-dependency-plugin</artifactId>
-        <version>2.8</version>
-          <executions>
-            <execution>
-              <id>copy</id>
-              <phase>package</phase>
-              <goals>
-                <goal>copy</goal>
-              </goals>
-            </execution>
-          </executions>
-          <configuration>
-            <artifactItems>
-              <artifactItem>
-                <groupId>org.opendaylight.controller</groupId>
-                <artifactId>sanitytest</artifactId>
-                <version>${controller.version}</version>
-                <type>jar</type>
-              </artifactItem>
-            </artifactItems>
-          </configuration>
-      </plugin>
-
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>exec-maven-plugin</artifactId>
-        <version>1.2.1</version>
-        <executions>
-          <execution>
-            <id>sanity-test</id>
-            <phase>package</phase>
-            <goals>
-              <goal>exec</goal>
-            </goals>
-          </execution>
-        </executions>
-          <configuration>
-            <executable>${java.home}/bin/java</executable>
-            <arguments>
-                <argument>-cp</argument>
-                <argument>./target/dependency/*</argument>
-                <argument>org.opendaylight.controller.distribution.Sanity</argument>
-            </arguments>
-            <environmentVariables>
-              <JAVA_HOME>
-                ${java.home}
-              </JAVA_HOME>
-            </environmentVariables>
-          </configuration>
-      </plugin>
     </plugins>
   </build>
 </project>
index 241f926ae4b44c53477d6b0b938e8df164dbc084..6faf2e91782495efe48be290910f5958f80a8e92 100644 (file)
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/opendaylight/hosttracker/implementation/src/test/resources/logback.xml b/opendaylight/hosttracker/implementation/src/test/resources/logback.xml
deleted file mode 100644 (file)
index 5fa21fe..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<configuration scan="true">\r
-\r
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
-    <encoder>\r
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
-      </pattern>\r
-    </encoder>\r
-  </appender>\r
-\r
-  <root level="error">\r
-    <appender-ref ref="STDOUT" />\r
-  </root>\r
-</configuration>\r
index 99760a68341edb9e11f0198dbec54d2089125d21..0405d45b6e1989cc186927a016794108c9ac86d2 100644 (file)
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/opendaylight/hosttracker_new/implementation/src/test/resources/logback.xml b/opendaylight/hosttracker_new/implementation/src/test/resources/logback.xml
deleted file mode 100644 (file)
index 5fa21fe..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<configuration scan="true">\r
-\r
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
-    <encoder>\r
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
-      </pattern>\r
-    </encoder>\r
-  </appender>\r
-\r
-  <root level="error">\r
-    <appender-ref ref="STDOUT" />\r
-  </root>\r
-</configuration>\r
index fd89da4dd0c0e2b7876e8e0adcf6f90d87fc6cff..1ff7f2dc302e1218f8a494cdb0b4f0c9811a7548 100644 (file)
@@ -49,7 +49,6 @@
         <module>compatibility</module>
 
         <module>sal-zeromq-connector</module>
-        <module>test</module>
     </modules>
 
 
@@ -62,6 +61,7 @@
             <modules>
                 <module>sal-binding-it</module>
                 <module>clustered-data-store/integrationtest</module>
+                <module>test</module>
             </modules>
         </profile>
     </profiles>
     <build>
         <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.jacoco</groupId>
-                                    <artifactId>jacoco-maven-plugin</artifactId>
-                                    <versionRange>[0.0,)</versionRange>
-                                    <goals>
-                                      <goal>prepare-agent</goal>
-                                      <goal>pre-test</goal>
-                                      <goal>post-test</goal>
-                                    </goals>
-                                  </pluginExecutionFilter>
-                                  <action>
-                                    <ignore />
-                                  </action>
-                                </pluginExecution>
-                            </pluginExecutions>
-                        </lifecycleMappingMetadata>
-                    </configuration>
-                </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-release-plugin</artifactId>
                             <pluginExecutions>
                                 <pluginExecution>
                                     <pluginExecutionFilter>
-                                        <groupId>
-                                            org.opendaylight.yangtools
-                                        </groupId>
-                                        <artifactId>
-                                            yang-maven-plugin
-                                        </artifactId>
-                                        <versionRange>
-                                            [0.5,)
-                                        </versionRange>
+                                        <groupId>org.opendaylight.yangtools</groupId>
+                                        <artifactId>yang-maven-plugin</artifactId>
+                                        <versionRange>[0,)</versionRange>
+                                        <goals>
+                                            <goal>generate-sources</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore/>
+                                    </action>
+                                </pluginExecution>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>net.alchim31.maven</groupId>
+                                        <artifactId>scala-maven-plugin</artifactId>
+                                        <versionRange>[0,)</versionRange>
                                         <goals>
-                                            <goal>
-                                                generate-sources
-                                            </goal>
+                                            <goal>compile</goal>
+                                            <goal>testCompile</goal>
                                         </goals>
                                     </pluginExecutionFilter>
                                     <action>
-                                        <ignore></ignore>
+                                      <ignore/>
                                     </action>
                                 </pluginExecution>
                                 <pluginExecution>
                                     <pluginExecutionFilter>
                                         <groupId>org.jacoco</groupId>
-                                        <artifactId>
-                                            jacoco-maven-plugin
-                                        </artifactId>
-                                        <versionRange>
-                                            [0.5.3.201107060350,)
-                                        </versionRange>
+                                        <artifactId>jacoco-maven-plugin</artifactId>
+                                        <versionRange>[0,)</versionRange>
                                         <goals>
                                             <goal>prepare-agent</goal>
                                         </goals>
                                     </pluginExecutionFilter>
                                     <action>
-                                        <ignore></ignore>
+                                        <ignore/>
                                     </action>
                                 </pluginExecution>
                             </pluginExecutions>
index b0e2023f1fd11faab50376aa846034c16472078b..35264e74e6bd22bf1a69db6f97c3884270d3a5a5 100644 (file)
@@ -16,6 +16,7 @@
 
     <build>
         <plugins>
+        
             <plugin>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>yang-maven-plugin</artifactId>
@@ -51,6 +52,7 @@
                     </dependency>
                 </dependencies>
             </plugin>
+            
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>build-helper-maven-plugin</artifactId>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
             <version>${osgi.core.version}</version>
+        <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>javassist</artifactId>
             <version>3.17.1-GA</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-impl</artifactId>
+            <version>0.6.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+            <scope>test</scope>
+        </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>sal-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>runtime</scope>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <groupId>org.eclipse.xtend</groupId>
             <artifactId>org.eclipse.xtend.lib</artifactId>
         </dependency>
+       <dependency>
+       <groupId>org.eclipse.xtend</groupId>
+       <artifactId>org.eclipse.xtend.standalone</artifactId>
+       <version>2.4.3</version>
+       <scope>runtime</scope>
+       </dependency> 
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-config</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-flow-service</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-util</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>${slf4j.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
index 87cc42c6e413d15502c068431da14d10c851fc99..ea6dc131c6583b3587b23cc172e61f62c3ad68af 100644 (file)
@@ -33,7 +33,7 @@ import java.util.Arrays
 import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.*
 import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
 import java.util.HashSet
-import static org.opendaylight.controller.sal.binding.impl.osgi.ClassLoaderUtils.*
+import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker
 import java.util.Set
index d9a3dd547f67a1cc448272f7d0a67c2284fb9ddb..31d5d0126fc8115546d1d1b7709671e946b2e026 100644 (file)
@@ -40,10 +40,11 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
 import org.opendaylight.yangtools.yang.binding.BaseIdentity
 import com.google.common.collect.Multimap
 import com.google.common.collect.HashMultimap
-import static org.opendaylight.controller.sal.binding.impl.osgi.ClassLoaderUtils.*
+import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*
 import java.util.concurrent.Executors
 import java.util.Collections
 import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.sal.binding.impl.connect.dom.ConnectorActivator
 
 class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable {
     private static val log = LoggerFactory.getLogger(BindingAwareBrokerImpl)
@@ -86,7 +87,8 @@ class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable {
     
     ServiceRegistration<DataBrokerService> dataConsumerRegistration
     
-    private HashMapDataStore store = new HashMapDataStore();
+    ConnectorActivator connectorActivator
+   
     
     public new(BundleContext bundleContext) {
         _brokerBundleContext = bundleContext;
@@ -115,11 +117,9 @@ class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable {
         notifyConsumerRegistration = brokerBundleContext.registerService(NotificationService, notifyBroker, brokerProperties)
         dataProviderRegistration = brokerBundleContext.registerService(DataProviderService, dataBroker, brokerProperties)
         dataConsumerRegistration = brokerBundleContext.registerService(DataBrokerService, dataBroker, brokerProperties)
-        
-        
-        getDataBroker().registerDataReader(root, store);
-        getDataBroker().registerCommitHandler(root, store)
-        
+
+        connectorActivator = new ConnectorActivator(dataBroker,brokerBundleContext);
+        connectorActivator.start();
         log.info("MD-SAL: Binding Aware Broker Started");
     }
 
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java
new file mode 100644 (file)
index 0000000..7a1ca11
--- /dev/null
@@ -0,0 +1,93 @@
+package org.opendaylight.controller.sal.binding.impl;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+
+public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier<? extends DataObject>, DataObject, DataChangeListener> implements
+        DataProviderService {
+
+    public DataBrokerImpl() {
+        setDataReadRouter(new BindingAwareDataReaderRouter());
+    }
+
+    @Override
+    public DataTransactionImpl beginTransaction() {
+        return new DataTransactionImpl(this);
+    }
+
+    @Override
+    public <T extends DataRoot> T getData(DataStoreIdentifier store, Class<T> rootType) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T extends DataRoot> T getData(DataStoreIdentifier store, T filter) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, Class<T> rootType) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, T filter) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public RpcResult<DataRoot> editCandidateData(DataStoreIdentifier store, DataRoot changeSet) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> commit(DataStoreIdentifier store) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public DataObject getData(InstanceIdentifier<? extends DataObject> data) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public DataObject getConfigurationData(InstanceIdentifier<?> data) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void registerChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener changeListener) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void unregisterChangeListener(InstanceIdentifier<? extends DataObject> path,
+            DataChangeListener changeListener) {
+        // TODO Auto-generated method stub
+        
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend
deleted file mode 100644 (file)
index 6ed63b2..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.opendaylight.controller.sal.binding.impl
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-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.md.sal.common.api.TransactionStatus
-import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
-import org.opendaylight.yangtools.concepts.ListenerRegistration
-import com.google.common.collect.Multimap
-import static com.google.common.base.Preconditions.*;
-import java.util.List
-import com.google.common.collect.HashMultimap
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Callable
-import org.opendaylight.yangtools.yang.common.RpcResult
-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.binding.impl.util.BindingAwareDataReaderRouter
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration
-import java.util.Arrays
-
-class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderService {
-
-    @Property
-    var ExecutorService executor;
-
-    val dataReadRouter = new BindingAwareDataReaderRouter;
-
-    Multimap<InstanceIdentifier, DataChangeListenerRegistration> listeners = HashMultimap.create();
-    Multimap<InstanceIdentifier, DataCommitHandlerRegistration> commitHandlers = HashMultimap.create();
-
-    override beginTransaction() {
-        return new DataTransactionImpl(this);
-    }
-
-    override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
-        return dataReadRouter.readConfigurationData(path);
-    }
-
-    override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
-        return dataReadRouter.readOperationalData(path);
-    }
-
-    override registerCommitHandler(InstanceIdentifier<? extends DataObject> path,
-        DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
-            val registration = new DataCommitHandlerRegistration(path,commitHandler,this);
-            commitHandlers.put(path,registration)
-            return registration;
-    }
-
-    override registerDataChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener listener) {
-        val reg = new DataChangeListenerRegistration(path, listener, this);
-        listeners.put(path, reg);
-        return reg;
-    }
-
-    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) {
-        listeners.remove(registration.path, registration);
-    }
-
-    protected def removeCommitHandler(DataCommitHandlerRegistration registration) {
-        commitHandlers.remove(registration.path, registration);
-    }
-    
-    protected def getActiveCommitHandlers() {
-        return commitHandlers.entries.map[ value.instance].toSet
-    }
-
-    protected def commit(DataTransactionImpl transaction) {
-        checkNotNull(transaction);
-        transaction.changeStatus(TransactionStatus.SUBMITED);
-        val task = new TwoPhaseCommit(transaction, this);
-        return executor.submit(task);
-    }
-
-}
-
-package class DataChangeListenerRegistration extends AbstractObjectRegistration<DataChangeListener> implements ListenerRegistration<DataChangeListener> {
-
-    DataBrokerImpl dataBroker;
-
-    @Property
-    val InstanceIdentifier<?> path;
-
-    new(InstanceIdentifier<?> path, DataChangeListener instance, DataBrokerImpl broker) {
-        super(instance)
-        dataBroker = broker;
-        _path = path;
-    }
-
-    override protected removeRegistration() {
-        dataBroker.removeListener(this);
-        dataBroker = null;
-    }
-
-}
-
-package class DataCommitHandlerRegistration //
-extends AbstractObjectRegistration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> {
-
-    DataBrokerImpl dataBroker;
-
-    @Property
-    val InstanceIdentifier<?> path;
-
-    new(InstanceIdentifier<?> path, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> instance,
-        DataBrokerImpl broker) {
-        super(instance)
-        dataBroker = broker;
-        _path = path;
-    }
-
-    override protected removeRegistration() {
-        dataBroker.removeCommitHandler(this);
-        dataBroker = null;
-    }
-
-}
-
-package class TwoPhaseCommit implements Callable<RpcResult<TransactionStatus>> {
-
-    val DataTransactionImpl transaction;
-    val DataBrokerImpl dataBroker;
-
-    new(DataTransactionImpl transaction, DataBrokerImpl broker) {
-        this.transaction = transaction;
-        this.dataBroker = broker;
-    }
-
-    override call() throws Exception {
-
-        val Iterable<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> commitHandlers = dataBroker.activeCommitHandlers;
-
-        // requesting commits
-        val List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> handlerTransactions = new ArrayList();
-        try {
-            for (handler : commitHandlers) {
-                handlerTransactions.add(handler.requestCommit(transaction));
-            }
-        } catch (Exception e) {
-            return rollback(handlerTransactions,e);
-        }
-        val List<RpcResult<Void>> results = new ArrayList();
-        try {
-            for (subtransaction : handlerTransactions) {
-                results.add(subtransaction.finish());
-            }
-        } catch (Exception e) {
-            return rollback(handlerTransactions,e);
-        }
-
-        return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
-    }
-
-    def rollback(List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> transactions,Exception e) {
-        for (transaction : transactions) {
-            transaction.rollback()
-        }
-        // FIXME return encoutered error.
-        return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
-    }
-}
index c970fc5e920db0cfbfcd8a277ec9bcaa8a109fb6..f7967beaae6471a482885535e02d2aae26a06536 100644 (file)
@@ -1,89 +1,22 @@
 package org.opendaylight.controller.sal.binding.impl;
 
-import java.util.concurrent.Future;
-
 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.impl.ListenerRegistry;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-public class DataTransactionImpl extends AbstractDataModification<InstanceIdentifier<? extends DataObject>, DataObject>
-        implements DataModificationTransaction {
-
-    private final Object identifier;
-
-    private TransactionStatus status;
-    private ListenerRegistry<DataTransactionListener> listeners;
-
-    final DataBrokerImpl broker;
 
+public class DataTransactionImpl extends AbstractDataTransaction<InstanceIdentifier<? extends DataObject>, DataObject> 
+    implements DataModificationTransaction {
+    private final ListenerRegistry<DataTransactionListener> listeners = new ListenerRegistry<DataTransactionListener>();
+    
+    
+    
     public DataTransactionImpl(DataBrokerImpl dataBroker) {
         super(dataBroker);
-        identifier = new Object();
-        broker = dataBroker;
-        status = TransactionStatus.NEW;
-        listeners = new ListenerRegistry<>();
-    }
-
-    @Override
-    public Future<RpcResult<TransactionStatus>> commit() {
-        return broker.commit(this);
-    }
-
-    @Override
-    public DataObject readConfigurationData(
-            org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path) {
-        return broker.readConfigurationData(path);
-    }
-
-    @Override
-    public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
-        return broker.readOperationalData(path);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((broker == null) ? 0 : broker.hashCode());
-        result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        DataTransactionImpl other = (DataTransactionImpl) obj;
-        if (broker == null) {
-            if (other.broker != null)
-                return false;
-        } else if (!broker.equals(other.broker))
-            return false;
-        if (identifier == null) {
-            if (other.identifier != null)
-                return false;
-        } else if (!identifier.equals(other.identifier))
-            return false;
-        return true;
-    }
-
-    @Override
-    public TransactionStatus getStatus() {
-        return status;
-    }
-
-    @Override
-    public Object getIdentifier() {
-        return identifier;
     }
 
     @Override
@@ -91,11 +24,9 @@ public class DataTransactionImpl extends AbstractDataModification<InstanceIdenti
         return listeners.register(listener);
     }
 
-    public void changeStatus(TransactionStatus status) {
-        this.status = status;
-        Iterable<ListenerRegistration<DataTransactionListener>> listenersToNotify = listeners.getListeners();
-        for (ListenerRegistration<DataTransactionListener> listenerRegistration : listenersToNotify) {
+    protected void onStatusChange(TransactionStatus status) {
+        for (ListenerRegistration<DataTransactionListener> listenerRegistration : listeners) {
             listenerRegistration.getInstance().onStatusUpdated(this, status);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java
new file mode 100644 (file)
index 0000000..ff897aa
--- /dev/null
@@ -0,0 +1,151 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.base.Preconditions;
+
+public class BindingIndependentDataServiceConnector implements //
+        RuntimeDataProvider, //
+        DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+    private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
+
+    private BindingIndependentMappingService mappingService;
+
+    private DataBrokerService biDataService;
+
+    private DataProviderService baDataService;
+
+    @Override
+    public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+        // TODO Auto-generated method stub
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+        CompositeNode result = biDataService.readOperationalData(biPath);
+        return mappingService.dataObjectFromDataDom(path, result);
+    }
+
+    @Override
+    public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+        CompositeNode result = biDataService.readConfigurationData(biPath);
+        return mappingService.dataObjectFromDataDom(path, result);
+    }
+
+    @Override
+    public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
+            DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+
+        DataModificationTransaction translated = translateTransaction(modification);
+        return new WrappedTransaction(translated, modification);
+    }
+
+    private DataModificationTransaction translateTransaction(
+            DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
+        DataModificationTransaction target = biDataService.beginTransaction();
+        for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
+                .entrySet()) {
+            Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+                    .toDataDom(entry);
+            target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
+        }
+        for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
+                .entrySet()) {
+            Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+                    .toDataDom(entry);
+            target.putOperationalData(biEntry.getKey(), biEntry.getValue());
+        }
+        for(InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+            target.removeConfigurationData(biEntry);
+        }
+        for(InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+            target.removeOperationalData(biEntry);
+        }
+        return target;
+    }
+
+    private class WrappedTransaction implements
+            DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+        private DataModificationTransaction backing;
+        private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+
+        public WrappedTransaction(DataModificationTransaction backing,
+                DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+            this.backing = backing;
+            this.modification = modification;
+        }
+
+        @Override
+        public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
+            return modification;
+        }
+
+        @Override
+        public RpcResult<Void> finish() throws IllegalStateException {
+            Future<RpcResult<TransactionStatus>> result = backing.commit();
+            try {
+                RpcResult<TransactionStatus> biresult = result.get();
+            } catch (InterruptedException e) {
+                throw new IllegalStateException("", e);
+            } catch (ExecutionException e) {
+                throw new IllegalStateException("", e);
+            }
+            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+        }
+
+        @Override
+        public RpcResult<Void> rollback() throws IllegalStateException {
+            // backing.cancel();
+            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+        }
+
+    }
+
+    public DataBrokerService getBiDataService() {
+        return biDataService;
+    }
+
+    public void setBiDataService(DataBrokerService biDataService) {
+        this.biDataService = biDataService;
+    }
+
+    public DataProviderService getBaDataService() {
+        return baDataService;
+    }
+
+    public void setBaDataService(DataProviderService baDataService) {
+        this.baDataService = baDataService;
+    }
+
+    public void start() {
+        baDataService.registerDataReader(ROOT, this);
+        baDataService.registerCommitHandler(ROOT, this);
+    }
+
+    public void setMappingService(BindingIndependentMappingService mappingService) {
+        this.mappingService = mappingService;
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java
new file mode 100644 (file)
index 0000000..d8fbc70
--- /dev/null
@@ -0,0 +1,19 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Map.Entry;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface BindingIndependentMappingService {
+
+    CompositeNode toDataDom(DataObject data);
+
+    Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+            Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry);
+
+    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(InstanceIdentifier<? extends DataObject> path);
+
+    DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result);
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentRpcConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentRpcConnector.java
new file mode 100644 (file)
index 0000000..d22da30
--- /dev/null
@@ -0,0 +1,5 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+public class BindingIndependentRpcConnector {
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend
new file mode 100644 (file)
index 0000000..9a6330e
--- /dev/null
@@ -0,0 +1,402 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom
+
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext
+import java.util.List
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import java.util.Map
+import org.opendaylight.yangtools.yang.model.api.SchemaPath
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
+import org.opendaylight.yangtools.binding.generator.util.Types
+import java.util.HashMap
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.binding.DataContainer
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import java.util.Collections
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import org.opendaylight.yangtools.yang.model.util.ExtendedType
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import com.google.common.collect.FluentIterable
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
+import org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition
+
+class BindingMapping {
+
+    val Map<Type, GeneratedTypeBuilder> typeToDefinition = new HashMap();
+    val Map<Type, SchemaNode> typeToSchemaNode = new HashMap();
+
+    def QName getSchemaNode(Class<?> cls) {
+        val ref = Types.typeForClass(cls);
+        return typeToSchemaNode.get(ref)?.QName;
+    }
+
+    def void updateBinding(SchemaContext schemaContext, ModuleContext moduleBindingContext) {
+        updateBindingFor(moduleBindingContext.childNodes, schemaContext);
+
+    }
+
+    def org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
+        InstanceIdentifier<? extends DataObject> obj) {
+        val pathArguments = obj.path;
+        var Class<? extends DataObject> parent;
+        val dataDomArgs = new ArrayList<PathArgument>();
+        for (pathArgument : pathArguments) {
+            dataDomArgs.add(pathArgument.toDataDomPathArgument(parent));
+            parent = pathArgument.type;
+        }
+
+        return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(dataDomArgs);
+    }
+
+    
+
+    def DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> identifier, CompositeNode node) {
+        if (node == null) {
+            return null;
+        }
+        val targetClass = identifier.targetType;
+        val classLoader = targetClass.classLoader;
+        val ref = Types.typeForClass(targetClass);
+        val targetType = typeToDefinition.get(ref);
+        val targetSchema = typeToSchemaNode.get(ref);
+        return node.toDataObject(classLoader, targetType.toInstance, targetSchema);
+
+    }
+
+    def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument, Class<? extends DataObject> parent) {
+        val Class rawType = argument.type;
+        val ref = Types.typeForClass(rawType);
+        val schemaType = typeToSchemaNode.get(ref);
+        val qname = schemaType.QName
+
+        val Object key = argument.key;
+        val predicates = key.toPredicates(schemaType as ListSchemaNode);
+
+        return new NodeIdentifierWithPredicates(qname, predicates);
+    }
+    
+    def dispatch PathArgument toDataDomPathArgument(Item<?> argument, Class<? extends DataObject> parent) {
+        val ref = Types.typeForClass(argument.type);
+        val qname = typeToSchemaNode.get(ref).QName
+        return new NodeIdentifier(qname);
+    }
+
+    def Map<QName, Object> toPredicates(Object identifier, ListSchemaNode node) {
+        val keyDefinitions = node.keyDefinition;
+        val map = new HashMap<QName, Object>();
+        for (keydef : keyDefinitions) {
+            val keyNode = node.getDataChildByName(keydef) as LeafSchemaNode;
+            val value = identifier.getSimpleValue(keydef, keyNode.type);
+            map.put(keydef, value.value);
+        }
+        return map;
+    }
+
+    def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
+        for (entry : map.entrySet) {
+            val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
+            typeToDefinition.put(entry.value, entry.value);
+            typeToSchemaNode.put(entry.value, schemaNode)
+        }
+    }
+
+    def CompositeNode toCompositeNode(DataContainer data) {
+        val type = data.implementedInterface;
+        val typeRef = Types.typeForClass(type);
+        val schemaNode = typeToSchemaNode.get(typeRef);
+        val generatedType = typeToDefinition.get(typeRef);
+
+        return data.toDataDom(schemaNode, generatedType);
+    }
+
+    private def dispatch CompositeNode toDataDom(DataContainer data, ContainerSchemaNode node,
+        GeneratedTypeBuilder builder) {
+        val subnodes = data.toDataDomComponents(node);
+        return new CompositeNodeTOImpl(node.QName, null, subnodes);
+    }
+
+    private def dispatch CompositeNode toDataDom(DataContainer data, NotificationDefinition node,
+        GeneratedTypeBuilder builder) {
+        val subnodes = data.toDataDomComponents(node);
+        return new CompositeNodeTOImpl(node.QName, null, subnodes);
+    }
+
+    private def dispatch CompositeNode toDataDom(DataContainer data, ListSchemaNode node,
+        GeneratedTypeBuilder builder) {
+        val subnodes = data.toDataDomComponents(node);
+        return new CompositeNodeTOImpl(node.QName, null, subnodes);
+    }
+
+    private def List<Node<?>> toDataDomComponents(DataContainer data, DataNodeContainer node) {
+        val subnodes = new ArrayList<Node<?>>();
+        for (childNode : node.childNodes) {
+            val value = childNode.dataDomFromParent(data);
+            if (value !== null) {
+                subnodes.addAll(value);
+            }
+        }
+        return subnodes;
+    }
+
+    private def List<Node<?>> dataDomFromParent(DataSchemaNode node, DataContainer container) {
+        if (node.augmenting) {
+            return Collections.emptyList();
+        }
+        return dataDomFromParentImpl(node, container);
+    }
+
+    private def dispatch List<Node<?>> dataDomFromParentImpl(LeafSchemaNode node, DataContainer container) {
+        val value = container.getSimpleValue(node.QName, node.type);
+        if (value !== null) {
+            return Collections.<Node<?>>singletonList(value);
+        }
+        return Collections.emptyList();
+    }
+
+    private def dispatch List<Node<?>> dataDomFromParentImpl(LeafListSchemaNode node, DataContainer container) {
+        val values = container.getSimpleValues(node);
+        if (values !== null) {
+            //val it = new ArrayList<Node<?>>();
+            //for (value : values) {
+            //}
+
+        }
+        return Collections.emptyList();
+    }
+
+    def getSimpleValues(DataContainer container, LeafListSchemaNode node) {
+        return Collections.emptyList();
+    }
+
+    private def dispatch List<Node<?>> dataDomFromParentImpl(ListSchemaNode node, DataContainer container) {
+        val qname = node.QName;
+        val values = container.<List>getValue(qname, List) as List<? extends DataContainer>;
+        if (values === null) {
+            return Collections.emptyList;
+        }
+        val it = new ArrayList<Node<?>>();
+        for (value : values) {
+            add(value.toCompositeNode());
+        }
+
+        return it;
+    }
+
+    private def dispatch List<Node<?>> dataDomFromParentImpl(ChoiceNode node, DataContainer container) {
+    }
+
+    private def dispatch List<Node<?>> serializeValueImpl(List<?> list, GeneratedTypeBuilder builder,
+        ListSchemaNode node) {
+        val it = new ArrayList<Node<?>>();
+        for (value : list) {
+
+            val serVal = value.serializeValueImpl(builder, node);
+            if (serVal !== null) {
+                addAll(serVal);
+            }
+        }
+        return it;
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, ExtendedType type) {
+        getSimpleValue(container, name, type.baseType);
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, StringTypeDefinition type) {
+        val value = container.getValue(name, String);
+        if(value === null) return null;
+        return new SimpleNodeTOImpl(name, null, value);
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, TypeDefinition<?> type) {
+        val value = container.getValue(name, Object);
+        if(value === null) return null;
+        return new SimpleNodeTOImpl(name, null, value);
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, BooleanTypeDefinition type) {
+        val value = container.getValue(name, Boolean);
+        if(value === null) return null;
+        return new SimpleNodeTOImpl(name, null, value);
+    }
+
+    private def dispatch Node<?> getSimpleValue(Object container, QName name, BinaryTypeDefinition type) {
+        val Object value = container.getValue(name, Object); //Constants.BYTES_CLASS);
+        if(value === null) return null;
+        return new SimpleNodeTOImpl(name, null, value);
+    }
+
+    private def <T> T getValue(Object object, QName node, Class<T> type) {
+        val methodName = BindingGeneratorImpl.getterMethodName(node.localName, Types.typeForClass(type));
+        var clz = object.class;
+        if (object instanceof DataContainer) {
+            clz = (object as DataContainer).implementedInterface;
+        }
+        val method = clz.getMethod(methodName);
+        if (method === null) {
+            return null;
+        }
+        val value = method.invoke(object);
+        if (value === null) {
+            return null;
+        }
+        if (type.isAssignableFrom(value.class)) {
+            return value  as T;
+        }
+        return value.getEncapsulatedValue(type);
+    }
+
+    private def <T> T getEncapsulatedValue(Object value, Class<T> type) {
+        val method = value.class.getMethod("getValue");
+        if (method !== null && type.isAssignableFrom(method.returnType)) {
+            return method.invoke(value) as T;
+        }
+        return null;
+    }
+
+    private def dispatch List<Node<?>> serializeValueImpl(DataContainer data, GeneratedTypeBuilder builder,
+        SchemaNode node) {
+        return Collections.<Node<?>>singletonList(data.toDataDom(node, builder));
+    }
+
+    private def dispatch List<Node<?>> serializeValueImpl(Object object, GeneratedTypeBuilder builder,
+        SchemaNode node) {
+    }
+
+    def DataObject toDataObject(CompositeNode node, ClassLoader loader, GeneratedType type, SchemaNode schema) {
+
+        // Nasty reflection hack (for now)
+        val builderClass = loader.loadClass(type.builderFQN);
+        val builder = builderClass.newInstance;
+        val buildMethod = builderClass.getMethod("build");
+
+        node.fillDataObject(builder, loader, type, schema);
+
+        return buildMethod.invoke(builder) as DataObject;
+    }
+
+    def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
+        ListSchemaNode schema) {
+
+        if (schema.keyDefinition !== null && !schema.keyDefinition.empty) {
+
+            val value = node.keyToBindingKey(loader, type, schema);
+            builder.setProperty("key", value);
+        }
+    }
+
+    def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
+        ContainerSchemaNode schema) {
+    }
+
+    
+    def Object keyToBindingKey(CompositeNode node, ClassLoader loader, GeneratedType type, ListSchemaNode schema) {
+        val keyClass = loader.loadClass(type.keyFQN);
+        val constructor = keyClass.constructors.get(0);
+        val keyType = type.keyTypeProperties;
+        val args = new ArrayList();
+        for (key : schema.keyDefinition) {
+            val keyProperty = keyType.get(BindingGeneratorUtil.parseToClassName(key.localName));
+            val domKeyValue = node.getFirstSimpleByName(key);
+            val keyValue = domKeyValue.deserializeSimpleValue(loader, keyProperty.returnType,
+                schema.getDataChildByName(key));
+            args.add(keyValue);
+        }
+        return ClassLoaderUtils.construct(constructor, args);
+    }
+
+    def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        LeafSchemaNode node2) {
+        deserializeSimpleValueImpl(node, loader, type, node2.type);
+    }
+
+    def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        LeafListSchemaNode node2) {
+        deserializeSimpleValueImpl(node, loader, type, node2.type);
+    }
+
+    def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        ExtendedType definition) {
+        deserializeSimpleValueImpl(node, loader, type, definition.baseType);
+    }
+
+    def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        StringTypeDefinition definition) {
+        if (type instanceof GeneratedTransferObject) {
+            val cls = loader.getClassForType(type);
+            val const = cls.getConstructor(String);
+            val str = String.valueOf(node.value);
+            return const.newInstance(str);
+        }
+        return node.value;
+    }
+
+    def Class<?> getClassForType(ClassLoader loader, Type type) {
+        loader.loadClass(type.fullyQualifiedName);
+    }
+
+    def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+        TypeDefinition definition) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    def Map<String, GeneratedProperty> getKeyTypeProperties(GeneratedType type) {
+        val method = FluentIterable.from(type.methodDefinitions).findFirst[name == "getKey"]
+        val key = method.returnType as GeneratedTransferObject;
+        val ret = new HashMap<String, GeneratedProperty>();
+        for (prop : key.properties) {
+            ret.put(prop.name, prop);
+        }
+        return ret;
+    }
+
+    def void setProperty(Object object, String property, Object value) {
+        val cls = object.class;
+        val valMethod = cls.getMethod("set" + property.toFirstUpper, value.class);
+        if (valMethod != null)
+            valMethod.invoke(object, value);
+    }
+
+    def String getBuilderFQN(Type type) '''«type.fullyQualifiedName»Builder'''
+
+    def String getKeyFQN(Type type) '''«type.fullyQualifiedName»Key'''
+
+}
+
+@Data
+class PropertyCapture {
+
+    @Property
+    val Type returnType;
+    @Property
+    val String name;
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java
new file mode 100644 (file)
index 0000000..c96835b
--- /dev/null
@@ -0,0 +1,73 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class ConnectorActivator implements Provider, ServiceTrackerCustomizer<Broker, Broker> {
+
+    BindingIndependentDataServiceConnector dataConnector;
+    BindingIndependentMappingService mappingService;
+
+    private final DataProviderService baDataService;
+    private BundleContext context;
+
+    private ServiceTracker<Broker, Broker> brokerTracker;
+
+    public ConnectorActivator(DataProviderService dataService, BundleContext context) {
+        baDataService = dataService;
+        this.context = context;
+        brokerTracker = new ServiceTracker<>(context, Broker.class, this);
+    }
+
+    @Override
+    public Collection<ProviderFunctionality> getProviderFunctionality() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+
+        MappingServiceImpl mappingImpl = new MappingServiceImpl();
+        mappingImpl.setSchemaService(session.getService(SchemaService.class));
+        mappingImpl.start();
+
+        mappingService = mappingImpl;
+        dataConnector = new BindingIndependentDataServiceConnector();
+        dataConnector.setBaDataService(baDataService);
+        dataConnector.setBiDataService(session.getService(DataBrokerService.class));
+        dataConnector.setMappingService(mappingService);
+        dataConnector.start();
+    }
+
+    @Override
+    public Broker addingService(ServiceReference<Broker> reference) {
+        Broker br= context.getService(reference);
+        br.registerProvider(this, context);
+        return br;
+    }
+
+    @Override
+    public void modifiedService(ServiceReference<Broker> reference, Broker service) {
+        // NOOP
+    }
+
+    @Override
+    public void removedService(ServiceReference<Broker> reference, Broker service) {
+        // NOOP
+    }
+
+    public void start() {
+        brokerTracker.open();
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/Constants.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/Constants.java
new file mode 100644 (file)
index 0000000..1c9a59d
--- /dev/null
@@ -0,0 +1,5 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+public class Constants {
+    public static final Class<byte[]> BYTES_CLASS = byte[].class;
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend
new file mode 100644 (file)
index 0000000..84a0065
--- /dev/null
@@ -0,0 +1,68 @@
+package org.opendaylight.controller.sal.binding.impl.connect.dom
+
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import java.util.Collections
+import java.util.Map.Entry
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import java.util.AbstractMap.SimpleEntry
+import org.opendaylight.controller.sal.core.api.model.SchemaService
+
+class MappingServiceImpl implements SchemaServiceListener, BindingIndependentMappingService {
+
+    var extension BindingMapping mapping = new BindingMapping;
+
+    @Property
+    BindingGeneratorImpl binding;
+
+    @Property
+    SchemaService schemaService;
+
+    override onGlobalContextUpdated(SchemaContext arg0) {
+        recreateBindingContext(arg0);
+    }
+
+    def recreateBindingContext(SchemaContext schemaContext) {
+        val newBinding = new BindingGeneratorImpl();
+        newBinding.generateTypes(schemaContext);
+        val newMapping = new BindingMapping();
+        for (entry : newBinding.moduleContexts.entrySet) {
+            val module = entry.key;
+            val context = entry.value;
+            
+            newMapping.updateBinding(schemaContext, context);
+        }
+        mapping = newMapping
+    }
+
+    override CompositeNode toDataDom(DataObject data) {
+        mapping.toCompositeNode(data);
+    }
+
+    override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+        Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
+        val key = mapping.toDataDom(entry.key);
+        val data = mapping.toCompositeNode(entry.value);
+        return new SimpleEntry(key, data);
+    }
+
+    override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
+        InstanceIdentifier<? extends DataObject> path) {
+        return mapping.toDataDom(path);
+    }
+    
+    override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) {
+        return mapping.dataObjectFromDataDom(path,result);
+    }
+    
+    public def void start() {
+        schemaService.registerSchemaServiceListener(this);
+        recreateBindingContext(schemaService.globalContext);
+    }
+}
@@ -1,10 +1,17 @@
-package org.opendaylight.controller.sal.binding.impl.osgi;
+package org.opendaylight.controller.sal.binding.impl.util;
 
 
 
 import java.util.concurrent.Callable;
+
 import static com.google.common.base.Preconditions.*;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
 public class ClassLoaderUtils {
     
     public static <V> V withClassLoader(ClassLoader cls,Callable<V> function) throws Exception {
@@ -21,4 +28,9 @@ public class ClassLoaderUtils {
             throw new Exception(e);
         }
     }
+
+    public static Object construct(Constructor<? extends Object> constructor, ArrayList<Object> objects) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+    Object[] initargs = objects.toArray(new Object[]{});
+    return constructor.newInstance(initargs);
+    }
 }
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java
new file mode 100644 (file)
index 0000000..0448238
--- /dev/null
@@ -0,0 +1,136 @@
+package org.opendaylight.controller.sal.binding.test.connect.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public class BrokerIntegrationTest {
+
+    DataBrokerService biDataService;
+    DataProviderService baDataService;
+    private MappingServiceImpl mappingServiceImpl;
+    private MappingServiceImpl mappingService;
+    private DataBrokerImpl baDataImpl;
+    private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
+    private ListeningExecutorService executor;
+    private BindingIndependentDataServiceConnector connectorServiceImpl;
+    private HashMapDataStore dataStore;
+    
+    
+    @Before
+    public void setUp() {
+        executor = MoreExecutors.sameThreadExecutor();
+        baDataImpl = new DataBrokerImpl();
+        baDataService = baDataImpl;
+        baDataImpl.setExecutor(executor);
+        
+        biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
+        biDataService =  biDataImpl;
+        biDataImpl.setExecutor(executor);
+        
+        dataStore = new HashMapDataStore();
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder().toInstance();
+        biDataImpl.registerConfigurationReader(treeRoot, dataStore);
+        biDataImpl.registerOperationalReader(treeRoot, dataStore);
+        biDataImpl.registerCommitHandler(treeRoot, dataStore);
+        
+        mappingServiceImpl = new MappingServiceImpl();
+        mappingService = mappingServiceImpl;
+        
+        
+        connectorServiceImpl = new BindingIndependentDataServiceConnector();
+        connectorServiceImpl.setBaDataService(baDataService);
+        connectorServiceImpl.setBiDataService(biDataService);
+        connectorServiceImpl.setMappingService(mappingServiceImpl);
+        connectorServiceImpl.start();
+        
+        String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
+        "node-inventory.yang" };
+        
+        mappingService.onGlobalContextUpdated(MappingServiceTest.getContext(yangFiles));
+    }
+    
+    @Test
+    public void simpleModifyOperation() throws Exception {
+        
+        DataModificationTransaction transaction = baDataService.beginTransaction();
+        assertNotNull(transaction);
+        
+        NodeRef node1 = createNodeRef("0");
+        DataObject  node = baDataService.readConfigurationData(node1.getValue());
+        assertNull(node);
+        Node nodeData1 = createNode("0");
+        
+        transaction.putConfigurationData(node1.getValue(), nodeData1);
+        Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
+        assertNotNull(commitResult);
+        
+        RpcResult<TransactionStatus> result = commitResult.get();
+        
+        assertNotNull(result);
+        assertNotNull(result.getResult());
+        assertEquals(TransactionStatus.COMMITED, result.getResult());
+        
+        Node readedData = (Node) baDataService.readConfigurationData(node1.getValue());
+        assertNotNull(readedData);
+        assertEquals(nodeData1.getKey(), readedData.getKey());
+        
+        
+        DataModificationTransaction transaction2 = baDataService.beginTransaction();
+        assertNotNull(transaction);
+        
+        transaction2.removeConfigurationData(node1.getValue());
+        
+        Future<RpcResult<TransactionStatus>> commitResult2 = transaction2.commit();
+        assertNotNull(commitResult2);
+        
+        RpcResult<TransactionStatus> result2 = commitResult2.get();
+        
+        assertNotNull(result2);
+        assertNotNull(result2.getResult());
+        assertEquals(TransactionStatus.COMMITED, result2.getResult());
+    
+        DataObject readedData2 = baDataService.readConfigurationData(node1.getValue());
+        assertNull(readedData2);
+    }
+    
+    private static NodeRef createNodeRef(String string) {
+        NodeKey key = new NodeKey(new NodeId(string));
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
+                .toInstance();
+        return new NodeRef(path);
+    }
+    
+    private static Node createNode(String string) {
+        NodeBuilder ret = new NodeBuilder();
+        ret.setId(new NodeId(string));
+        ret.setKey(new NodeKey(ret.getId()));
+        return ret.build();
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java
new file mode 100644 (file)
index 0000000..b0c2e75
--- /dev/null
@@ -0,0 +1,118 @@
+package org.opendaylight.controller.sal.binding.test.connect.dom;
+
+import static org.junit.Assert.*;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class MappingServiceTest {
+
+    private static final QName NODES = QName.create("urn:opendaylight:inventory", "2013-08-19", "nodes");
+    private static final QName NODE = QName.create(NODES,"node");
+    private static final QName ID = QName.create(NODES,"id");
+    
+    BindingIndependentMappingService service;
+    private MappingServiceImpl impl;
+
+    @Before
+    public void setUp() {
+        impl = new MappingServiceImpl();
+        service = impl;
+    }
+
+    @Test
+    public void baDataToBiData() throws Exception {
+
+        String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
+                "node-inventory.yang" };
+
+        SchemaContext ctx = getContext(yangFiles);
+
+        impl.onGlobalContextUpdated(ctx);
+
+        NodesBuilder nodes = new NodesBuilder();
+
+        List<Node> nodeList = new ArrayList<>();
+        nodeList.add(createChildNode("foo"));
+        nodeList.add(createChildNode("bar"));
+
+        nodes.setNode(nodeList);
+        Nodes nodesTO = nodes.build();
+        CompositeNode xmlNodes = service.toDataDom(nodesTO);
+        assertNotNull(xmlNodes);
+        List<CompositeNode> invNodes = xmlNodes.getCompositesByName(NODE);
+        assertNotNull(invNodes);
+        assertEquals(2, invNodes.size());
+    }
+
+    @Test
+    public void instanceIdentifierTest() throws Exception {
+
+        String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
+                "node-inventory.yang" };
+        SchemaContext ctx = getContext(yangFiles);
+        impl.onGlobalContextUpdated(ctx);
+
+        NodeKey nodeKey = new NodeKey(new NodeId("foo"));
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).child(Node.class, nodeKey).toInstance();
+        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier result = service.toDataDom(path);
+        assertNotNull(result);
+        assertEquals(2, result.getPath().size());
+    }
+
+    public static SchemaContext getContext(String[] yangFiles) {
+
+        ClassLoader loader = MappingServiceTest.class.getClassLoader();
+
+        List<InputStream> streams = new ArrayList<>();
+        for (String string : yangFiles) {
+            InputStream stream = loader.getResourceAsStream("META-INF/yang/" + string);
+            streams.add(stream);
+
+        }
+        YangParserImpl parser = new YangParserImpl();
+
+        Set<Module> modules = parser.parseYangModelsFromStreams(streams);
+        return parser.resolveSchemaContext(modules);
+    }
+
+    private Node createChildNode(String id) {
+        NodeBuilder node = new NodeBuilder();
+        NodeId nodeId = new NodeId(id);
+
+        node.setId(nodeId);
+        node.setKey(new NodeKey(nodeId));
+
+        FlowCapableNodeBuilder aug = new FlowCapableNodeBuilder();
+        aug.setManufacturer(id);
+        node.addAugmentation(FlowCapableNode.class, aug.build());
+
+        return node.build();
+    }
+
+}
index a20491b6bea6b1371514bd30267728fdd7acbff5..e242b9ecee2c3e8f9cc8ff1d9b777a036d1f07eb 100644 (file)
       <version>1.0-SNAPSHOT</version>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+            <version>4.0</version>
+    </dependency>
   </dependencies>
 </project>
index 3e3ee3a8742e1af5ca3a14a30382217064e1d931..2f9c397632795d334799f32030be734fe38ae113 100644 (file)
@@ -25,6 +25,7 @@ public class TestHelper {
                 mavenBundle(CONTROLLER, "sal-common-api").versionAsInProject(), //
                 mavenBundle(CONTROLLER, "sal-common-impl").versionAsInProject(), //
                 
+                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
                 mavenBundle("com.google.guava", "guava").versionAsInProject(), //
                 mavenBundle(YANGTOOLS + ".thirdparty", "xtend-lib-osgi").versionAsInProject() //
         );
@@ -44,8 +45,32 @@ public class TestHelper {
                 mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(),
                 mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), //
                 mavenBundle("org.javassist", "javassist").versionAsInProject(), //
-                mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject() //
-        );
+                mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), //
+        
+                mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+                
+                
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
+                
+                
+                mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
+                mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
+                
+                mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject() //
+       );
 
     }
 
index 4057d9d1bc0ec3807b85754764bbbc108dc095a6..41b1e310a06e6812d954cee64e7db3c895e8f996 100644 (file)
@@ -11,6 +11,7 @@ import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.options.DefaultCompositeOption;
+import org.ops4j.pax.exam.util.PathUtils;
 import org.osgi.framework.BundleContext;
 
 @RunWith(PaxExam.class)
@@ -48,6 +49,9 @@ public abstract class AbstractTest {
     public Option[] config() {
         return options(systemProperty("osgi.console").value("2401"), mavenBundle("org.slf4j", "slf4j-api")
                 .versionAsInProject(), //
+                systemProperty("logback.configurationFile").value(
+                        "file:" + PathUtils.getBaseDir()
+                                + "/src/test/resources/logback.xml"),
                 mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
                 mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
                 mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
index d26f2e7aa161fe4dbb247f301db414cfa703c4ff..e1f109b88dc2e923f8580b47e57c1795cc50d947 100644 (file)
@@ -11,6 +11,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
 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.controller.sal.core.api.Broker;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -21,9 +22,15 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
+import com.google.inject.Inject;
+
 public class DataServiceTest extends AbstractTest {
 
     protected DataBrokerService consumerDataService;
+    
+    
+    @Inject
+    Broker broker2;
 
     @Before
     public void setUp() throws Exception {
@@ -61,9 +68,9 @@ public class DataServiceTest extends AbstractTest {
         assertNotNull(result.getResult());
         assertEquals(TransactionStatus.COMMITED, result.getResult());
         
-        DataObject readedData = consumerDataService.readConfigurationData(node1.getValue());
+        Node readedData = (Node) consumerDataService.readConfigurationData(node1.getValue());
         assertNotNull(readedData);
-        assertEquals(nodeData1, readedData);
+        assertEquals(nodeData1.getKey(), readedData.getKey());
         
         
         DataModificationTransaction transaction2 = consumerDataService.beginTransaction();
@@ -97,7 +104,9 @@ public class DataServiceTest extends AbstractTest {
     
     private static Node createNode(String string) {
         NodeBuilder ret = new NodeBuilder();
-        ret.setId(new NodeId(string));
+        NodeId id = new NodeId(string);
+        ret.setKey(new NodeKey(id));
+        ret.setId(id);
         return ret.build();
     }
 }
index 3bd51ec7d8b68dabe567857101a098cf2d2f4928..7fb05806df36f1925a936fb49615212f64339a8d 100644 (file)
@@ -1,50 +1,59 @@
 <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-common-impl</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>
+    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-common-impl</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>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-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>
-  </dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+    </dependencies>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <configuration>
-          <instructions>
-            <Export-Package>
-                org.opendaylight.controller.md.sal.common.impl,
-                org.opendaylight.controller.md.sal.common.impl.*
-            </Export-Package>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.opendaylight.controller.md.sal.common.impl,
+                            org.opendaylight.controller.md.sal.common.impl.*
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
index c335b75e15981989078fa862ad31b88dd70d4e04..c9e1d6e330e38324f21e26b510cb548f5298a562 100644 (file)
@@ -1,8 +1,8 @@
 package org.opendaylight.controller.md.sal.common.impl;
 
+import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.NEW;
+
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -10,9 +10,6 @@ import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.yangtools.concepts.Path;
-
-import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.NEW;
 
 public abstract class AbstractDataModification<P /* extends Path<P> */, D> implements DataModification<P, D> {
 
@@ -86,7 +83,7 @@ public abstract class AbstractDataModification<P /* extends Path<P> */, D> imple
 
     @Override
     public final void putRuntimeData(P path, D data) {
-        putRuntimeData(path, data);
+        putOperationalData(path, data);
     }
 
     @Override
index 531ce224e6a02867a8fe6b71ae565fef1f7b9b0b..d6b3c5334aa1c4d02563d51cef0a0d27d8939c61 100644 (file)
@@ -35,7 +35,7 @@ public abstract class AbstractDataReadRouter<P extends Path<?>, D> implements Da
     @Override
     public D readOperationalData(P path) {
         FluentIterable<D> dataBits = FluentIterable //
-                .from(getReaders(configReaders, path)).transform(operationalRead(path));
+                .from(getReaders(operationalReaders, path)).transform(operationalRead(path));
         return merge(path,dataBits);
 
     }
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend
new file mode 100644 (file)
index 0000000..b878071
--- /dev/null
@@ -0,0 +1,259 @@
+package org.opendaylight.controller.md.sal.common.impl.service
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
+import org.opendaylight.yangtools.concepts.ListenerRegistration
+import com.google.common.collect.Multimap
+import static com.google.common.base.Preconditions.*;
+import java.util.List
+import com.google.common.collect.HashMultimap
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Callable
+import org.opendaylight.yangtools.yang.common.RpcResult
+import java.util.Collections
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
+import java.util.ArrayList
+import org.opendaylight.yangtools.concepts.CompositeObjectRegistration
+import java.util.Arrays
+import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService
+import org.opendaylight.controller.md.sal.common.api.data.DataModificationTransactionFactory
+import org.opendaylight.controller.md.sal.common.api.data.DataChangePublisher
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener
+import org.opendaylight.controller.sal.common.util.Rpcs
+import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification
+import java.util.concurrent.Future
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
+import org.opendaylight.yangtools.concepts.Path
+import org.slf4j.LoggerFactory
+
+abstract class AbstractDataBroker<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> implements 
+DataModificationTransactionFactory<P, D>, //
+DataReader<P, D>, //
+DataChangePublisher<P, D, DCL>, //
+DataProvisionService<P,D> {
+
+    @Property
+    var ExecutorService executor;
+
+    @Property
+    var AbstractDataReadRouter<P,D> dataReadRouter;
+
+    Multimap<P, DataChangeListenerRegistration<P,D,DCL>> listeners = HashMultimap.create();
+    Multimap<P, DataCommitHandlerRegistration<P,D>> commitHandlers = HashMultimap.create();
+
+
+    public new() {
+        
+    }
+
+    override final readConfigurationData(P path) {
+        return dataReadRouter.readConfigurationData(path);
+    }
+
+    override final readOperationalData(P path) {
+        return dataReadRouter.readOperationalData(path);
+    }
+
+    override final registerCommitHandler(P path,
+        DataCommitHandler<P, D> commitHandler) {
+            val registration = new DataCommitHandlerRegistration(path,commitHandler,this);
+            commitHandlers.put(path,registration)
+            return registration;
+    }
+
+    override final def registerDataChangeListener(P path, DCL listener) {
+        val reg = new DataChangeListenerRegistration(path, listener, this);
+        listeners.put(path, reg);
+        return reg;
+    }
+
+     final def registerDataReader(P path,DataReader<P,D> reader) {
+        
+        val confReg = dataReadRouter.registerConfigurationReader(path,reader);
+        val dataReg = dataReadRouter.registerOperationalReader(path,reader);
+        
+        return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg));
+    }
+
+    protected  final def removeListener(DataChangeListenerRegistration<P,D,DCL> registration) {
+        listeners.remove(registration.path, registration);
+    }
+
+    protected  final def removeCommitHandler(DataCommitHandlerRegistration<P,D> registration) {
+        commitHandlers.remove(registration.path, registration);
+    }
+    
+    protected  final def getActiveCommitHandlers() {
+        return commitHandlers.entries.map[ value.instance].toSet
+    }
+
+    package final def Future<RpcResult<TransactionStatus>>  commit(AbstractDataTransaction<P,D> transaction) {
+        checkNotNull(transaction);
+        transaction.changeStatus(TransactionStatus.SUBMITED);
+        val task = new TwoPhaseCommit(transaction, this);
+        return executor.submit(task);
+    }
+
+}
+
+package class DataChangeListenerRegistration<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> extends AbstractObjectRegistration<DCL> implements ListenerRegistration<DCL> {
+
+    AbstractDataBroker<P,D,DCL> dataBroker;
+
+    @Property
+    val P path;
+
+    new(P path, DCL instance, AbstractDataBroker<P,D,DCL> broker) {
+        super(instance)
+        dataBroker = broker;
+        _path = path;
+    }
+
+    override protected removeRegistration() {
+        dataBroker.removeListener(this);
+        dataBroker = null;
+    }
+
+}
+
+package class DataCommitHandlerRegistration<P extends Path<P>,D>
+extends AbstractObjectRegistration<DataCommitHandler<P, D>> {
+
+    AbstractDataBroker<P,D,?> dataBroker;
+
+    @Property
+    val P path;
+
+    new(P path, DataCommitHandler<P, D> instance,
+        AbstractDataBroker<P,D,?> broker) {
+        super(instance)
+        dataBroker = broker;
+        _path = path;
+    }
+
+    override protected removeRegistration() {
+        dataBroker.removeCommitHandler(this);
+        dataBroker = null;
+    }
+
+}
+
+package class TwoPhaseCommit<P extends Path<P>,D> implements Callable<RpcResult<TransactionStatus>> {
+    
+    private static val log = LoggerFactory.getLogger(TwoPhaseCommit);
+
+    val AbstractDataTransaction<P,D> transaction;
+    val AbstractDataBroker<P,D,?> dataBroker;
+
+    new(AbstractDataTransaction<P,D> transaction, AbstractDataBroker<P,D,?> broker) {
+        this.transaction = transaction;
+        this.dataBroker = broker;
+    }
+
+    override call() throws Exception {
+
+        val Iterable<DataCommitHandler<P, D>> commitHandlers = dataBroker.activeCommitHandlers;
+
+        // requesting commits
+        val List<DataCommitTransaction<P, D>> handlerTransactions = new ArrayList();
+        try {
+            for (handler : commitHandlers) {
+                handlerTransactions.add(handler.requestCommit(transaction));
+            }
+        } catch (Exception e) {
+            log.error("Request Commit failded",e);
+            return rollback(handlerTransactions,e);
+        }
+        val List<RpcResult<Void>> results = new ArrayList();
+        try {
+            for (subtransaction : handlerTransactions) {
+                results.add(subtransaction.finish());
+            }
+        } catch (Exception e) {
+            log.error("Finish Commit failed",e);
+            return rollback(handlerTransactions,e);
+        }
+
+        return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
+    }
+
+    def rollback(List<DataCommitTransaction<P, D>> transactions,Exception e) {
+        for (transaction : transactions) {
+            transaction.rollback()
+        }
+        // FIXME return encountered error.
+        return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
+    }
+}
+
+public abstract class AbstractDataTransaction<P extends Path<P>, D> extends AbstractDataModification<P, D> {
+
+    @Property
+    private val Object identifier;
+
+    
+    var TransactionStatus status;
+    
+    
+    var AbstractDataBroker<P, D, ?> broker;
+
+    protected new (AbstractDataBroker<P,D,?> dataBroker) {
+        super(dataBroker);
+        _identifier = new Object();
+        broker = dataBroker;
+        status = TransactionStatus.NEW;
+        //listeners = new ListenerRegistry<>();
+    }
+
+    override  commit() {
+        return broker.commit(this);
+    }
+
+    override readConfigurationData(P path) {
+        return broker.readConfigurationData(path);
+    }
+
+    override readOperationalData(P path) {
+        return broker.readOperationalData(path);
+    }
+
+    override hashCode() {
+        return identifier.hashCode;
+    }
+
+    override equals(Object obj) {
+        if (this === obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        val other = (obj as AbstractDataTransaction<P,D>) ;
+        if (broker == null) {
+            if (other.broker != null)
+                return false;
+        } else if (!broker.equals(other.broker))
+            return false;
+        if (identifier == null) {
+            if (other.identifier != null)
+                return false;
+        } else if (!identifier.equals(other.identifier))
+            return false;
+        return true;
+    }
+
+    override TransactionStatus getStatus() {
+        return status;
+    }
+
+    
+    protected abstract def void onStatusChange(TransactionStatus status);
+    
+    public def changeStatus(TransactionStatus status) {
+        this.status = status;
+        onStatusChange(status);
+    }
+    
+}
index f92d86af91b46ba1f072fac794511e07f26ec97b..62dbe16e4135de42001f6fde721799128b8dbebd 100644 (file)
             <artifactId>sal-common-util</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-impl</artifactId>
index e49cb4bb0a7580c6905eade22b13b7ae88e3f7a5..3af645a2b8a48753b79659f58877c1044ff83394 100644 (file)
@@ -8,6 +8,8 @@ import org.opendaylight.controller.sal.core.api.data.DataProviderService;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
 import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
@@ -15,6 +17,7 @@ import org.osgi.framework.ServiceRegistration;
 
 public class BrokerActivator implements BundleActivator {
 
+    private static final InstanceIdentifier ROOT = InstanceIdentifier.builder().toInstance();
     BrokerImpl broker;
     private ServiceRegistration<Broker> brokerReg;
     private ServiceRegistration<SchemaService> schemaReg;
@@ -25,13 +28,14 @@ public class BrokerActivator implements BundleActivator {
     private MountPointManagerImpl mountService;
     private ServiceRegistration<MountService> mountReg;
     private ServiceRegistration<MountProvisionService> mountProviderReg;
+    private HashMapDataStore hashMapStore;
 
     @Override
     public void start(BundleContext context) throws Exception {
         Hashtable<String, String> emptyProperties = new Hashtable<String, String>();
         broker = new BrokerImpl();
         broker.setBundleContext(context);
-        brokerReg = context.registerService(Broker.class, broker, emptyProperties);
+        
 
         schemaService = new SchemaServiceImpl();
         schemaService.setContext(context);
@@ -40,14 +44,24 @@ public class BrokerActivator implements BundleActivator {
         schemaReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String, String>());
         
         dataService = new DataBrokerImpl();
+        dataService.setExecutor(broker.getExecutor());
+        
         dataReg = context.registerService(DataBrokerService.class, dataService, emptyProperties);
         dataProviderReg = context.registerService(DataProviderService.class, dataService, emptyProperties);
         
+        hashMapStore = new HashMapDataStore();
+        
+        dataService.registerConfigurationReader(ROOT, hashMapStore);
+        dataService.registerCommitHandler(ROOT, hashMapStore);
+        dataService.registerOperationalReader(ROOT, hashMapStore);
+        
         mountService = new MountPointManagerImpl();
         mountService.setDataBroker(dataService);
         
         mountReg = context.registerService(MountService.class, mountService, emptyProperties);
         mountProviderReg =  context.registerService(MountProvisionService.class, mountService, emptyProperties);
+        
+        brokerReg = context.registerService(Broker.class, broker, emptyProperties);
     }
 
     @Override
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java
new file mode 100644 (file)
index 0000000..d95fdcc
--- /dev/null
@@ -0,0 +1,66 @@
+package org.opendaylight.controller.sal.dom.broker;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
+import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier, CompositeNode, DataChangeListener> implements
+        DataProviderService {
+
+    public DataBrokerImpl() {
+        setDataReadRouter(new DataReaderRouter());
+    }
+
+    @Override
+    public DataTransactionImpl beginTransaction() {
+        return new DataTransactionImpl(this);
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return getDataReadRouter().registerConfigurationReader(path, reader);
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return getDataReadRouter().registerOperationalReader(path, reader);
+    }
+
+    @Deprecated
+    @Override
+    public void addValidator(DataStoreIdentifier store, DataValidator validator) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Deprecated
+    @Override
+    public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Deprecated
+    @Override
+    public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Deprecated
+    @Override
+    public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        // TODO Auto-generated method stub
+
+    }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend
deleted file mode 100644 (file)
index 8a17c83..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.opendaylight.controller.sal.dom.broker
-
-import org.opendaylight.controller.sal.core.api.data.DataProviderService
-import org.opendaylight.controller.sal.common.DataStoreIdentifier
-import org.opendaylight.controller.sal.core.api.data.DataProviderService.DataRefresher
-import org.opendaylight.controller.sal.core.api.data.DataValidator
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.controller.md.sal.common.api.data.DataReader
-
-class DataBrokerImpl implements DataProviderService {
-
-    val readRouter = new DataReaderRouter();
-
-    override addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
-        // NOOP
-    }
-
-    override addValidator(DataStoreIdentifier store, DataValidator validator) {
-        // NOOP
-    }
-
-    override beginTransaction() {
-        // NOOP
-    }
-
-    override readConfigurationData(InstanceIdentifier path) {
-        readRouter.readConfigurationData(path)
-    }
-
-    override readOperationalData(InstanceIdentifier path) {
-        readRouter.readOperationalData(path)
-    }
-
-    override registerConfigurationReader(InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
-        readRouter.registerConfigurationReader(path, reader);
-    }
-
-    override registerOperationalReader(InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
-        readRouter.registerOperationalReader(path, reader);
-    }
-
-    override removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
-        // NOOP
-    }
-
-    override removeValidator(DataStoreIdentifier store, DataValidator validator) {
-        // NOOP
-    }
-
-    override registerDataChangeListener(InstanceIdentifier path, DataChangeListener listener) {
-        // NOOP
-    }
-
-    override registerCommitHandler(InstanceIdentifier path,
-        DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
-        // NOOP
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java
new file mode 100644 (file)
index 0000000..5cb01c9
--- /dev/null
@@ -0,0 +1,31 @@
+package org.opendaylight.controller.sal.dom.broker;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class DataTransactionImpl extends AbstractDataTransaction<InstanceIdentifier, CompositeNode> 
+    implements DataModificationTransaction {
+    private final ListenerRegistry<DataTransactionListener> listeners = new ListenerRegistry<DataTransactionListener>();
+    
+    
+    
+    public DataTransactionImpl(DataBrokerImpl dataBroker) {
+        super(dataBroker);
+    }
+
+    @Override
+    public ListenerRegistration<DataTransactionListener> registerListener(DataTransactionListener listener) {
+        return listeners.register(listener);
+    }
+
+    protected void onStatusChange(TransactionStatus status) {
+        for (ListenerRegistration<DataTransactionListener> listenerRegistration : listeners) {
+            listenerRegistration.getInstance().onStatusUpdated(this, status);
+        }
+    }
+}
\ No newline at end of file
index b0c61c920f7c6ee967a9e5229a11b5c21558f8e6..fbed2ca113621c728dd00a5fa4b9ae932344d7db 100644 (file)
@@ -8,7 +8,11 @@ import org.opendaylight.controller.md.sal.common.api.data.DataReader
 class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
 
     override protected merge(InstanceIdentifier path, Iterable<CompositeNode> data) {
-        return data.iterator.next
+        val iterator = data.iterator;
+        if(iterator.hasNext) {
+            return data.iterator.next
+        }
+        return null;
     }
 
 }
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend
new file mode 100644 (file)
index 0000000..1a2f947
--- /dev/null
@@ -0,0 +1,50 @@
+package org.opendaylight.controller.sal.dom.broker.impl
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import java.util.Map
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import java.util.Map.Entry
+import java.util.HashSet
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+
+class DataUtils {
+
+    static def CompositeNode read(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
+        val root = map.get(path);
+        val childs = map.getChilds(path);
+        if(root === null && childs.empty) {
+            return null;
+        }
+        
+        return merge(path, root, childs);
+    }
+
+    static def CompositeNode merge(InstanceIdentifier path, CompositeNode node,
+        HashSet<Entry<InstanceIdentifier, CompositeNode>> entries) {
+        val it = new ArrayList<Node<?>>();
+        val qname = path.path.last.nodeType;
+        if (node != null) {
+            addAll(node.children);
+        }
+        for (entry : entries) {
+            val nesting = entry.key.path.size - path.path.size;
+            if (nesting === 1) {
+                add(entry.value);
+            }
+        }
+        return new CompositeNodeTOImpl(qname, null, it);
+    }
+
+    static def getChilds(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
+        val it = new HashSet<Entry<InstanceIdentifier, CompositeNode>>();
+        for (entry : map.entrySet) {
+            if (path.contains(entry.key)) {
+                add(entry);
+            }
+        }
+        return it;
+    }
+
+}
@@ -1,10 +1,7 @@
-package org.opendaylight.controller.sal.binding.impl
+package org.opendaylight.controller.sal.dom.broker.impl
 
 import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.controller.md.sal.common.api.data.DataModification
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
 import org.opendaylight.yangtools.yang.common.RpcResult
@@ -12,58 +9,62 @@ import java.util.Map
 import java.util.concurrent.ConcurrentHashMap
 import org.opendaylight.controller.sal.common.util.Rpcs
 import java.util.Collections
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import static extension org.opendaylight.controller.sal.dom.broker.impl.DataUtils.*;
 
 class HashMapDataStore //
 implements //
-RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+DataReader<InstanceIdentifier, CompositeNode>, DataCommitHandler<InstanceIdentifier, CompositeNode> {
 
-    val Map<InstanceIdentifier<? extends DataObject>,DataObject> configuration = new ConcurrentHashMap();
-    val Map<InstanceIdentifier<? extends DataObject>,DataObject> operational = new ConcurrentHashMap();
+    val Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap();
+    val Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap();
 
-
-    override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
-        configuration.get(path);
+    override readConfigurationData(InstanceIdentifier path) {
+        configuration.read(path);
     }
 
-    override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
-        operational.get(path);
+    override readOperationalData(InstanceIdentifier path) {
+        operational.read(path);
     }
+    
+
 
-    override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-        return new HashMapDataStoreTransaction(modification,this);
+
+    override requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
+        return new HashMapDataStoreTransaction(modification, this);
     }
-    
+
     def RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
-        return Rpcs.getRpcResult(true,null,Collections.emptySet);
+        return Rpcs.getRpcResult(true, null, Collections.emptySet);
     }
-    
+
     def RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
         val modification = transaction.modification;
         configuration.putAll(modification.updatedConfigurationData);
         operational.putAll(modification.updatedOperationalData);
-        
-        for(removal : modification.removedConfigurationData) {
+
+        for (removal : modification.removedConfigurationData) {
             configuration.remove(removal);
         }
-        for(removal : modification.removedOperationalData) {
+        for (removal : modification.removedOperationalData) {
             operational.remove(removal);
         }
-        return Rpcs.getRpcResult(true,null,Collections.emptySet);
+        return Rpcs.getRpcResult(true, null, Collections.emptySet);
     }
 
 }
 
 class HashMapDataStoreTransaction implements // 
-DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+DataCommitTransaction<InstanceIdentifier, CompositeNode> {
     @Property
-    val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification
+    val DataModification<InstanceIdentifier, CompositeNode> modification
 
     @Property
     val HashMapDataStore datastore;
-    
-    
+
     new(
-        DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modify,
+        DataModification<InstanceIdentifier, CompositeNode> modify,
         HashMapDataStore store
     ) {
         _modification = modify;
index 59ec7a780b2a4665325579ad125c958d87aab16e..6ef5780c8a577c1bc93c97bd95420a50d608f5fc 100644 (file)
             <artifactId>yang-data-impl</artifactId>
             <version>0.5.9-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-broker-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+            <type>jar</type>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
     </dependencies>
 
     <packaging>bundle</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.opendaylight.controller.sal.connect.netconf.NetconfProvider</Bundle-Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/InventoryUtils.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/InventoryUtils.java
new file mode 100644 (file)
index 0000000..8350e39
--- /dev/null
@@ -0,0 +1,39 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import java.net.URI;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class InventoryUtils {
+
+    private static final URI INVENTORY_NAMESPACE = URI.create("urn:opendaylight:inventory");
+    private static final Date INVENTORY_REVISION = date();
+    public static final QName INVENTORY_NODES = new QName(INVENTORY_NAMESPACE, INVENTORY_REVISION, "nodes");
+    public static final QName INVENTORY_NODE = new QName(INVENTORY_NAMESPACE, INVENTORY_REVISION, "node");
+    public static final QName INVENTORY_ID = new QName(INVENTORY_NAMESPACE, INVENTORY_REVISION, "id");
+
+    public static final InstanceIdentifier INVENTORY_PATH = InstanceIdentifier.builder().node(INVENTORY_NODES)
+            .toInstance();
+    public static final QName NETCONF_INVENTORY_MOUNT = null;
+    
+    
+    
+    private static Date date() {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            return formatter.parse("2013-08-19");
+        } catch (ParseException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    
+    
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.xtend b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.xtend
new file mode 100644 (file)
index 0000000..0171c1f
--- /dev/null
@@ -0,0 +1,95 @@
+package org.opendaylight.controller.sal.connect.netconf
+
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.netconf.client.NetconfClient
+import org.opendaylight.controller.sal.core.api.RpcImplementation
+import static extension org.opendaylight.controller.sal.connect.netconf.NetconfMapping.*
+import java.net.InetSocketAddress
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import org.opendaylight.yangtools.yang.common.QName
+import java.util.Collections
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
+import org.opendaylight.yangtools.concepts.Registration
+
+class NetconfDevice implements DataReader<InstanceIdentifier, CompositeNode>, RpcImplementation {
+
+    var NetconfClient client;
+
+    @Property
+    var InetSocketAddress socketAddress;
+
+    @Property
+    val MountProvisionInstance mountInstance;
+
+    @Property
+    val InstanceIdentifier path;
+    
+    Registration<DataReader<InstanceIdentifier,CompositeNode>> operReaderReg
+    
+    Registration<DataReader<InstanceIdentifier,CompositeNode>> confReaderReg
+    
+    public new(MountProvisionInstance mount,InstanceIdentifier path) {
+        _mountInstance = mount;
+        _path = path;
+    }
+
+    def start(NetconfClientDispatcher dispatcher) {
+        client = new NetconfClient("sal-netconf-connector", socketAddress, dispatcher);
+        
+        confReaderReg = mountInstance.registerConfigurationReader(path,this);
+        operReaderReg = mountInstance.registerOperationalReader(path,this);
+    }
+
+    override readConfigurationData(InstanceIdentifier path) {
+        val result = invokeRpc(NETCONF_GET_CONFIG_QNAME, wrap(NETCONF_GET_CONFIG_QNAME, path.toFilterStructure()));
+        val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
+        return data?.findNode(path) as CompositeNode;
+    }
+
+    override readOperationalData(InstanceIdentifier path) {
+        val result = invokeRpc(NETCONF_GET_QNAME, wrap(NETCONF_GET_QNAME, path.toFilterStructure()));
+        val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
+        return data?.findNode(path) as CompositeNode;
+    }
+
+    override getSupportedRpcs() {
+        Collections.emptySet;
+    }
+
+    override invokeRpc(QName rpc, CompositeNode input) {
+        val message = rpc.toRpcMessage(input);
+        val result = client.sendMessage(message);
+        return result.toRpcResult();
+    }
+
+    def Node<?> findNode(CompositeNode node, InstanceIdentifier identifier) {
+
+        var Node<?> current = node;
+        for (arg : identifier.path) {
+            if (current instanceof SimpleNode<?>) {
+                return null;
+            } else if (current instanceof CompositeNode) {
+                val currentComposite = (current as CompositeNode);
+
+                current = currentComposite.getFirstCompositeByName(arg.nodeType);
+                if (current == null) {
+                    current = currentComposite.getFirstSimpleByName(arg.nodeType);
+                }
+                if (current == null) {
+                    return null;
+                }
+            }
+        }
+        return current;
+    }
+    
+    public def stop() {
+        confReaderReg?.close()
+        operReaderReg?.close()
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceManager.xtend b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceManager.xtend
new file mode 100644 (file)
index 0000000..2fe145e
--- /dev/null
@@ -0,0 +1,84 @@
+package org.opendaylight.controller.sal.connect.netconf
+
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
+import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.common.QName
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.*;
+import static extension org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils.*;
+
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent
+import java.util.Map
+import java.util.concurrent.ConcurrentHashMap
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
+import java.io.OptionalDataException
+import com.google.common.base.Optional
+import java.net.SocketAddress
+import java.net.InetSocketAddress
+
+class NetconfDeviceManager {
+
+    val Map<InstanceIdentifier, NetconfDevice> devices = new ConcurrentHashMap;
+
+    var ProviderSession session;
+
+    @Property
+    var DataProviderService dataService;
+    
+    @Property
+    var MountProvisionService mountService;
+    
+    val nodeUpdateListener = new NetconfInventoryListener(this);
+
+
+    @Property
+    var NetconfClientDispatcher dispatcher;
+
+    def void start() {
+        dataService?.registerDataChangeListener(INVENTORY_PATH, nodeUpdateListener);
+        if(dispatcher == null) {
+        dispatcher = new NetconfClientDispatcher(Optional.absent);
+        }
+    }
+
+    def netconfNodeAdded(InstanceIdentifier path, CompositeNode node) {
+        val address = node.endpointAddress;
+        val port = Integer.parseInt(node.endpointPort);
+        netconfNodeAdded(path,new InetSocketAddress(address,port))
+
+    }
+    
+    def netconfNodeAdded(InstanceIdentifier path, InetSocketAddress address) {
+    
+        val mountPointPath = path;
+        val mountPoint = mountService.createOrGetMountPoint(mountPointPath);
+        val localPath = InstanceIdentifier.builder().toInstance;
+        val netconfDevice = new NetconfDevice(mountPoint,localPath);
+        netconfDevice.setSocketAddress(address);
+        netconfDevice.start(dispatcher);
+    }
+
+    def netconfNodeRemoved(InstanceIdentifier path) {
+    
+    }
+
+}
+
+class NetconfInventoryListener implements DataChangeListener {
+
+    val NetconfDeviceManager manager;
+
+    new(NetconfDeviceManager manager) {
+        this.manager = manager;
+    }
+
+    override onDataChanged(DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
+        
+        //manager.netconfNodeAdded(path, change);
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfInventoryUtils.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfInventoryUtils.java
new file mode 100644 (file)
index 0000000..a69f670
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public class NetconfInventoryUtils {
+
+    
+    public static final QName NETCONF_MOUNT = null;
+    public static final QName NETCONF_ENDPOINT = null;
+    public static final QName NETCONF_ENDPOINT_ADDRESS = null;
+    public static final QName NETCONF_ENDPOINT_PORT = null;
+
+
+    public static String getEndpointAddress(CompositeNode node) {
+        return node.getCompositesByName(NETCONF_ENDPOINT).get(0).getFirstSimpleByName(NETCONF_ENDPOINT_ADDRESS).getValue().toString();
+    }
+    
+    public static String getEndpointPort(CompositeNode node) {
+        return node.getCompositesByName(NETCONF_ENDPOINT).get(0).getFirstSimpleByName(NETCONF_ENDPOINT_PORT).getValue().toString();
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.xtend b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.xtend
new file mode 100644 (file)
index 0000000..d23ec1c
--- /dev/null
@@ -0,0 +1,95 @@
+package org.opendaylight.controller.sal.connect.netconf
+
+import org.opendaylight.controller.netconf.api.NetconfMessage
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.common.RpcResult
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import java.net.URI
+import java.util.Collections
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.NodeUtils
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import java.util.concurrent.atomic.AtomicInteger
+import org.w3c.dom.Document
+import org.w3c.dom.Element
+import org.opendaylight.controller.sal.common.util.Rpcs
+
+class NetconfMapping {
+
+    public static val NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0")
+    public static val NETCONF_QNAME = new QName(NETCONF_URI,null,"netconf");
+    public static val NETCONF_RPC_QNAME = new QName(NETCONF_QNAME,"rpc");
+    public static val NETCONF_GET_QNAME = new QName(NETCONF_QNAME,"get");
+    public static val NETCONF_GET_CONFIG_QNAME = new QName(NETCONF_QNAME,"get-config");
+    public static val NETCONF_RPC_REPLY_QNAME = new QName(NETCONF_QNAME,"rpc-reply");
+    public static val NETCONF_OK_QNAME = new QName(NETCONF_QNAME,"ok");
+    public static val NETCONF_DATA_QNAME = new QName(NETCONF_QNAME,"data");
+    
+
+    static val messageId = new AtomicInteger(0);
+
+
+
+    static def Node<?> toFilterStructure(InstanceIdentifier identifier) {
+        var Node<?> previous = null;
+        for (component : identifier.path.reverse) {
+            val Node<?> current = component.toNode(previous);
+            previous = current;
+        }
+        return previous;
+    }
+    
+    static def dispatch Node<?> toNode(NodeIdentifierWithPredicates argument, Node<?> node) {
+        val list = new ArrayList<Node<?>>();
+        for( arg : argument.keyValues.entrySet) {
+            list.add = new SimpleNodeTOImpl(arg.key,null,arg.value);
+        }
+        return new CompositeNodeTOImpl(argument.nodeType,null,list)
+    }
+    
+    static def dispatch Node<?> toNode(PathArgument argument, Node<?> node) {
+        if(node != null) {
+            return new CompositeNodeTOImpl(argument.nodeType,null,Collections.singletonList(node));
+        } else {
+            return new SimpleNodeTOImpl(argument.nodeType,null,null);
+        }
+    }
+
+    static def CompositeNode toCompositeNode(NetconfMessage message) {
+        return message.toRpcResult().result;
+    }
+
+    static def NetconfMessage toRpcMessage(QName rpc, CompositeNode node) {
+        val rpcPayload = wrap(NETCONF_RPC_QNAME,node);
+        val w3cPayload = NodeUtils.buildShadowDomTree(rpcPayload);
+        w3cPayload.documentElement.setAttribute("message-id","m-"+ messageId.andIncrement);
+        return new NetconfMessage(w3cPayload);
+    }
+
+    static def RpcResult<CompositeNode> toRpcResult(NetconfMessage message) {
+        val rawRpc = message.document.toCompositeNode() as CompositeNode;
+        //rawRpc.
+        
+        return Rpcs.getRpcResult(true,rawRpc,Collections.emptySet());
+    }
+    
+    
+    static def wrap(QName name,Node<?> node) {
+        if(node != null) {
+            return new CompositeNodeTOImpl(name,null,Collections.singletonList(node));
+        }
+        else {
+            return new CompositeNodeTOImpl(name,null,Collections.emptyList());
+        }
+    }
+    
+    
+    public static def Node<?> toCompositeNode(Document document) {
+        return XmlDocumentUtils.toCompositeNode(document) as Node<?>
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfProvider.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfProvider.java
new file mode 100644 (file)
index 0000000..8cf5f02
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import java.util.Hashtable;
+
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.osgi.framework.BundleContext;
+
+public class NetconfProvider extends AbstractProvider {
+
+    private NetconfDeviceManager netconfDeviceManager;
+
+    @Override
+    protected void startImpl(BundleContext context) {
+        netconfDeviceManager = new NetconfDeviceManager();
+        context.registerService(NetconfDeviceManager.class, netconfDeviceManager, new Hashtable<String,String>());
+    }
+    
+    
+    @Override
+    public void onSessionInitiated(ProviderSession session) {
+        MountProvisionService mountService = session.getService(MountProvisionService.class);
+        
+        
+        netconfDeviceManager.setMountService(mountService);
+        netconfDeviceManager.start();
+    }
+
+    @Override
+    protected void stopImpl(BundleContext context) {
+        
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/XmlDocumentUtils.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/XmlDocumentUtils.java
new file mode 100644 (file)
index 0000000..3f6b4e1
--- /dev/null
@@ -0,0 +1,54 @@
+package org.opendaylight.controller.sal.connect.netconf;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+public class XmlDocumentUtils {
+
+    public static CompositeNode toCompositeNode(Document doc) {
+        return (CompositeNode) toCompositeNode(doc.getDocumentElement());
+    }
+
+    private static Node<?> toCompositeNode(Element element) {
+        String orgNamespace = element.getNamespaceURI();
+        URI biNamespace = null;
+        if (orgNamespace != null) {
+            biNamespace = URI.create(orgNamespace);
+        }
+        QName qname = new QName(biNamespace, element.getLocalName());
+
+        List<Node<?>> values = new ArrayList<>();
+        NodeList nodes = element.getChildNodes();
+        boolean isSimpleObject = false;
+        String value = null;
+        for (int i = 0; i < nodes.getLength(); i++) {
+            org.w3c.dom.Node child = nodes.item(i);
+            if (child instanceof Element) {
+                isSimpleObject = false;
+                values.add(toCompositeNode((Element) child));
+            }
+            if (!isSimpleObject && child instanceof org.w3c.dom.Text) {
+                value = element.getTextContent();
+                if (value.matches(".*\\w.*")) {
+                    isSimpleObject = true;
+                    break;
+                }
+            }
+        }
+
+        if (isSimpleObject) {
+            return new SimpleNodeTOImpl<>(qname, null, value);
+        }
+        return new CompositeNodeTOImpl(qname, null, values);
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connector/netconf/test/MountTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connector/netconf/test/MountTest.java
new file mode 100644 (file)
index 0000000..4abf0e1
--- /dev/null
@@ -0,0 +1,197 @@
+package org.opendaylight.controller.sal.connector.netconf.test;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+import io.netty.channel.ChannelFuture;
+import io.netty.util.HashedWheelTimer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLContext;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.yang.store.api.YangStoreException;
+import org.opendaylight.controller.config.yang.store.impl.HardcodedYangStoreService;
+import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.client.NetconfClient;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
+import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
+import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
+import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
+import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceManager;
+import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl;
+import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
+public class MountTest extends AbstractConfigTest {
+
+    private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
+    private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024);
+    private static final URI NETCONF_MONITORING_NS = URI.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring");
+    
+    private static final QName NETCONF_MONITORING = new QName(NETCONF_MONITORING_NS, new Date(2010,10,04), "ietf-netconf-monitoring");
+    private static final QName NETCONF_MONITORING_STATE = new QName(NETCONF_MONITORING,"netconf-state");
+    
+
+    private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession;
+    private DefaultCommitNotificationProducer commitNot;
+    private NetconfServerDispatcher dispatch;
+    private DataProviderService dataBroker;
+    private MountPointManagerImpl mountManager;
+    private NetconfDeviceManager netconfManager;
+
+    private static QName CONFIG_MODULES = new QName(
+            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+    private static QName CONFIG_SERVICES = new QName(
+            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+
+    private NetconfClient createSession(final InetSocketAddress address, NetconfClientDispatcher dispatcher) throws InterruptedException {
+        final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, dispatcher);
+        return netconfClient;
+    }
+    
+    @Before
+    public void setUp() throws Exception {
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(getModuleFactories().toArray(
+                new ModuleFactory[0])));
+
+        loadMessages();
+
+        NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+        factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
+
+        commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
+
+        dispatch = createDispatcher(Optional.<SSLContext> absent(), factoriesListener);
+        ChannelFuture s = dispatch.createServer(tcpAddress);
+        s.await();
+
+        dataBroker = new DataBrokerImpl();
+        mountManager = new MountPointManagerImpl();
+        mountManager.setDataBroker(dataBroker);
+        netconfManager = new NetconfDeviceManager();
+
+        netconfManager.setMountService(mountManager);
+        netconfManager.setDataService(dataBroker);
+        netconfManager.start();
+
+        try (NetconfClient netconfClient = createSession(tcpAddress, netconfManager.getDispatcher())) {
+            // send edit_config.xml
+            final Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument();
+            assertNotNull(rpcReply);
+        }
+    }
+
+
+    protected List<ModuleFactory> getModuleFactories() {
+        return getModuleFactoriesS();
+    }
+
+    static List<ModuleFactory> getModuleFactoriesS() {
+        return Lists.newArrayList(new TestImplModuleFactory(), new DepTestImplModuleFactory(),
+                new NetconfTestImplModuleFactory());
+    }
+
+    private void loadMessages() throws IOException, SAXException, ParserConfigurationException {
+        this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml");
+        this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
+        this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml");
+        this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml");
+    }
+
+    private NetconfServerDispatcher createDispatcher(Optional<SSLContext> sslC,
+            NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+        SessionIdProvider idProvider = new SessionIdProvider();
+        NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
+                new HashedWheelTimer(5000, TimeUnit.MILLISECONDS), factoriesListener, idProvider);
+
+        NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
+                factoriesListener, commitNot, idProvider);
+
+        return new NetconfServerDispatcher(sslC, serverNegotiatorFactory, listenerFactory);
+    }
+
+    private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
+        final Collection<InputStream> yangDependencies = getBasicYangs();
+        return new HardcodedYangStoreService(yangDependencies);
+    }
+
+    private Collection<InputStream> getBasicYangs() throws IOException {
+        List<String> paths = Arrays.asList("/META-INF/yang/config.yang", "/META-INF/yang/rpc-context.yang",
+                "/META-INF/yang/config-test.yang", "/META-INF/yang/config-test-impl.yang",
+                "/META-INF/yang/ietf-inet-types.yang");
+        final Collection<InputStream> yangDependencies = new ArrayList<>();
+        for (String path : paths) {
+            final InputStream is = Preconditions
+                    .checkNotNull(getClass().getResourceAsStream(path), path + " not found");
+            yangDependencies.add(is);
+        }
+        return yangDependencies;
+    }
+
+    @Test
+    public void test() {
+        // MountProvisionInstance mount =
+        // Mockito.mock(MountProvisionInstance.class);
+        InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
+                .node(InventoryUtils.INVENTORY_NODE).toInstance();
+        netconfManager.netconfNodeAdded(path, tcpAddress);
+        InstanceIdentifier mountPointPath = path;
+        MountProvisionInstance mountPoint = mountManager.getMountPoint(mountPointPath);
+
+        CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
+                .toInstance());
+        assertNotNull(data);
+        assertEquals(CONFIG_MODULES, data.getNodeType());
+
+        CompositeNode data2 = mountPoint.readOperationalData(InstanceIdentifier.builder().toInstance());
+        assertNotNull(data2);
+
+        InstanceIdentifier fullPath = InstanceIdentifier.builder(mountPointPath).node(CONFIG_MODULES).toInstance();
+
+        CompositeNode data3 = dataBroker.readOperationalData(fullPath);
+        assertNotNull(data3);
+        assertEquals(CONFIG_MODULES, data.getNodeType());
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java
new file mode 100644 (file)
index 0000000..70b2cf5
--- /dev/null
@@ -0,0 +1,17 @@
+package org.opendaylight.controller.sal.rest.api;
+
+public class Draft02 {
+    public static class MediaTypes {
+        public static final String API = "application/yang.api";
+        public static final String DATASTORE = "application/yang.datastore";
+        public static final String DATA = "application/yang.data";
+        public static final String OPERATION = "application/yang.operation";
+        public static final String PATCH = "application/yang.patch";
+        public static final String PATCH_STATUS = "application/yang.patch-status";
+        public static final String STREAM = "application/yang.stream";
+    }
+    
+    public static class Paths {
+        
+    }
+}
index b8cb2292542b8da4ecf7f8573d6b578a47ff3810..c36a79c5d901093ad3bf79d1a4a354ebcf161209 100644 (file)
@@ -16,7 +16,9 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
 /**
@@ -25,7 +27,9 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
  *  Section 5 for details on each URI.
  *    <ul>
  *    <li><b>/restconf</b> - {@link #getRoot()}
- *     <ul><li><b>/datastore</b> - {@link #readAllData()}
+ *     <ul><li><b>/config</b> 
+ *         <li><b>/operational</b> - {@link #readAllData()} - Added in Draft02
+ *         <li><b>/datastore</b> - {@link #readAllData()}
  *         <ul>
  *            <li>/(top-level-data-nodes) (config=true or false)
  *         </ul>
@@ -45,7 +49,7 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
  *     </ul>
  */
 @Path("/")
-public interface RestconfService {
+public interface RestconfService extends RestconfServiceLegacy {
 
     public static final String XML = "+xml";
     public static final String JSON = "+json";
@@ -53,33 +57,49 @@ public interface RestconfService {
     @GET
     public Object getRoot();
 
+
     @GET
-    @Path("/datastore")
+    @Path("/modules")
     @Produces({API+JSON,API+XML})
-    public Object readAllData();
+    public StructuredData getModules();
 
+    @POST
+    @Path("/operations/{identifier}")
+    @Produces({Draft02.MediaTypes.API+JSON,Draft02.MediaTypes.API+XML,API+JSON,API+XML})
+    public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+    
+    
     @GET
-    @Path("/datastore/{identifier:.+}")
-    @Produces({API+JSON,API+XML})
-    public StructuredData readData(@PathParam("identifier") String identifier);
+    @Path("/config/{identifier:.+}")
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+    public StructuredData readConfigurationData(@PathParam("identifier") String identifier);
 
+    
+    
     @PUT
-    @Path("/datastore/{identifier:.+}")
+    @Path("/config/{identifier:.+}")
     @Produces({API+JSON,API+XML})
-    public Object createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+    public RpcResult<TransactionStatus> createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
 
     @POST
-    @Path("/datastore/{identifier:.+}")
+    @Path("/config/{identifier:.+}")
     @Produces({API+JSON,API+XML})
-    public Object updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+    public RpcResult<TransactionStatus> updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
 
     @GET
-    @Path("/modules")
+    @Path("/operational/{identifier:.+}")
+    @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+    public StructuredData readOperationalData(@PathParam("identifier") String identifier);
+
+    @PUT
+    @Path("/operational/{identifier:.+}")
     @Produces({API+JSON,API+XML})
-    public Object getModules();
+    public RpcResult<TransactionStatus> createOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
 
     @POST
-    @Path("/operations/{identifier}")
+    @Path("/operational/{identifier:.+}")
     @Produces({API+JSON,API+XML})
-    public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+    public RpcResult<TransactionStatus> updateOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
+
+    
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java
new file mode 100644 (file)
index 0000000..6683fd1
--- /dev/null
@@ -0,0 +1,46 @@
+package org.opendaylight.controller.sal.rest.api;
+
+import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface RestconfServiceLegacy {
+
+    public static final String XML = "+xml";
+    public static final String JSON = "+json";
+    
+    @Deprecated
+    @GET
+    @Path("/datastore")
+    @Produces({API+JSON,API+XML})
+    public StructuredData readAllData();
+
+    @Deprecated
+    @GET
+    @Path("/datastore/{identifier:.+}")
+    @Produces({API+JSON,API+XML})
+    public StructuredData readData(@PathParam("identifier") String identifier);
+
+    @Deprecated
+    @PUT
+    @Path("/datastore/{identifier:.+}")
+    @Produces({API+JSON,API+XML})
+    public RpcResult<TransactionStatus> createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
+
+    @Deprecated
+    @POST
+    @Path("/datastore/{identifier:.+}")
+    @Produces({API+JSON,API+XML})
+    public RpcResult<TransactionStatus> updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
+
+}
index 8e18661db6ecdfcc65d822dff5bf1e4c115c0b96..3c31c5a313ec0b45a9a8390729638331d4a7a7a0 100644 (file)
@@ -42,15 +42,15 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
         return future.get;
     }
 
-    def commitConfigurationDataUpdate(InstanceIdentifier path, CompositeNode payload) {
+    def commitConfigurationDataPut(InstanceIdentifier path, CompositeNode payload) {
         val transaction = dataService.beginTransaction;
         transaction.putConfigurationData(path, payload);
         return transaction.commit()
     }
 
-    def commitConfigurationDataCreate(InstanceIdentifier path, CompositeNode payload) {
+    def commitOperationalDataPut(InstanceIdentifier path, CompositeNode payload) {
         val transaction = dataService.beginTransaction;
-        transaction.putConfigurationData(path, payload);
+        transaction.putOperationalData(path, payload);
         return transaction.commit()
     }
     
index 2b3a3042c2ce9119c9ee9d0176dcf88ed52807cb..400850103d7be35f72beeb39088a1618a23feff5 100644 (file)
@@ -25,6 +25,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext
 
 import static com.google.common.base.Preconditions.*
 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+import java.util.concurrent.ConcurrentHashMap
 
 class ControllerContext implements SchemaServiceListener {
 
@@ -37,6 +39,8 @@ class ControllerContext implements SchemaServiceListener {
 
     private val BiMap<URI, String> uriToModuleName = HashBiMap.create();
     private val Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
+    private val Map<QName,RpcDefinition> qnameToRpc = new ConcurrentHashMap();
+    
 
     private new() {
         if (INSTANCE != null) {
@@ -272,11 +276,23 @@ class ControllerContext implements SchemaServiceListener {
         }
     }
 
-    public def QName toRpcQName(String name) {
+    public def QName toQName(String name) {
+        val module = name.toModuleName;
+        val node = name.toNodeName;
+        val namespace = moduleNameToUri.get(module);
+        return new QName(namespace,null,node);
     }
 
     override onGlobalContextUpdated(SchemaContext context) {
         this.schemas = context;
+        for(operation : context.operations) {
+            val qname = new QName(operation.QName.namespace,null,operation.QName.localName);
+            qnameToRpc.put(qname,operation);
+        }
+    }
+    
+    def ContainerSchemaNode getRpcOutputSchema(QName name) {
+        qnameToRpc.get(name)?.output;
     }
 
 }
index fc0dd1017fea6fbb9e77cd5f3b5a84d616b9e58f..31fbe8ec876876b0d677ffaa90df95fddbdfa91a 100644 (file)
@@ -25,7 +25,7 @@ class RestconfImpl implements RestconfService {
 
     override readAllData() {
 //        return broker.readOperationalData("".toInstanceIdentifier.getInstanceIdentifier);
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        throw new UnsupportedOperationException("Reading all data is currently not supported.")
     }
 
     override getModules() {
@@ -33,8 +33,7 @@ class RestconfImpl implements RestconfService {
     }
 
     override getRoot() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-
+        return null;
     }
 
     override readData(String identifier) {
@@ -44,18 +43,50 @@ class RestconfImpl implements RestconfService {
     }
 
     override createConfigurationData(String identifier, CompositeNode payload) {
-//        return broker.commitConfigurationDataCreate(identifier.toInstanceIdentifier.getInstanceIdentifier, payload);
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
     }
 
     override updateConfigurationData(String identifier, CompositeNode payload) {
-//        return broker.commitConfigurationDataCreate(identifier.toInstanceIdentifier.getInstanceIdentifier, payload);
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
     }
 
     override invokeRpc(String identifier, CompositeNode payload) {
-        val rpcResult = broker.invokeRpc(identifier.toRpcQName, payload);
-        return new StructuredData(rpcResult.result, identifier.toInstanceIdentifier.getSchemaNode)
+        val rpc = identifier.toQName;
+        val rpcResult = broker.invokeRpc(rpc, payload);
+        val schema = controllerContext.getRpcOutputSchema(rpc);
+        return new StructuredData(rpcResult.result, schema);
+    }
+    
+    override readConfigurationData(String identifier) {
+        val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+        val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+        return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
+    }
+    
+    override readOperationalData(String identifier) {
+        val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+        val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+        return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
+    }
+    
+    override updateConfigurationDataLegacy(String identifier, CompositeNode payload) {
+        updateConfigurationData(identifier,payload);
+    }
+    
+    override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
+        createConfigurationData(identifier,payload);
+    }
+    
+    override createOperationalData(String identifier, CompositeNode payload) {
+        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
+    }
+    
+    override updateOperationalData(String identifier, CompositeNode payload) {
+        val identifierWithSchemaNode = identifier.toInstanceIdentifier
+        return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
     }
 
 }
index 6f53bcd2c4d8d0a513fe79ad7d038f692b88bdfd..a1925a53b505a616b1dc3cd6b6d99146a7fe97f7 100644 (file)
             <artifactId>logback-classic</artifactId>
             <version>1.0.9</version>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+            <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+            <version>4.0</version>
+        </dependency>
     </dependencies>
 </project>
index 7cd4fa52c6318eb620b28aa94fa86838a9a8867f..f42cd01cf78e5bda4e3b0e4b37e9346d076ba565 100644 (file)
@@ -17,12 +17,17 @@ 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.systemProperty;
+import org.ops4j.pax.exam.util.PathUtils;
 
 @RunWith(PaxExam.class)
 public class ToasterTest {
 
     public static final String ODL = "org.opendaylight.controller";
     public static final String YANG = "org.opendaylight.yangtools";
+    public static final String CONTROLLER = "org.opendaylight.controller";
+    public static final String YANGTOOLS = "org.opendaylight.yangtools";
+    
+    
     public static final String SAMPLE = "org.opendaylight.controller.samples";
 
     @Test
@@ -46,13 +51,13 @@ public class ToasterTest {
     @Configuration
     public Option[] config() {
         return options(systemProperty("osgi.console").value("2401"), 
+                systemProperty("logback.configurationFile").value(
+                    "file:" + PathUtils.getBaseDir()
+                    + "/src/test/resources/logback.xml"),
                 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-api").versionAsInProject(), //
-                mavenBundle(ODL, "sal-binding-config").versionAsInProject(), 
-                mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject(), //
                 
                 mavenBundle(ODL, "sal-common").versionAsInProject(), //
                 mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
@@ -62,7 +67,37 @@ public class ToasterTest {
                 mavenBundle(ODL, "config-api").versionAsInProject(), //
                 mavenBundle(ODL, "config-manager").versionAsInProject(), //
                 mavenBundle("commons-io", "commons-io").versionAsInProject(),
+                mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
                 
+                mavenBundle(CONTROLLER, "sal-binding-api").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(),
+                mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), //
+                mavenBundle("org.javassist", "javassist").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), //
+        
+                mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+                
+                
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), //
+                mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(),
+                mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
+                
+                
+                mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
+                mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), //
+                mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
+                
+                mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
                 
                 mavenBundle(SAMPLE, "sample-toaster").versionAsInProject(), //
                 mavenBundle(SAMPLE, "sample-toaster-consumer").versionAsInProject(), //
similarity index 99%
rename from opendaylight/clustering/services_implementation/src/test/resources/logback.xml
rename to opendaylight/md-sal/samples/toaster-it/src/test/resources/logback.xml
index 6d9dfda9a365f9a08f9d4ba5b7733f2cb6340ba6..2d63ce57448f88b77a39b1bcb0525b9721c08370 100644 (file)
@@ -1,4 +1,5 @@
 <configuration scan="true">
+
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     <encoder>
       <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
index b5b1642797ab6dcbbeb4e789c353dfde0733c6f4..8569783ad79818056eb45303692ec869f57c0671 100644 (file)
@@ -21,6 +21,8 @@
         <spring.version>3.1.3.RELEASE</spring.version>
         <jersey.version>1.17</jersey.version>
         <spring-security.version>3.1.3.RELEASE</spring-security.version>
+        <netconf.version>0.2.2-SNAPSHOT</netconf.version>
+        <config.version>0.2.2-SNAPSHOT</config.version>
     </properties>
 
     <build>
             <version>1.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-netconf-connector</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-it</artifactId>
             <version>1.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+        <groupId>org.opendaylight.controller.thirdparty</groupId>
+        <artifactId>exificient</artifactId>
+        <version>0.9.2</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>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+            <version>4.0.10.Final</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.ops4j.pax.exam</groupId>
             <artifactId>pax-exam-link-mvn</artifactId>
             <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
             <version>7.0.42</version>
         </dependency>
+
+
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-manager</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-util</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-jmx-generator</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-store-api</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-store-impl</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>logback-config</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-persister-api</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-persister-file-adapter</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-api</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-impl</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-util</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-client</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-mapping-api</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-netconf-connector</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-persister-impl</artifactId>
+            <version>${netconf.version}</version>
+        </dependency>
     </dependencies>
 </project>
index 1087da22f9b2ddcbdb54e9e441530124ba175771..23ba8aaea41e5866fc1934290bfd17f6154aadd9 100644 (file)
@@ -1,5 +1,6 @@
 package org.opendaylight.controller.test.restconf.it;
 
+import static junit.framework.Assert.assertEquals;
 import static org.junit.Assert.*;
 import static org.ops4j.pax.exam.CoreOptions.junitBundles;
 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
@@ -8,14 +9,27 @@ 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.net.InetSocketAddress;
+import java.net.URI;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
 
 import javax.inject.Inject;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceManager;
+import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
 import org.opendaylight.controller.test.sal.binding.it.TestHelper;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.ops4j.pax.exam.Configuration;
 import org.ops4j.pax.exam.CoreOptions;
 import org.ops4j.pax.exam.Option;
@@ -34,23 +48,55 @@ public class ServiceProviderController {
     public static final String YANG = "org.opendaylight.yangtools";
     public static final String SAMPLE = "org.opendaylight.controller.samples";
 
+    private static QName CONFIG_MODULES = new QName(
+            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+    private static QName CONFIG_SERVICES = new QName(
+            URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+    @Inject
+    BundleContext context;
+
+    @Inject
+    MountProvisionService mountService;
+
+    @Inject
+    DataBrokerService dataBroker;
+
+    @Inject
+    NetconfDeviceManager netconfManager;
+
     @Test
     public void properInitialized() throws Exception {
 
-        Thread.sleep(30*60*1000); // Waiting for services to get wired.
-        assertTrue(true);
-        // assertTrue(consumer.createToast(WhiteBread.class, 5));
+        Map<QName, String> arg = Collections.singletonMap(InventoryUtils.INVENTORY_ID, "foo");
 
-    }
+        InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
+                .nodeWithKey(InventoryUtils.INVENTORY_NODE, InventoryUtils.INVENTORY_ID, "foo").toInstance();
 
-    // @Inject
-    // BindingAwareBroker broker;
+        netconfManager.netconfNodeAdded(path, new InetSocketAddress("127.0.0.1", 8383));
 
-    // @Inject
-    // ToastConsumer consumer;
+        
+        InstanceIdentifier mountPointPath = path;
+        
+        /** We retrive a mountpoint **/
+        MountProvisionInstance mountPoint = mountService.getMountPoint(mountPointPath);
+        CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
+                .toInstance());
+        assertNotNull(data);
+        assertEquals(CONFIG_MODULES, data.getNodeType());
 
-    @Inject
-    BundleContext ctx;
+        CompositeNode data2 = mountPoint.readOperationalData(InstanceIdentifier.builder().toInstance());
+        assertNotNull(data2);
+
+        InstanceIdentifier fullPath = InstanceIdentifier.builder(mountPointPath).node(CONFIG_MODULES).toInstance();
+
+        CompositeNode data3 = dataBroker.readOperationalData(fullPath);
+        assertNotNull(data3);
+        assertEquals(CONFIG_MODULES, data.getNodeType());
+
+        //Thread.sleep(30 * 60 * 1000); // Waiting for services to get wired.
+        //assertTrue(true);
+        // assertTrue(consumer.createToast(WhiteBread.class, 5));
+    }
 
     @Configuration
     public Option[] config() {
@@ -63,6 +109,7 @@ public class ServiceProviderController {
                 mdSalCoreBundles(),
                 baseModelBundles(),
                 flowCapableModelBundles(),
+                configMinumumBundles(),
 
                 // mavenBundle(ODL,
                 // "sal-binding-broker-impl").versionAsInProject().update(), //
@@ -79,6 +126,7 @@ public class ServiceProviderController {
                 // mavenBundle(SAMPLE,
                 // "zeromq-test-provider").versionAsInProject(), //
                 mavenBundle(ODL, "sal-rest-connector").versionAsInProject(), //
+                mavenBundle(ODL, "sal-netconf-connector").versionAsInProject(), //
 
                 mavenBundle(YANG, "concepts").versionAsInProject(),
                 mavenBundle(YANG, "yang-binding").versionAsInProject(), //
@@ -89,6 +137,7 @@ public class ServiceProviderController {
                 mavenBundle(YANG, "yang-model-util").versionAsInProject(), //
                 mavenBundle(YANG, "yang-parser-api").versionAsInProject(),
                 mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
+
                 mavenBundle(YANG + ".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
                 mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
                 mavenBundle("com.google.guava", "guava").versionAsInProject(), //
@@ -105,8 +154,15 @@ public class ServiceProviderController {
                 // earlier.
                 systemProperty("osgi.bundles.defaultStartLevel").value("4"),
 
+                systemProperty("netconf.tcp.address").value("127.0.0.1"),
+                systemProperty("netconf.tcp.port").value("8383"),
+
                 // Set the systemPackages (used by clustering)
                 systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
+
+                mavenBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.xerces", "2.11.0_1"),
+                mavenBundle("org.eclipse.birt.runtime.3_7_1", "org.apache.xml.resolver", "1.2.0"),
+
                 mavenBundle("org.slf4j", "jcl-over-slf4j").versionAsInProject(),
                 mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
                 mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
@@ -140,6 +196,40 @@ public class ServiceProviderController {
                 // mavenBundle("commons-fileupload",
                 // "commons-fileupload").versionAsInProject(),
 
+                mavenBundle("io.netty", "netty-handler").versionAsInProject(),
+                mavenBundle("io.netty", "netty-codec").versionAsInProject(),
+                mavenBundle("io.netty", "netty-buffer").versionAsInProject(),
+                mavenBundle("io.netty", "netty-transport").versionAsInProject(),
+                mavenBundle("io.netty", "netty-common").versionAsInProject(),
+
+                mavenBundle(ODL, "config-api").versionAsInProject(),
+                mavenBundle(ODL, "config-manager").versionAsInProject(),
+                mavenBundle(ODL, "config-util").versionAsInProject(),
+                mavenBundle(ODL, "yang-jmx-generator").versionAsInProject(),
+                mavenBundle(ODL, "yang-store-api").versionAsInProject(),
+                mavenBundle(ODL, "yang-store-impl").versionAsInProject(),
+                mavenBundle(ODL, "logback-config").versionAsInProject(),
+                mavenBundle(ODL, "config-persister-api").versionAsInProject(),
+                // mavenBundle(ODL,"config-persister-file-adapter").versionAsInProject(),
+                mavenBundle(ODL, "netconf-api").versionAsInProject(),
+                mavenBundle(ODL, "netconf-impl").versionAsInProject(),
+                mavenBundle(ODL, "netconf-client").versionAsInProject(),
+                mavenBundle(ODL, "netconf-util").versionAsInProject(),
+                mavenBundle(ODL + ".thirdparty", "ganymed", "1.0-SNAPSHOT"),
+                mavenBundle(ODL, "netconf-mapping-api").versionAsInProject(),
+                mavenBundle(ODL, "config-netconf-connector").versionAsInProject(),
+                mavenBundle(ODL, "config-persister-impl").versionAsInProject(),
+
+                mavenBundle("org.opendaylight.bgpcep", "framework").versionAsInProject(),
+                mavenBundle("org.opendaylight.bgpcep", "util").versionAsInProject(),
+                mavenBundle(YANG, "binding-generator-spi").versionAsInProject(), //
+                mavenBundle(YANG, "binding-model-api").versionAsInProject(), //
+                mavenBundle(YANG, "binding-generator-util").versionAsInProject(),
+                mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
+                mavenBundle(YANG, "binding-type-provider").versionAsInProject(),
+
+                mavenBundle("org.opendaylight.controller.thirdparty", "exificient", "0.9.2"),
+
                 mavenBundle("equinoxSDK381", "javax.servlet").versionAsInProject(),
                 mavenBundle("equinoxSDK381", "javax.servlet.jsp").versionAsInProject(),
                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds").versionAsInProject(),
index 74c08e379ffa86f4b47593a75058ce13d9d70d1f..d855f1554125764c16170b84c26457bd0976fa04 100755 (executable)
             <version>${bgpcep.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>commons.logback_settings</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
index 028e9b4bd41c2b55b2f71676275049e0dee28d4e..33fa675a926677245ae6583acc5106c9327f179c 100644 (file)
             <artifactId>netconf-client</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>commons.logback_settings</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
index 8606421ab9b547d427a57d08412218ddea9f9b06..13b0a1e570b122ae04a94e5b626b27e7c93f7b88 100644 (file)
             <artifactId>mockito-configuration</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>commons.logback_settings</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
index 7bec2722bf96fd1e9b3b645203aa67c8a6b4f36c..602de9a1c6f28f8e195ed0aa00c78bd82f3da434 100644 (file)
@@ -310,7 +310,7 @@ public class NorthboundIT {
         JSONTokener jt = new JSONTokener(result);
         JSONObject json = new JSONObject(jt);
         JSONArray subnetConfigs = json.getJSONArray("subnetConfig");
-        Assert.assertEquals(subnetConfigs.length(), 0);
+        Assert.assertEquals(subnetConfigs.length(), 1); // should only get the default subnet
 
         // Test GET subnet1 expecting 404
         result = getJsonResult(baseURL + "default/subnet/" + name1);
diff --git a/opendaylight/northbound/java-client/enunciate.xml b/opendaylight/northbound/java-client/enunciate.xml
new file mode 100644 (file)
index 0000000..ce9186e
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+
+  <services> </services>
+
+  <modules>
+    <!-- Disable doc generation -->
+    <docs disabled="true"/>
+
+    <!-- Disable all the client generation tools -->
+    <basic-app disabled="true" />
+    <c disabled="true" />
+    <csharp disabled="true" />
+    <jaxws-client disabled="true" />
+    <jaxws-ri disabled="true" />
+    <jaxws-support disabled="true" />
+    <obj-c disabled="true" />
+    <ruby disabled="true"/>
+    <php disabled="true"/>
+
+    <!-- enable only the java clients -->
+    <xml disabled="false" />
+    <java-client disabled="false"/>
+  </modules>
+
+  <api-classes>
+    <include pattern="org.opendaylight.controller.**"/>
+  </api-classes>
+
+  <api-import pattern="org.opendaylight.controller.**"/>
+</enunciate>
diff --git a/opendaylight/northbound/java-client/pom.xml b/opendaylight/northbound/java-client/pom.xml
new file mode 100644 (file)
index 0000000..b6fd296
--- /dev/null
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.1-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+    <tag>HEAD</tag>
+  </scm>
+
+  <artifactId>northbound.client</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <properties>
+    <docs.output.dir>${project.build.directory}/rest-api-docs</docs.output.dir>
+    <java-client>${project.build.directory}/enunciate/build/java-client/full-client.jar</java-client>
+    <java-client-sources>${project.build.directory}/enunciate/build/java-client/full-client-sources.jar</java-client-sources>
+    <json-client>${project.build.directory}/enunciate/build/java-client/full-json-client.jar</json-client>
+    <json-client-sources>${project.build.directory}/enunciate/build/java-client/full-json-client-sources.jar</json-client-sources>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.enunciate</groupId>
+        <artifactId>maven-enunciate-plugin</artifactId>
+        <version>${enunciate.version}</version>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.5</version>
+        <executions>
+          <execution>
+            <phase>install</phase>
+            <goals>
+                <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <target>
+            <taskdef resource="net/sf/antcontrib/antcontrib.properties"
+                     classpathref="maven.plugin.classpath" />
+            <patternset id="rest.paths">
+              <include name="**/target/site/wsdocs/**"/>
+              <exclude name="**/java-client/**"/>
+            </patternset>
+
+            <echo message="======== Assembling enunciate docs ========"/>
+            <!-- cleanup existing generated files -->
+            <delete dir="${docs.output.dir}"/>
+            <delete file="${docs.output.dir}.zip"/>
+            <mkdir dir="${docs.output.dir}"/>
+            <!-- copy enunciate docs to stage -->
+            <copy todir="${docs.output.dir}">
+              <fileset dir="${basedir}/../../..">
+                <patternset refid="rest.paths"/>
+              </fileset>
+              <mapper type="regexp"
+                      from="^(.*)/([^/]+)/target/site/wsdocs/(.*)$$"
+                      to="\2/\3"/>
+            </copy>
+            <!-- generate index.html -->
+            <!-- append header -->
+            <echo file="${docs.output.dir}/index.html" append="true">
+&lt;![CDATA[
+&lt;html&gt;
+  &lt;head&gt;
+    &lt;title&gt; OpenDaylight REST API Documentation &lt;/title&gt;
+  &lt;/head&gt;
+  &lt;body&gt;
+  &lt;h2&gt;OpenDaylight REST API Documentation&lt;/h2&gt;
+  &lt;p&gt; OpenDaylight supports the following &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;Representational State Transfer (REST)&lt;/a&gt; APIs: &lt;/p&gt;
+  &lt;h4&gt;
+]]&gt;
+            </echo>
+            <dirset id="nbset" dir="${docs.output.dir}">
+              <include name="*"/>
+            </dirset>
+            <pathconvert pathsep="&amp;#36;{line.separator}"
+                         property="nbs"
+                         refid="nbset"/>
+            <echo file="${docs.output.dir}/index.html"
+                  append="true"
+                  message="${nbs}"/>
+            <replaceregexp file="${docs.output.dir}/index.html"
+                           match="^\${docs.output.dir}/(.*)$"
+                           replace="&amp;lt;li&amp;gt;&amp;lt;a href=\1/index.html&amp;gt; \1 &amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;"
+                           byline="true"/>
+
+            <!-- append footer -->
+            <echo file="${docs.output.dir}/index.html" append="true">
+&lt;![CDATA[
+  &lt;/h4&gt;
+  &lt;i&gt;---&lt;/i&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
+]]&gt;
+            </echo>
+            <!-- archive all the docs excluding whatever is not needed -->
+            <echo message="======== Archiving enunciate docs ========"/>
+            <zip destfile="${docs.output.dir}.zip">
+              <zipfileset dir="${docs.output.dir}"/>
+            </zip>
+
+            <echo message="======== Build successful ========"/>
+            <echo message="REST docs archive: ${docs.output.dir}.zip"/>
+          </target>
+        </configuration>
+        <dependencies>
+          <dependency>
+            <groupId>ant-contrib</groupId>
+            <artifactId>ant-contrib</artifactId>
+            <version>20020829</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <version>2.5</version>
+        <configuration>
+          <packaging>jar</packaging>
+          <groupId>${project.groupId}</groupId>
+          <version>${project.version}</version>
+        </configuration>
+        <executions>
+          <execution>
+            <!-- skip default install -->
+            <id>default-install</id>
+            <phase>install</phase>
+            <goals>
+              <goal>install</goal>
+            </goals>
+            <configuration>
+              <skip>true</skip>
+            </configuration>
+          </execution>
+          <execution>
+            <!-- install full java client -->
+            <id>install-full-client</id>
+            <phase>install</phase>
+            <goals>
+              <goal>install-file</goal>
+            </goals>
+            <configuration>
+              <artifactId>${project.artifactId}.full-client</artifactId>
+              <file>${java-client}</file>
+              <sources>${java-client-sources}</sources>
+            </configuration>
+          </execution>
+          <execution>
+            <!-- install full java json client -->
+            <id>install-full-json-client</id>
+            <phase>install</phase>
+            <goals>
+              <goal>install-file</goal>
+            </goals>
+            <configuration>
+              <artifactId>${project.artifactId}.full-json-client</artifactId>
+              <file>${json-client}</file>
+              <sources>${json-client-sources}</sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <version>2.5</version>
+        <configuration>
+          <packaging>jar</packaging>
+          <generatePom>true</generatePom>
+          <groupId>${project.groupId}</groupId>
+          <version>${project.version}</version>
+          <url>${project.distributionManagement.repository.url}</url>
+        </configuration>
+        <executions>
+          <execution>
+            <!-- skip default deploy -->
+            <id>default-deploy</id>
+            <phase>deploy</phase>
+            <goals>
+              <goal>deploy</goal>
+            </goals>
+            <configuration>
+              <skip>true</skip>
+            </configuration>
+          </execution>
+          <execution>
+            <!-- deploy full java client -->
+            <id>deploy-full-client</id>
+            <phase>deploy</phase>
+            <goals>
+              <goal>deploy-file</goal>
+            </goals>
+            <configuration>
+              <artifactId>${project.artifactId}.full-client</artifactId>
+              <file>${java-client}</file>
+              <sources>${java-client-sources}</sources>
+            </configuration>
+          </execution>
+          <execution>
+            <!-- deploy full java json client -->
+            <id>deploy-full-json-client</id>
+            <phase>deploy</phase>
+            <goals>
+              <goal>deploy-file</goal>
+            </goals>
+            <configuration>
+              <artifactId>${project.artifactId}.full-json-client</artifactId>
+              <file>${json-client}</file>
+              <sources>${json-client-sources}</sources>
+            </configuration>
+          </execution>
+       </executions>
+    </plugin>
+
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.codehaus.enunciate</groupId>
+      <artifactId>enunciate-core-annotations</artifactId>
+      <version>${enunciate.version}</version>
+    </dependency>
+
+    <!-- add dependency on all northbound bundles -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>connectionmanager.northbound</artifactId>
+      <version>0.1.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>controllermanager.northbound</artifactId>
+      <version>0.0.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>flowprogrammer.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>networkconfig.bridgedomain.northbound</artifactId>
+      <version>0.0.2-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>networkconfig.neutron.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwarding.staticrouting.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>statistics.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>subnets.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topology.northbound</artifactId>
+      <version>0.4.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>usermanager.northbound</artifactId>
+      <version>0.0.1-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+</project>
index c7522c977f81527adf1acc63696d5a0dda49f38f..ca0ff45d61e4977ed677f761d93c73c86262482e 100644 (file)
@@ -70,7 +70,7 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
+      <version>0.6.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index da7735d4c59a9c086f5ec688612999c28a71b8fa..9041004605dded75ce2fe44f129c617656ab6e60 100644 (file)
@@ -132,12 +132,17 @@ public class MessageReadWriteService implements IMessageReadWrite {
             throw new AsynchronousCloseException();
         }
 
-        inBuffer.flip();
-        msgs = factory.parseMessages(inBuffer);
-        if (inBuffer.hasRemaining()) {
-            inBuffer.compact();
-        } else {
+        try {
+            inBuffer.flip();
+            msgs = factory.parseMessages(inBuffer);
+            if (inBuffer.hasRemaining()) {
+                inBuffer.compact();
+            } else {
+                inBuffer.clear();
+            }
+        } catch (Exception e) {
             inBuffer.clear();
+            logger.debug("Caught exception: ", e);
         }
         return msgs;
     }
index f0922d3658f946c474e48002874bf4a34295221a..90b47cf26421e6ff6a05c0e6ef21451c52173ac9 100644 (file)
@@ -282,12 +282,17 @@ public class SecureMessageReadWriteService implements IMessageReadWrite {
                     peerNetData.position(), peerNetData.limit());
         }
 
-        peerAppData.flip();
-        msgs = factory.parseMessages(peerAppData);
-        if (peerAppData.hasRemaining()) {
-            peerAppData.compact();
-        } else {
+        try {
+            peerAppData.flip();
+            msgs = factory.parseMessages(peerAppData);
+            if (peerAppData.hasRemaining()) {
+                peerAppData.compact();
+            } else {
+                peerAppData.clear();
+            }
+        } catch (Exception e) {
             peerAppData.clear();
+            logger.debug("Caught exception: ", e);
         }
 
         this.socket.register(this.selector, SelectionKey.OP_READ, this);
index 6e000022df12909e1f4facdcbcf4236d20d3fd69..6fddef06a8388a80a5278ce2f9a3234ae4461982 100644 (file)
@@ -359,8 +359,6 @@ public class SwitchHandler implements ISwitch {
         }
 
         if (msgs == null) {
-            logger.info("{} is down", this);
-            reportSwitchStateChange(false);
             return;
         }
         for (OFMessage msg : msgs) {
@@ -369,16 +367,15 @@ public class SwitchHandler implements ISwitch {
             OFType type = msg.getType();
             switch (type) {
             case HELLO:
-                // send feature request
-                OFMessage featureRequest = factory.getMessage(OFType.FEATURES_REQUEST);
-                asyncFastSend(featureRequest);
-                this.state = SwitchState.WAIT_FEATURES_REPLY;
-                startSwitchTimer();
+                sendFeaturesRequest();
                 break;
             case ECHO_REQUEST:
                 OFEchoReply echoReply = (OFEchoReply) factory.getMessage(OFType.ECHO_REPLY);
                 // respond immediately
                 asyncSendNow(echoReply, msg.getXid());
+
+                // send features request if not sent yet
+                sendFeaturesRequest();
                 break;
             case ECHO_REPLY:
                 this.probeSent = false;
@@ -507,6 +504,16 @@ public class SwitchHandler implements ISwitch {
         return this.sid;
     }
 
+    private void sendFeaturesRequest() {
+        if (!isOperational() && (this.state != SwitchState.WAIT_FEATURES_REPLY)) {
+            // send feature request
+            OFMessage featureRequest = factory.getMessage(OFType.FEATURES_REQUEST);
+            asyncFastSend(featureRequest);
+            this.state = SwitchState.WAIT_FEATURES_REPLY;
+            startSwitchTimer();
+        }
+    }
+
     private void processFeaturesReply(OFFeaturesReply reply) {
         if (this.state == SwitchState.WAIT_FEATURES_REPLY) {
             this.sid = reply.getDatapathId();
index 2bbe9c12c6719e736f960bd2fba4a1457825060c..8fa4941b88771c94dbf3b578a3f89717339f899e 100644 (file)
@@ -12,7 +12,9 @@ import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod;
 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
@@ -20,6 +22,7 @@ import org.opendaylight.controller.sal.action.Action;
 import org.opendaylight.controller.sal.action.ActionType;
 import org.opendaylight.controller.sal.action.Controller;
 import org.opendaylight.controller.sal.action.Drop;
+import org.opendaylight.controller.sal.action.Enqueue;
 import org.opendaylight.controller.sal.action.Flood;
 import org.opendaylight.controller.sal.action.FloodAll;
 import org.opendaylight.controller.sal.action.HwPath;
@@ -747,4 +750,50 @@ public class FlowConverter {
         return flow;
     }
 
+    private static final Map<Integer, Class<? extends Action>> actionMap = new HashMap<Integer, Class<? extends Action>>() {
+        private static final long serialVersionUID = 1L;
+        {
+            put(1 << 0, Output.class);
+            put(1 << 1, SetVlanId.class);
+            put(1 << 2, SetVlanPcp.class);
+            put(1 << 3, PopVlan.class);
+            put(1 << 4, SetDlSrc.class);
+            put(1 << 5, SetDlDst.class);
+            put(1 << 6, SetNwSrc.class);
+            put(1 << 7, SetNwDst.class);
+            put(1 << 8, SetNwTos.class);
+            put(1 << 9, SetTpSrc.class);
+            put(1 << 10, SetTpDst.class);
+            put(1 << 11, Enqueue.class);
+        }
+    };
+
+    /**
+     * Returns the supported flow actions for the netwrok node given the bitmask
+     * representing the actions the Openflow 1.0 switch supports
+     *
+     * @param ofActionBitmask
+     *            OF 1.0 action bitmask
+     * @return The correspondent list of SAL Action classes
+     */
+    public static List<Class<? extends Action>> getFlowActions(int ofActionBitmask) {
+        List<Class<? extends Action>> list = new ArrayList<Class<? extends Action>>();
+
+        for (int i = 0; i < Integer.SIZE; i++) {
+            int index = 1 << i;
+            if ((index & ofActionBitmask) > 0) {
+                if (actionMap.containsKey(index)) {
+                    list.add(actionMap.get(index));
+                }
+            }
+        }
+        // Add implicit SAL actions
+        list.add(Controller.class);
+        list.add(SwPath.class);
+        list.add(HwPath.class);
+        list.add(Drop.class);
+
+        return list;
+    }
+
 }
index a920adf71d35163094514674fbb5b8a158bf66d7..f4843cf8283f36f2dc4ae957c2e46c42d363e4d6 100644 (file)
@@ -26,9 +26,9 @@ import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
 import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener;
 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
 import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitchStateListener;
+import org.opendaylight.controller.sal.action.SupportedFlowActions;
 import org.opendaylight.controller.sal.connection.ConnectionLocality;
 import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
-import org.opendaylight.controller.sal.core.Actions;
 import org.opendaylight.controller.sal.core.Buffers;
 import org.opendaylight.controller.sal.core.Capabilities;
 import org.opendaylight.controller.sal.core.ContainerFlow;
@@ -503,7 +503,7 @@ public class InventoryServiceShim implements IContainerListener,
             props.add(c);
         }
         int act = sw.getActions();
-        Actions a = new Actions(act);
+        SupportedFlowActions a = new SupportedFlowActions(FlowConverter.getFlowActions(act));
         if (a != null) {
             props.add(a);
         }
diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Enqueue.java
new file mode 100644 (file)
index 0000000..b3891c8
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.action;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.sal.core.NodeConnector;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class Enqueue extends Action {
+    private static final long serialVersionUID = 1L;
+    @XmlElement
+    private NodeConnector port;
+
+    /* Dummy constructor for JAXB */
+    @SuppressWarnings("unused")
+    private Enqueue() {
+    }
+
+    public Enqueue(NodeConnector port) {
+        type = ActionType.ENQUEUE;
+        this.port = port;
+    }
+
+    public NodeConnector getPort() {
+        return port;
+    }
+}
diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SupportedFlowActions.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SupportedFlowActions.java
new file mode 100644 (file)
index 0000000..0a5d9c8
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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.action;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.opendaylight.controller.sal.core.Property;
+
+/**
+ * @file SupportedFlowActions.java
+ *
+ * @brief Class representing the supported flow actions
+ *
+ *        Describes the supported flow actions
+ */
+
+@XmlAccessorType(XmlAccessType.NONE)
+public class SupportedFlowActions extends Property {
+    private static final long serialVersionUID = 1L;
+    public static final String SupportedFlowActionsPropName = "supportedFlowActions";
+    private List<Class<? extends Action>> actions;
+
+    private SupportedFlowActions() {
+        super(SupportedFlowActionsPropName);
+        this.actions = new ArrayList<Class<? extends Action>>();
+    }
+
+    public SupportedFlowActions(List<Class<? extends Action>> actions) {
+        super(SupportedFlowActionsPropName);
+        this.actions = new ArrayList<Class<? extends Action>>(actions);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + ((actions == null) ? 0 : actions.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!super.equals(obj)) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        SupportedFlowActions other = (SupportedFlowActions) obj;
+        if (actions == null) {
+            if (other.actions != null) {
+                return false;
+            }
+        } else if (!actions.equals(other.actions)) {
+            return false;
+        }
+        return true;
+    }
+
+    public List<Class<? extends Action>> getActions() {
+        return new ArrayList<Class<? extends Action>>(this.actions);
+    }
+
+    @XmlElement(name = "value")
+    @Override
+    public String getStringValue() {
+        List<String> nameList = new ArrayList<String>();
+        for (Class<? extends Action> clazz : actions) {
+            nameList.add(clazz.getSimpleName());
+        }
+        Collections.sort(nameList);
+        return nameList.toString();
+    }
+
+    @Override
+    public Property clone() {
+        return new SupportedFlowActions(this.actions);
+    }
+
+    @Override
+    public String toString() {
+        return this.getStringValue();
+    }
+}
index 6cada2c0417788291aa62491513e851645599f08..b3fa45bbc957322d3b0839ac86506d30359def7e 100644 (file)
@@ -20,8 +20,9 @@ import javax.xml.bind.annotation.XmlRootElement;
  * @brief  Class representing actions
  *
  * Describes supported actions
+ * @Deprecated This class is OF 1.0 specific. Use SupportedFlowActions instead.
  */
-
+@Deprecated
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
 public class Actions extends Property {
@@ -92,15 +93,19 @@ public class Actions extends Property {
 
     @Override
     public boolean equals(Object obj) {
-        if (this == obj)
+        if (this == obj) {
             return true;
-        if (!super.equals(obj))
+        }
+        if (!super.equals(obj)) {
             return false;
-        if (getClass() != obj.getClass())
+        }
+        if (getClass() != obj.getClass()) {
             return false;
+        }
         Actions other = (Actions) obj;
-        if (actionsValue != other.actionsValue)
+        if (actionsValue != other.actionsValue) {
             return false;
+        }
         return true;
     }
 
index 7281b9a71ffd7b08e60154e796b61ed5342b907e..54ba4865b2231d9e2b15b299e1b76094285a8c85 100644 (file)
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
+    </dependency>
   </dependencies>
 </project>
index 1a787c7dc12ed38f25df230b39cb25fc92b61509..1e78ec7a3df60a545b6ff6c89d0e15567d44f359 100644 (file)
       <artifactId>junit</artifactId>
     </dependency>
     <dependency>
-        <groupId>equinoxSDK381</groupId>
-        <artifactId>org.apache.felix.gogo.runtime</artifactId>
+      <groupId>equinoxSDK381</groupId>
+      <artifactId>org.apache.felix.gogo.runtime</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>commons.logback_settings</artifactId>
     </dependency>
   </dependencies>
 </project>
index 99482debd6d7e51c84415d3064ed38d05b5ca77e..4d2aea203601dafe6e19fcacc208ae4760819b0f 100644 (file)
@@ -111,6 +111,19 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
     private boolean isDefaultContainer = true;
     private static final int REPLACE_RETRY = 1;
 
+    /* Information about the default subnet. If there have been no configured subnets, i.e.,
+     * subnets.size() == 0 or subnetsConfigList.size() == 0, then this subnet will be the
+     * only subnet returned. As soon as a user-configured subnet is created this one will
+     * vanish.
+     */
+    protected static SubnetConfig DEFAULT_SUBNETCONFIG;
+    protected static Subnet DEFAULT_SUBNET;
+    protected static String DEFAULT_SUBNET_NAME = "default (cannot be modifed)";
+    static{
+        DEFAULT_SUBNETCONFIG = new SubnetConfig(DEFAULT_SUBNET_NAME, "0.0.0.0/0", new ArrayList<String>());
+        DEFAULT_SUBNET = new Subnet(DEFAULT_SUBNETCONFIG);
+    }
+
     public void notifySubnetChange(Subnet sub, boolean add) {
         synchronized (switchManagerAware) {
             for (Object subAware : switchManagerAware) {
@@ -295,12 +308,22 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
 
     @Override
     public List<SubnetConfig> getSubnetsConfigList() {
-        return new ArrayList<SubnetConfig>(subnetsConfigList.values());
+        // if there are no subnets, return the default subnet
+        if(subnetsConfigList.size() == 0){
+            return Collections.singletonList(DEFAULT_SUBNETCONFIG);
+        }else{
+            return new ArrayList<SubnetConfig>(subnetsConfigList.values());
+        }
     }
 
     @Override
     public SubnetConfig getSubnetConfig(String subnet) {
-        return subnetsConfigList.get(subnet);
+        // if there are no subnets, return the default subnet
+        if(subnetsConfigList.size() == 0 && subnet == DEFAULT_SUBNET_NAME){
+            return DEFAULT_SUBNETCONFIG;
+        }else{
+            return subnetsConfigList.get(subnet);
+        }
     }
 
     private List<SpanConfig> getSpanConfigList(Node node) {
@@ -646,6 +669,11 @@ public class SwitchManager implements ISwitchManager, IConfigurationContainerAwa
 
     @Override
     public Subnet getSubnetByNetworkAddress(InetAddress networkAddress) {
+        // if there are no subnets, return the default subnet
+        if (subnets.size() == 0) {
+            return DEFAULT_SUBNET;
+        }
+
         Subnet sub;
         Set<InetAddress> indices = subnets.keySet();
         for (InetAddress i : indices) {
diff --git a/opendaylight/switchmanager/implementation/src/test/resources/logback.xml b/opendaylight/switchmanager/implementation/src/test/resources/logback.xml
deleted file mode 100644 (file)
index 5fa21fe..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<configuration scan="true">\r
-\r
-  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
-    <encoder>\r
-      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
-      </pattern>\r
-    </encoder>\r
-  </appender>\r
-\r
-  <root level="error">\r
-    <appender-ref ref="STDOUT" />\r
-  </root>\r
-</configuration>\r
index 8c6e23f9d3c5b3243e9f842c2739ee67a78319ac..3c28152c25fa0a16e7263d3b69b2fa49f8264306 100644 (file)
@@ -161,16 +161,16 @@ public class DaylightWebAdmin {
      */
     @RequestMapping(value = "/users", method = RequestMethod.POST)
     @ResponseBody
-    public String saveLocalUserConfig(@RequestParam(required = true) String json,
+    public Status saveLocalUserConfig(@RequestParam(required = true) String json,
             @RequestParam(required = true) String action, HttpServletRequest request) {
 
         IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
         if (userManager == null) {
-            return "Internal Error";
+            return new Status(StatusCode.NOSERVICE, "User Manager unavailable");
         }
 
         if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
-            return "Operation not permitted";
+            return new Status(StatusCode.UNAUTHORIZED, "Operation not permitted");
         }
 
         Gson gson = new Gson();
@@ -180,46 +180,87 @@ public class DaylightWebAdmin {
 
         Status result = (action.equals("add")) ? userManager.addLocalUser(config) : userManager.removeLocalUser(config);
         if (result.isSuccess()) {
-            String userAction = (action.equals("add")) ? "added" : "removed";
             if (action.equals("add")) {
-                String userRoles = "";
-                for (String userRole : config.getRoles()) {
-                    userRoles = userRoles + userRole + ",";
-                }
-                DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), userAction, config.getUser()
-                        + " as " + userRoles.substring(0, userRoles.length() - 1));
+                DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "added", config.getUser()
+                        + " as " + config.getRoles().toString());
             } else {
-                DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), userAction, config.getUser());
+                DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "removed", config.getUser());
             }
-            return "Success";
         }
-        return result.getDescription();
+        return result;
     }
 
+    @RequestMapping(value = "/user/modify", method = RequestMethod.POST)
+    @ResponseBody
+    public Status modifyUser(@RequestParam(required = true) String json,
+            @RequestParam(required = true) String action, HttpServletRequest request) {
+
+        IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
+        if (userManager == null) {
+            return new Status(StatusCode.NOSERVICE, "User Manager unavailable");
+        }
+
+        if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
+            return new Status(StatusCode.UNAUTHORIZED, "Operation not permitted");
+        }
+
+        UserConfig newConfig = gson.fromJson(json, UserConfig.class);
+        List<UserConfig> currentUserConfig = userManager.getLocalUserList();
+        String password = null;
+        String user = newConfig.getUser();
+        for (UserConfig userConfig : currentUserConfig) {
+            if(userConfig.getUser().equals(user)){
+                password = userConfig.getPassword();
+                break;
+            }
+        }
+        if (password == null) {
+            String msg = String.format("User %s not found in configuration database", user);
+            return new Status(StatusCode.NOTFOUND, msg);
+        }
+
+        //While modifying a user role, the password is not provided from GUI for any user.
+        //The password is stored in hash mode, hence it cannot be retrieved and added to UserConfig object
+        //The hashed password is injected below to the json string containing username and new roles before
+        //converting to UserConfig object.
+        json = json.replace("\"roles\"", "\"password\":\""+ password + "\",\"roles\"");
+        Gson gson = new Gson();
+        newConfig = gson.fromJson(json, UserConfig.class);
+
+        Status result = userManager.modifyLocalUser(newConfig);
+        if (result.isSuccess()) {
+            DaylightWebUtil.auditlog("Roles of", request.getUserPrincipal().getName(), "updated", newConfig.getUser()
+                    + " to " + newConfig.getRoles().toString());
+        }
+        return result;
+    }
+
+
     @RequestMapping(value = "/users/{username}", method = RequestMethod.POST)
     @ResponseBody
-    public String removeLocalUser(@PathVariable("username") String userName, HttpServletRequest request) {
+    public Status removeLocalUser(@PathVariable("username") String userName, HttpServletRequest request) {
 
-        String username = request.getUserPrincipal().getName();
-        if (username.equals(userName)) {
-            return "Invalid Request: User cannot delete itself";
+        String loggedInUser = request.getUserPrincipal().getName();
+        if (loggedInUser.equals(userName)) {
+            String msg = "Invalid Request: User cannot delete itself";
+            return new Status(StatusCode.NOTALLOWED, msg);
         }
 
         IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
         if (userManager == null) {
-            return "Internal Error";
+            return new Status(StatusCode.NOSERVICE, "User Manager unavailable");
         }
 
         if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
-            return "Operation not permitted";
+            return new Status(StatusCode.UNAUTHORIZED, "Operation not permitted");
         }
 
-        Status result = userManager.removeLocalUser(userName);
-        if (result.isSuccess()) {
+        Status status = userManager.removeLocalUser(userName);
+        if (status.isSuccess()) {
             DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "removed", userName);
-            return "Success";
+            return status;
         }
-        return result.getDescription();
+        return status;
     }
 
     @RequestMapping(value = "/users/password/{username}", method = RequestMethod.POST)
@@ -280,7 +321,7 @@ public class DaylightWebAdmin {
         }
 
         if (status.isSuccess()) {
-            DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), " changed password for User ",
+            DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "changed password for",
                     username);
         }
         return status;
index 6a2efdbf9a730e51fc37bc18a3fd297d91c93535..511e5881ac557ca90ca1fc5192babdcd2c2f74c5 100644 (file)
@@ -142,6 +142,9 @@ one.main.admin = {
         close : "one_main_admin_id_modal_remove_close",
         password : 'one_main_admin_id_modal_remove_password'
       },
+      modify : {
+          user : "one_main_admin_id_modal_modify_user",
+      },
       password : {
         modal : 'one_main_admin_id_modal_password_modal',
         submit : 'one_main_admin_id_modal_password_submit',
@@ -156,10 +159,14 @@ one.main.admin = {
     add : {
       user : "one_main_admin_id_add_user"
     }
+  },
+  registry :{
+
   },
   address : {
     root : "/admin",
     users : "/users",
+    modifyUser : "/user/modify",
     password : '/admin/users/password/'
   },
   modal : {
@@ -195,6 +202,7 @@ one.main.admin = {
       $.getJSON(one.main.admin.address.root
           + one.main.admin.address.users, function(data) {
             var body = one.main.admin.data.users(data);
+            one.main.admin.registry["users"] = data;
             var $body = one.main.admin.body.users(body);
             callback($body);
           });
@@ -258,7 +266,7 @@ one.main.admin = {
   remove : {
     modal : {
       initialize : function(id) {
-        var h3 = "Edit User";
+        var h3 = "Manage user - " + id;
         var footer = one.main.admin.remove.footer();
         var $body = one.main.admin.remove.body();
         var $modal = one.lib.modal.spawn(one.main.admin.id.modal.user,
@@ -267,10 +275,14 @@ one.main.admin = {
         $('#'+one.main.admin.id.modal.remove.close, $modal).click(function() {
           $modal.modal('hide');
         });
+        // close binding
+        $('#'+one.main.admin.id.modal.modify.user, $modal).click(function() {
+          one.main.admin.add.modal.initialize(id, true);
+        });
         // remove binding
         $('#' + one.main.admin.id.modal.remove.user, $modal).click(function() {
           one.main.admin.remove.modal.ajax(id, function(result) {
-            if (result == 'Success') {
+            if (result.description == 'Success') {
               $modal.modal('hide');
               // body inject
               var $admin = $('#'+one.main.admin.id.modal.main);
@@ -278,7 +290,7 @@ one.main.admin = {
                 one.lib.modal.inject.body($admin, $body);
               });
             } else {
-              alert("Failed to remove user: " + result);
+              alert("Failed to remove user: " + result.description);
             }
           });
         });
@@ -302,6 +314,10 @@ one.main.admin = {
           one.main.admin.id.modal.remove.user, "btn-danger", "");
       var $removeButton = one.lib.dashlet.button.button(removeButton);
       footer.push($removeButton);
+      var modifyButton = one.lib.dashlet.button.single("Change Role",
+              one.main.admin.id.modal.modify.user, "btn-success", "");
+      var $modifyButton = one.lib.dashlet.button.button(modifyButton);
+      footer.push($modifyButton);
       var change = one.lib.dashlet.button.single('Change Password',
           one.main.admin.id.modal.remove.password, 'btn-success', '');
       var $change = one.lib.dashlet.button.button(change);
@@ -320,10 +336,10 @@ one.main.admin = {
   },
   add : {
     modal : {
-      initialize : function() {
-        var h3 = "Add User";
-        var footer = one.main.admin.add.footer();
-        var $body = one.main.admin.add.body();
+      initialize : function(id, edit) {
+        var h3 = edit? "Change Role of user " + id:"Add User";
+        var footer = one.main.admin.add.footer(edit);
+        var $body = one.main.admin.add.body(id, edit);
         var $modal = one.lib.modal.spawn(one.main.admin.id.modal.user,
             h3, $body, footer);
         // close binding
@@ -332,73 +348,100 @@ one.main.admin = {
         });
         // add binding
         $('#' + one.main.admin.id.modal.add.user, $modal).click(function() {
-          one.main.admin.add.modal.add($modal, function(result) {
-            if (result == 'Success') {
+          one.main.admin.add.modal.add($modal, edit, function(result) {
+            if (result.description == 'Success') {
               $modal.modal('hide');
               // body inject
               var $admin = $('#'+one.main.admin.id.modal.main);
               one.main.admin.ajax.users(function($body) {
-                one.lib.modal.inject.body($admin, $body);
+               one.lib.modal.inject.body($admin, $body);
               });
             } else {
-              alert("Failed to add user: "+result);
+              var action = edit? "edit" :"add";
+              alert("Failed to "+ action +" user: "+result.description);
             }
           });
         });
         $modal.modal();
       },
-      add : function($modal, callback) {
+      add : function($modal, edit, callback) {
         var user = {};
         user['user'] = $modal.find(
             '#' + one.main.admin.id.modal.add.form.name).val();
-        user['password'] = $modal.find(
-            '#' + one.main.admin.id.modal.add.form.password).val();
+        if (!edit) {
+            user['password'] = $modal.find(
+                '#' + one.main.admin.id.modal.add.form.password).val();
+        }
         roles = new Array();
         roles[0] = $modal.find(
             '#' + one.main.admin.id.modal.add.form.role).find(
               'option:selected').attr('value');
         user['roles'] = roles;
 
-        // password check
-        var verify = $('#'+one.main.admin.id.modal.add.form.verify).val();
-        if (user.password != verify) {
-          alert('Passwords do not match');
-          return false;
+        if (!edit) {
+            // password check
+            var verify = $('#'+one.main.admin.id.modal.add.form.verify).val();
+            if (user.password != verify) {
+              alert('Passwords do not match');
+              return false;
+            }
         }
-
         var resource = {};
         resource['json'] = JSON.stringify(user);
         resource['action'] = 'add'
 
-          one.main.admin.add.modal.ajax(resource, callback);
+        one.main.admin.add.modal.ajax(resource, edit, callback);
       },
-      ajax : function(data, callback) {
-        $.post(one.main.admin.address.root
-            + one.main.admin.address.users, data, function(data) {
-              callback(data);
-            });
+      ajax : function(data, edit, callback) {
+          if(edit) {
+            $.post(one.main.admin.address.root
+              + one.main.admin.address.modifyUser, data, function(data) {
+                callback(data);
+              });
+          } else {  
+            $.post(one.main.admin.address.root
+              + one.main.admin.address.users, data, function(data) {
+                callback(data);
+              });
+          }
       }
     },
-    body : function() {
+    body : function(id, edit) {
       var $form = $(document.createElement('form'));
       var $fieldset = $(document.createElement('fieldset'));
+      var users = one.main.admin.registry["users"];
+      var currentUser;
+      if(edit) {
+        $(users).each(function(index, val) {
+             if(val.user == id){
+            currentUser = val;
+          }
+        });
+      }
+
       // user
       var $label = one.lib.form.label('Username');
       var $input = one.lib.form.input('Username');
       $input.attr('id', one.main.admin.id.modal.add.form.name);
+      if(edit) {
+         $input.attr("disabled",true);
+         $input.val(id);
+      }
       $fieldset.append($label).append($input);
-      // password
-      var $label = one.lib.form.label('Password');
-      var $input = one.lib.form.input('Password');
-      $input.attr('id', one.main.admin.id.modal.add.form.password);
-      $input.attr('type', 'password');
-      $fieldset.append($label).append($input);
-      // password verify
-      var $label = one.lib.form.label('Verify Password');
-      var $input = one.lib.form.input('Verify Password');
-      $input.attr('id', one.main.admin.id.modal.add.form.verify);
-      $input.attr('type', 'password');
-      $fieldset.append($label).append($input);
+      if(!edit) {
+          // password
+          var $label = one.lib.form.label('Password');
+          var $input = one.lib.form.input('Password');
+          $input.attr('id', one.main.admin.id.modal.add.form.password);
+          $input.attr('type', 'password');
+          $fieldset.append($label).append($input);
+          // password verify
+          var $label = one.lib.form.label('Verify Password');
+          var $input = one.lib.form.input('Verify Password');
+          $input.attr('id', one.main.admin.id.modal.add.form.verify);
+          $input.attr('type', 'password');
+          $fieldset.append($label).append($input);
+      }
       // roles
       var $label = one.lib.form.label('Roles');
       var options = {
@@ -407,14 +450,22 @@ one.main.admin = {
       };
       var $select = one.lib.form.select.create(options);
       $select.attr('id', one.main.admin.id.modal.add.form.role);
+      if(edit) {
+          $select.children().each(function() {
+                 this.selected = (this.text == options[currentUser.roles[0]]);
+          });
+      }
+
       $fieldset.append($label).append($select);
       $form.append($fieldset);
       return $form;
     },
-    footer : function() {
+    footer : function(edit) {
       var footer = [];
 
-      var addButton = one.lib.dashlet.button.single("Add User",
+      var buttonText = edit ? "Update User" : "Add User";
+
+      var addButton = one.lib.dashlet.button.single(buttonText,
           one.main.admin.id.modal.add.user, "btn-primary", "");
       var $addButton = one.lib.dashlet.button.button(addButton);
       footer.push($addButton);
@@ -743,4 +794,4 @@ $.ajaxSetup({
 });
 
 /** MAIN PAGE LOAD */
-one.main.menu.load();
+one.main.menu.load();
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index b95cdfd62aaf03027969a0b14e0c30a515e3d8cf..f7f9bc2256b35c72697d4deeaef84e70930521ec 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <module>opendaylight/commons/checkstyle</module>
     <module>opendaylight/commons/opendaylight</module>
     <module>opendaylight/commons/parent</module>
+    <module>opendaylight/commons/logback_settings</module>
   </modules>
 
     <profiles>
                 <module>opendaylight/distribution/sanitytest/</module>
             </modules>
         </profile>
+        <profile>
+           <id>docs</id>
+           <activation>
+               <activeByDefault>false</activeByDefault>
+           </activation>
+            <modules>
+              <module>opendaylight/northbound/java-client</module>
+            </modules>
+        </profile>
     </profiles>
 </project>