Merge "Fix for incorrect request assumption in Update Neutron Port op"
authorEd Warnicke <eaw@cisco.com>
Fri, 8 Nov 2013 11:01:26 +0000 (11:01 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 8 Nov 2013 11:01:26 +0000 (11:01 +0000)
81 files changed:
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/DependencyResolver.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/ModulesHolder.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/TransactionHolder.java
opendaylight/distribution/opendaylight/pom.xml
opendaylight/forwardingrulesmanager_mdsal/openflow/pom.xml
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMConsumerImpl.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FlowConsumerImpl.java
opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/GroupConsumerImpl.java
opendaylight/md-sal/model/model-flow-base/src/main/yang/group-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/meter-types.yang
opendaylight/md-sal/model/model-flow-base/src/main/yang/port-types.yang
opendaylight/md-sal/model/model-flow-management/src/main/yang/meter-config.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-service/src/main/yang/group-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/meter-service.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-service/src/main/yang/table-service.yang
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaServiceListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/pom.xml
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/ConsumerContextImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataConsumerServiceImpl.xtend [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/AbstractBrokerServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataBrokerServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationPublishServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionJsonReaderTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionRegExTest.java [moved from opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversion.java with 51% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java
opendaylight/netconf/netconf-api/pom.xml
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSession.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java
opendaylight/netconf/netconf-client/src/main/resources/client_hello.xml
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/netconf-impl/src/main/resources/server_hello.xml
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java
opendaylight/netconf/netconf-util/pom.xml
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageAggregator.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml [new file with mode: 0644]
opendaylight/netconf/pom.xml
opendaylight/northbound/hosttracker/enunciate.xml
opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java
third-party/com.siemens.ct.exi/pom.xml [new file with mode: 0644]

index 8ff25c35def4f93e9b0d1a98b81f21e5673b96bc..862f809df2587458323a32ac15bf19562e494bb3 100644 (file)
     <java.version.target>1.7</java.version.target>
     <!-- enforcer version -->
     <enforcer.version>1.3.1</enforcer.version>
+    <exi.version>0.9.2</exi.version>
   </properties>
 
   <dependencyManagement>
         <artifactId>org.openflow.openflowj</artifactId>
         <version>1.0.2</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.thirdparty</groupId>
+        <artifactId>exificient</artifactId>
+        <version>${exi.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller.thirdparty</groupId>
         <artifactId>com.sun.jersey.jersey-servlet</artifactId>
index 7cac1060ba6357fd1cdd4e8bc26d4d9bf7118b52..39845454ef5ed17d108255dbf5e47f5b774ab93b 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.config.api;
 import javax.management.ObjectName;
 
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.yangtools.concepts.Identifiable;
 
 /**
  * Each new {@link org.opendaylight.controller.config.spi.Module} can receive
@@ -18,7 +19,7 @@ import org.opendaylight.controller.config.api.annotations.AbstractServiceInterfa
  *
  * @see org.opendaylight.controller.config.spi.Module
  */
-public interface DependencyResolver {
+public interface DependencyResolver extends Identifiable<ModuleIdentifier> {
 
     /**
      * To be used during validation phase to validate serice interface of
index 343d45a236e99bd9208ff4846d13c1e0a43bc571..3f569ae324ebebe51cf0550aa74b21bbcc8d58b8 100644 (file)
@@ -138,8 +138,10 @@ class ConfigTransactionControllerImpl implements
         for (ModuleFactory moduleFactory : toBeAdded) {
             Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, bundleContext);
             for (Module module : defaultModules) {
+                // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
+                DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
                 try {
-                    putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null);
+                    putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver);
                 } catch (InstanceAlreadyExistsException e) {
                     throw new IllegalStateException(e);
                 }
@@ -179,7 +181,7 @@ class ConfigTransactionControllerImpl implements
                     "Error while copying old configuration from %s to %s",
                     oldConfigBeanInfo, moduleFactory), e);
         }
-        putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo);
+        putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver);
     }
 
     @Override
@@ -196,19 +198,24 @@ class ConfigTransactionControllerImpl implements
         DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
         Module module = moduleFactory.createModule(instanceName, dependencyResolver, bundleContext);
         return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
-                moduleFactory, null);
+                moduleFactory, null, dependencyResolver);
     }
 
     private synchronized ObjectName putConfigBeanToJMXAndInternalMaps(
             ModuleIdentifier moduleIdentifier, Module module,
             ModuleFactory moduleFactory,
-            @Nullable ModuleInternalInfo maybeOldConfigBeanInfo)
+            @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver)
             throws InstanceAlreadyExistsException {
+
         logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
         if (moduleIdentifier.equals(module.getIdentifier())==false) {
             throw new IllegalStateException("Incorrect name reported by module. Expected "
              + moduleIdentifier + ", got " + module.getIdentifier());
         }
+        if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false ) {
+            throw new IllegalStateException("Incorrect name reported by dependency resolver. Expected "
+                    + moduleIdentifier + ", got " + dependencyResolver.getIdentifier());
+        }
         DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper(
                 module, moduleIdentifier, transactionIdentifier,
                 readOnlyAtomicBoolean, transactionsMBeanServer,
@@ -224,8 +231,6 @@ class ConfigTransactionControllerImpl implements
                 maybeOldConfigBeanInfo, transactionModuleJMXRegistration);
 
         dependencyResolverManager.put(moduleInternalTransactionalInfo);
-        // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
-        dependencyResolverManager.getOrCreate(moduleIdentifier);
         return writableON;
     }
 
index f817b41c5f929b18f0ff3dfcd7b89003dbd2ea93..065a0f843f501cdb7e2a4230c9cc0b72caf31f3c 100644 (file)
@@ -7,15 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import static java.lang.String.format;
-
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.ObjectName;
-
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
@@ -25,7 +16,14 @@ import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.yangtools.concepts.Identifiable;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.ObjectName;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static java.lang.String.format;
 
 /**
  * Protect {@link org.opendaylight.controller.config.spi.Module#getInstance()}
@@ -33,7 +31,7 @@ import org.opendaylight.yangtools.concepts.Identifiable;
  * during validation. Tracks dependencies for ordering purposes.
  */
 final class DependencyResolverImpl implements DependencyResolver,
-       Identifiable<ModuleIdentifier>, Comparable<DependencyResolverImpl> {
+       Comparable<DependencyResolverImpl> {
     private final ModulesHolder modulesHolder;
     private final ModuleIdentifier name;
     private final TransactionStatus transactionStatus;
@@ -47,11 +45,6 @@ final class DependencyResolverImpl implements DependencyResolver,
         this.modulesHolder = modulesHolder;
     }
 
-    @Deprecated
-    public ModuleIdentifier getName() {
-        return name;
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -177,7 +170,7 @@ final class DependencyResolverImpl implements DependencyResolver,
         int maxDepth = 0;
         LinkedHashSet<ModuleIdentifier> chainForDetectingCycles2 = new LinkedHashSet<>(
                 chainForDetectingCycles);
-        chainForDetectingCycles2.add(impl.getName());
+        chainForDetectingCycles2.add(impl.getIdentifier());
         for (ModuleIdentifier dependencyName : impl.dependencies) {
             DependencyResolverImpl dependentDRI = manager
                     .getOrCreate(dependencyName);
index 28f2e37ec187b5aaec8c18b98b568b4f47cc6dac..dea78c8b155d9f125783232bd7c5b531e673bce0 100644 (file)
@@ -7,15 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.DependencyResolverFactory;
 import org.opendaylight.controller.config.api.JmxAttribute;
@@ -26,6 +17,14 @@ import org.opendaylight.controller.config.manager.impl.TransactionStatus;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Holds information about modules being created and destroyed within this
  * transaction. Observes usage of DependencyResolver within modules to figure
@@ -80,7 +79,7 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR
         List<ModuleIdentifier> result = new ArrayList<>(
                 moduleIdentifiersToDependencyResolverMap.size());
         for (DependencyResolverImpl dri : getAllSorted()) {
-            ModuleIdentifier driName = dri.getName();
+            ModuleIdentifier driName = dri.getIdentifier();
             result.add(driName);
         }
         return result;
index f70c4bf57904b72b2e29d8071f671b2ea4042af5..6bbd7875a94b1fa8a1d4dd8662b2a9cb835420ea 100644 (file)
@@ -7,18 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
@@ -28,6 +16,17 @@ import org.opendaylight.controller.config.manager.impl.ModuleInternalTransaction
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Represents modules to be committed.
  */
@@ -117,8 +116,7 @@ class ModulesHolder implements TransactionHolder {
             throws InstanceAlreadyExistsException {
         if (commitMap.containsKey(moduleIdentifier)) {
             throw new InstanceAlreadyExistsException(
-                    "There is an instance registered with name "
-                            + moduleIdentifier);
+                    "There is an instance registered with name " + moduleIdentifier);
         }
     }
 
index f81e747f620950f71a1e0a217ee52e73d4b068fb..8f05ed75ae74a64d4c45c42969ee32d235880395 100644 (file)
@@ -7,10 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.impl.dependencyresolver;
 
-import java.util.Map;
-
-import javax.management.InstanceAlreadyExistsException;
-
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.manager.impl.CommitInfo;
@@ -18,6 +14,9 @@ import org.opendaylight.controller.config.manager.impl.ModuleInternalTransaction
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 
+import javax.management.InstanceAlreadyExistsException;
+import java.util.Map;
+
 interface TransactionHolder {
     CommitInfo toCommitInfo();
 
index a0d7162b3f524630ecbe944eebe0551abfa07086..1ebab9b03adefcf245319388a6f290ce0c759949 100644 (file)
           <artifactId>config-persister-impl</artifactId>
           <version>${netconf.version}</version>
         </dependency>
-
+        <dependency>
+          <groupId>org.opendaylight.controller.thirdparty</groupId>
+          <artifactId>exificient</artifactId>
+          <version>${exi.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.servicemix.bundles</groupId>
+            <artifactId>org.apache.servicemix.bundles.xerces</artifactId>
+            <version>2.11.0_1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.birt.runtime.3_7_1</groupId>
+            <artifactId>org.apache.xml.resolver</artifactId>
+            <version>1.2.0</version>
+        </dependency>
 
           <!-- toaster example I'm pretty sure we should trim -->
-
          <dependency>
           <groupId>org.opendaylight.controller.samples</groupId>
           <artifactId>sample-toaster</artifactId>
index 9b96f86c92497c70ec8c5b03c0d01aae70538224..29de77270bb6d63c5f791f0ad70cce2eda6d9250 100644 (file)
             <Import-Package>
               org.opendaylight.controller.sal.binding.api,
               org.opendaylight.controller.sal.binding.api.data,
-              org.opendaylight.controller.md.sal.common.api.data,              
-              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow,
+              org.opendaylight.controller.md.sal.common.api.data, 
+              org.opendaylight.controller.sal.utils, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket,
               org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819,
+              org.opendaylight.controller.clustering.services, org.opendaylight.controller.sal.core, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction,
+              org.opendaylight.controller.switchmanager, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list, 
+              org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024,
               org.opendaylight.yangtools.concepts,              
               org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819,
               org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819,
index ae488b689f4788c95d017a07c53cb0ddecb9f0fd..e48e03867c89025fc62babeab7548a8947a27712 100644 (file)
 package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
 
 
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.NotificationService;
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
-public class FRMConsumerImpl extends AbstractBindingAwareProvider {
+public class FRMConsumerImpl extends AbstractBindingAwareProvider implements CommandProvider{
        protected static final Logger logger = LoggerFactory.getLogger(FRMConsumerImpl.class);
        private static ProviderContext p_session;
     private static DataBrokerService dataBrokerService;         
@@ -28,11 +35,21 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
        private GroupConsumerImpl groupImplRef;
        private static DataProviderService dataProviderService;  
 
+       private static IClusterContainerServices clusterContainerService = null;
+       private static ISwitchManager switchManager;
+       private static IContainer container;
+       
        @Override
     public void onSessionInitiated(ProviderContext session) {
        
         FRMConsumerImpl.p_session = session;
         
+        if (!getDependentModule()) {
+            logger.error("Unable to fetch handlers for dependent modules");
+            System.out.println("Unable to fetch handlers for dependent modules");
+            return;
+        }
+        
         if (null != session) {
                notificationService = session.getSALService(NotificationService.class);
                
@@ -44,7 +61,8 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
                                
                                if (null != dataProviderService) {
                                        flowImplRef = new FlowConsumerImpl();
-                                       groupImplRef = new GroupConsumerImpl();
+                       //              groupImplRef = new GroupConsumerImpl();
+                                       registerWithOSGIConsole();
                                }
                                else {
                                        logger.error("Data Provider Service is down or NULL. " +
@@ -68,18 +86,85 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
                System.out.println("Consumer session is NULL. Please check if provider is registered");
         }
   
+    }
+       
+       public static IClusterContainerServices getClusterContainerService() {
+        return clusterContainerService;
+    }
+
+    public static void setClusterContainerService(
+            IClusterContainerServices clusterContainerService) {
+        FRMConsumerImpl.clusterContainerService = clusterContainerService;
+    }
+
+    public static ISwitchManager getSwitchManager() {
+        return switchManager;
+    }
+
+    public static void setSwitchManager(ISwitchManager switchManager) {
+        FRMConsumerImpl.switchManager = switchManager;
+    }
+
+    public static IContainer getContainer() {
+        return container;
     }
 
-       public static DataProviderService getDataProviderService() {
+    public static void setContainer(IContainer container) {
+        FRMConsumerImpl.container = container;
+    }
+
+    private void registerWithOSGIConsole() {
+        BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+        bundleContext.registerService(CommandProvider.class.getName(), this, null);
+    }
+       
+       private boolean getDependentModule() {
+           do {
+        clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(IClusterContainerServices.class, this);
+        try {
+            Thread.sleep(4);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+           } while(clusterContainerService == null);
+           
+           do {
+               
+           
+        container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
+        try {
+            Thread.sleep(5);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+           } while (container == null);
+           
+           do {
+               switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, container.getName(), this);
+               try {
+                   Thread.sleep(5);
+               } catch (InterruptedException e) {
+                   // TODO Auto-generated catch block
+                   e.printStackTrace();
+               }
+           } while(null == switchManager);
+        return true;
+       }
+
+       
+
+    public static DataProviderService getDataProviderService() {
                return dataProviderService;
        }
 
        public FlowConsumerImpl getFlowImplRef() {
-               return flowImplRef;
+           return flowImplRef;
        }
 
        public GroupConsumerImpl getGroupImplRef() {
-                       return groupImplRef;
+           return groupImplRef;
        }
         
        public static ProviderContext getProviderSession() {
@@ -93,6 +178,15 @@ public class FRMConsumerImpl extends AbstractBindingAwareProvider {
        public static DataBrokerService getDataBrokerService() {
                return dataBrokerService;
        }
+       
+       /*
+     * OSGI COMMANDS
+     */
+    @Override
+    public String getHelp() {
+        StringBuffer help = new StringBuffer();
+        return help.toString();
+    }
 
 }
        
diff --git a/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java b/opendaylight/forwardingrulesmanager_mdsal/openflow/src/main/java/org/opendaylight/controller/forwardingrulesmanager_mdsal/consumer/impl/FRMUtil.java
new file mode 100644 (file)
index 0000000..df34d19
--- /dev/null
@@ -0,0 +1,33 @@
+package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket.Actions;
+
+public class FRMUtil {
+    private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
+    public enum operation {ADD, DELETE, UPDATE, GET};
+    
+    
+    public static boolean isNameValid(String name) {
+    
+        //  Name validation 
+        if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) {
+            return false;
+        }
+        return true;
+        
+    }
+    
+    public static boolean areActionsValid(Actions actions) {
+     //   List<Action> actionList;
+       // Action actionRef;
+      //  if (null != actions && null != actions.getAction()) {
+       //     actionList = actions.getAction();
+            
+
+               
+       // }
+        
+        return true;
+    }
+}
index a6a3c71325ed7e644918527ef600fbe739f7faee..59c7e043de823a83a4f6b0318c2d25650bd4b384 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
@@ -27,6 +28,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.Flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 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;
@@ -61,6 +63,7 @@ public class FlowConsumerImpl {
                }
                
                listener = new FlowDataListener();
+               
                if (null == FRMConsumerImpl.getDataBrokerService().registerDataChangeListener(path, listener)) {
                        logger.error("Failed to listen on flow data modifcation events");
                System.out.println("Consumer SAL Service is down or NULL.");
@@ -75,7 +78,7 @@ public class FlowConsumerImpl {
                System.out.println("Consumer SAL Service is down or NULL.");
                return;
                }
-               addFlowTest();
+               //addFlowTest();
                System.out.println("-------------------------------------------------------------------");
                allocateCaches();
                commitHandler = new FlowDataCommitHandler();
@@ -120,11 +123,19 @@ public class FlowConsumerImpl {
     private void addFlow(InstanceIdentifier<?> path, Flow dataObject) {
 
         AddFlowInputBuilder input = new AddFlowInputBuilder();
+        List<Instruction> inst = (dataObject).getInstructions().getInstruction();
         input.setNode((dataObject).getNode());
         input.setPriority((dataObject).getPriority());
         input.setMatch((dataObject).getMatch());
         input.setCookie((dataObject).getCookie());
-        input.setAction((dataObject).getAction());
+        input.setInstructions((dataObject).getInstructions());
+        dataObject.getMatch().getLayer3Match()
+        for (int i=0;i<inst.size();i++) {
+            System.out.println("i = "+ i + inst.get(i).getInstruction().toString());
+            System.out.println("i = "+ i + inst.get(i).toString());
+        }
+        
+        System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
 
         // We send flow to the sounthbound plugin
         flowService.addFlow(input.build());
@@ -132,9 +143,11 @@ public class FlowConsumerImpl {
     
     private void commitToPlugin(internalTransaction transaction) {
         for(Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+            System.out.println("Coming add cc in FlowDatacommitHandler");
             addFlow(entry.getKey(),entry.getValue());
         }
-        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.updates.entrySet()) {
+            System.out.println("Coming update cc in FlowDatacommitHandler");
            // updateFlow(entry.getKey(),entry.getValue());
         }
         
@@ -196,9 +209,11 @@ public class FlowConsumerImpl {
             Flow original = originalSwView.get(key);
             if (original != null) {
                 // It is update for us
+                System.out.println("Coming update  in FlowDatacommitHandler");
                 updates.put(key, flow);
             } else {
                 // It is addition for us
+                System.out.println("Coming add in FlowDatacommitHandler");
                 additions.put(key, flow);
             }
         }
@@ -273,7 +288,7 @@ public class FlowConsumerImpl {
                        for (DataObject dataObject : additions) {
                            if (dataObject instanceof NodeFlow) {
                                NodeRef nodeOne = createNodeRef("foo:node:1");
-                                       // validating the dataObject here
+                                       // validating the dataObject here                               
                                    AddFlowInputBuilder input = new AddFlowInputBuilder();
                                    input.setNode(((NodeFlow) dataObject).getNode());
                                    input.setNode(nodeOne);
@@ -300,18 +315,6 @@ public class FlowConsumerImpl {
         return new NodeRef(path);
     }
            
-         /*  private void loadFlowData() {
        
-                   DataModification modification = (DataModification) dataservice.beginTransaction();
-                   String id = "abc";
-                   FlowKey key = new FlowKey(id, new NodeRef());
-                   InstanceIdentifier<?> path1;
-                   FlowBuilder flow = new FlowBuilder();
-                   flow.setKey(key);
-                   path1 = InstanceIdentifier.builder().node(Flows.class).node(Flow.class, key).toInstance();
-                   DataObject cls = (DataObject) modification.readConfigurationData(path);
-                   modification.putConfigurationData(path, flow.build());
-                   modification.commit();
-               }*/
 
 }
index cc42e21f2a1fc8e0199455f9d7cc65d6b3521183..acc0dc69cd4d059b074fc7691bc1b73d75130170 100644 (file)
@@ -1,7 +1,478 @@
 package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
 
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.Groups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes.GroupType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("unused")
 public class GroupConsumerImpl {
-       public GroupConsumerImpl() {
-               
+    
+    protected static final Logger logger = LoggerFactory.getLogger(GroupConsumerImpl.class);
+    private GroupEventListener groupEventListener = new GroupEventListener();
+    private Registration<NotificationListener> groupListener;
+    private SalGroupService groupService;    
+    private GroupDataCommitHandler commitHandler;
+    
+    private ConcurrentMap<GroupKey, Group> originalSwGroupView;
+    private ConcurrentMap<GroupKey, Group> installedSwGroupView;
+    
+    private ConcurrentMap<Node, List<Group>> nodeGroups;
+    private ConcurrentMap<GroupKey, Group> inactiveGroups;
+    
+    private IClusterContainerServices clusterGroupContainerService = null;
+    private ISwitchManager switchGroupManager;
+    private IContainer container;
+    
+    public GroupConsumerImpl() {
+           InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Groups.class).toInstance();
+        groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
+        
+        clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
+        switchGroupManager = FRMConsumerImpl.getSwitchManager();
+        container = FRMConsumerImpl.getContainer();
+        
+        if (!(cacheStartup())) {
+            logger.error("Unanle to allocate/retrieve group cache");
+            System.out.println("Unable to allocate/retrieve group cache");
+        }
+        
+        if (null == groupService) {
+            logger.error("Consumer SAL Group Service is down or NULL. FRM may not function as intended");
+            System.out.println("Consumer SAL Group Service is down or NULL.");
+            return;
+        }     
+        
+        // For switch events
+        groupListener = FRMConsumerImpl.getNotificationService().registerNotificationListener(groupEventListener);
+        
+        if (null == groupListener) {
+            logger.error("Listener to listen on group data modifcation events");
+            System.out.println("Listener to listen on group data modifcation events.");
+            return;
+        }       
+        
+        commitHandler = new GroupDataCommitHandler();
+        FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
        }
+       
+    private boolean allocateGroupCaches() {
+        if (this.clusterGroupContainerService == null) {
+            logger.warn("Group: Un-initialized clusterGroupContainerService, can't create cache");
+            return false;
+        }       
+
+        try {
+            clusterGroupContainerService.createCache("frm.originalSwGroupView",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+            clusterGroupContainerService.createCache("frm.installedSwGroupView",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+            clusterGroupContainerService.createCache("frm.inactiveGroups",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+            clusterGroupContainerService.createCache("frm.nodeGroups",
+                    EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            
+//TODO for cluster mode
+           /* clusterGroupContainerService.createCache(WORK_STATUS_CACHE,
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
+
+            clusterGroupContainerService.createCache(WORK_ORDER_CACHE,
+                    EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));*/
+            
+        } catch (CacheConfigException cce) {            
+            logger.error("Group CacheConfigException");
+            return false;
+            
+        } catch (CacheExistException cce) {
+            logger.error(" Group CacheExistException");           
+        }
+        
+        return true;
+    }
+    
+    private void nonClusterGroupObjectCreate() {
+        originalSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+        installedSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+        nodeGroups = new ConcurrentHashMap<Node, List<Group>>();        
+        inactiveGroups = new ConcurrentHashMap<GroupKey, Group>();
+    }
+    
+    @SuppressWarnings({ "unchecked" })
+    private boolean retrieveGroupCaches() {
+        ConcurrentMap<?, ?> map;
+
+        if (this.clusterGroupContainerService == null) {
+            logger.warn("Group: un-initialized clusterGroupContainerService, can't retrieve cache");
+            nonClusterGroupObjectCreate();
+            return false;
+        }       
+
+        map = clusterGroupContainerService.getCache("frm.originalSwGroupView");
+        if (map != null) {
+            originalSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+        } else {
+            logger.error("Retrieval of cache(originalSwGroupView) failed");
+            return false;
+        }
+
+        map = clusterGroupContainerService.getCache("frm.installedSwGroupView");
+        if (map != null) {
+            installedSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+        } else {
+            logger.error("Retrieval of cache(installedSwGroupView) failed");
+            return false;
+        }
+
+        map = clusterGroupContainerService.getCache("frm.inactiveGroups");
+        if (map != null) {
+            inactiveGroups = (ConcurrentMap<GroupKey, Group>) map;
+        } else {
+            logger.error("Retrieval of cache(inactiveGroups) failed");
+            return false;
+        }
+
+        map = clusterGroupContainerService.getCache("frm.nodeGroups");
+        if (map != null) {
+            nodeGroups = (ConcurrentMap<Node, List<Group>>) map;
+        } else {
+            logger.error("Retrieval of cache(nodeGroup) failed");
+            return false;
+        }
+        
+        return true;
+    }
+       
+    private boolean cacheStartup() {
+        if (allocateGroupCaches()) {
+            if (retrieveGroupCaches()) {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+    
+    public Status validateGroup(Group group, FRMUtil.operation operation) {
+        String containerName;
+        String groupName;
+        Iterator<Bucket> bucketIterator;
+        boolean returnResult;
+        Buckets groupBuckets;
+        
+        if (null != group) {
+            containerName = group.getContainerName();
+            
+            if (null == containerName) {
+                containerName = GlobalConstants.DEFAULT.toString();
+            }
+            else if (!FRMUtil.isNameValid(containerName)) {
+                logger.error("Container Name is invalid %s" + containerName);
+                return new Status(StatusCode.BADREQUEST, "Container Name is invalid");
+            }
+            
+            groupName = group.getGroupName();
+            if (!FRMUtil.isNameValid(groupName)) {
+                logger.error("Group Name is invalid %s" + groupName);
+                return new Status(StatusCode.BADREQUEST, "Group Name is invalid");
+            }
+            
+            returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName);
+            
+            if (FRMUtil.operation.ADD == operation && returnResult) {
+                logger.error("Record with same Group Name exists");
+                return new Status(StatusCode.BADREQUEST, "Group record exists");
+            }
+            else if (!returnResult) {
+                logger.error("Group record does not exist");
+                return new Status(StatusCode.BADREQUEST, "Group record does not exist");
+            }
+            
+            if (!(group.getGroupType().getIntValue() >= GroupType.GroupAll.getIntValue() && 
+                    group.getGroupType().getIntValue() <= GroupType.GroupFf.getIntValue())) {
+                logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
+                return new Status(StatusCode.BADREQUEST, "Invalid Group type");                
+            }
+            
+            groupBuckets = group.getBuckets();
+                    
+            if (null != groupBuckets && null != groupBuckets.getBucket()) {
+                bucketIterator = groupBuckets.getBucket().iterator();
+                
+                while (bucketIterator.hasNext()) {
+                    if(!(FRMUtil.areActionsValid(bucketIterator.next().getActions()))) {
+                        logger.error("Error in action bucket");
+                        return new Status(StatusCode.BADREQUEST, "Invalid Group bucket contents");
+                    }                                
+                }
+            }                
+        }
+        
+        return new Status(StatusCode.SUCCESS);
+        
+    }
+    
+    private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) {
+        if (! originalSwGroupView.containsKey(key)) {
+            return false;
+        }
+        
+        for (ConcurrentMap.Entry<GroupKey, Group> entry : originalSwGroupView.entrySet()) {
+            if (entry.getValue().getGroupName().equals(groupName)) {
+                if (entry.getValue().getContainerName().equals(containerName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    
+    /**
+     * Update Group entries to the southbound plugin/inventory and our internal database
+     *
+     * @param path
+     * @param dataObject
+     */
+    private Status updateGroup(InstanceIdentifier<?> path, Group groupUpdateDataObject) {
+        GroupKey groupKey = groupUpdateDataObject.getKey();
+        Status groupOperationStatus = validateGroup(groupUpdateDataObject, FRMUtil.operation.UPDATE);
+        
+        if (!groupOperationStatus.isSuccess()) {
+            logger.error("Group data object validation failed %s" + groupUpdateDataObject.getGroupName());
+            return groupOperationStatus;
+        }
+            
+        originalSwGroupView.remove(groupKey);
+        originalSwGroupView.put(groupKey, groupUpdateDataObject);
+        
+        if (groupUpdateDataObject.isInstall()) {
+            UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
+            //TODO how to get original group and modified group. 
+            
+            if (installedSwGroupView.containsKey(groupKey)) {
+                installedSwGroupView.remove(groupKey);
+            }
+            
+            installedSwGroupView.put(groupKey, groupUpdateDataObject);
+            groupService.updateGroup(groupData.build());
+        }
+        
+        return groupOperationStatus;
+    }
+    
+    /**
+     * Adds Group to the southbound plugin and our internal database
+     *
+     * @param path
+     * @param dataObject
+     */
+    private Status addGroup(InstanceIdentifier<?> path, Group groupAddDataObject) {
+        GroupKey groupKey = groupAddDataObject.getKey();
+        Status groupOperationStatus = validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+        
+        if (!groupOperationStatus.isSuccess()) {
+            logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName());
+            return groupOperationStatus;
+        }
+        validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+        originalSwGroupView.put(groupKey, groupAddDataObject);
+        
+        if (groupAddDataObject.isInstall()) {
+            AddGroupInputBuilder groupData = new AddGroupInputBuilder();
+            groupData.setBuckets(groupAddDataObject.getBuckets());
+            groupData.setContainerName(groupAddDataObject.getContainerName());
+            groupData.setGroupId(groupAddDataObject.getGroupId());
+            groupData.setGroupType(groupAddDataObject.getGroupType());
+            groupData.setNode(groupAddDataObject.getNode());  
+            installedSwGroupView.put(groupKey, groupAddDataObject);
+            groupService.addGroup(groupData.build());
+        }
+        
+        return groupOperationStatus;
+    }
+    
+       private RpcResult<Void> commitToPlugin(internalTransaction transaction) {
+        for(Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+            
+            if (!addGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+                return Rpcs.getRpcResult(false, null, null);
+            }
+        }
+        for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+           
+            if (!updateGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+                return Rpcs.getRpcResult(false, null, null);
+            }
+        }
+        
+        for(InstanceIdentifier<?> removal : transaction.removals) {
+           // removeFlow(removal);
+        }
+        
+        return Rpcs.getRpcResult(true, null, null);
+    }
+    
+    private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
+
+         @SuppressWarnings("unchecked")
+        @Override
+         public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+             // We should verify transaction
+             System.out.println("Coming in FlowDatacommitHandler");
+             internalTransaction transaction = new internalTransaction(modification);
+             transaction.prepareUpdate();
+             return transaction;
+         }
+    }
+
+    private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
+
+        private final DataModification<InstanceIdentifier<?>, DataObject> modification;
+
+        @Override
+        public DataModification<InstanceIdentifier<?>, DataObject> getModification() {
+            return modification;
+        }
+
+        public internalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+            this.modification = modification;
+        }
+
+        Map<InstanceIdentifier<?>, Group> additions = new HashMap<>();
+        Map<InstanceIdentifier<?>, Group> updates = new HashMap<>();
+        Set<InstanceIdentifier<?>> removals = new HashSet<>();
+
+        /**
+         * We create a plan which flows will be added, which will be updated and
+         * which will be removed based on our internal state.
+         * 
+         */
+        void prepareUpdate() {
+
+            Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
+            for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
+                if (entry.getValue() instanceof Group) {                    
+                    Group group = (Group) entry.getValue();                    
+                    preparePutEntry(entry.getKey(), group);
+                }
+
+            }
+
+            removals = modification.getRemovedConfigurationData();
+        }
+
+        private void preparePutEntry(InstanceIdentifier<?> key, Group group) {
+            
+            Group original = originalSwGroupView.get(key);
+            if (original != null) {
+                // It is update for us
+                
+                updates.put(key, group);               
+            } else {
+                // It is addition for us
+                
+                additions.put(key, group);
+            }
+        }
+
+        /**
+         * We are OK to go with execution of plan
+         * 
+         */
+        @Override
+        public RpcResult<Void> finish() throws IllegalStateException {
+            
+            RpcResult<Void> rpcStatus = commitToPlugin(this);
+            // We return true if internal transaction is successful.
+          //  return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            return rpcStatus;
+        }
+
+        /**
+         * 
+         * We should rollback our preparation
+         * 
+         */
+        @Override
+        public RpcResult<Void> rollback() throws IllegalStateException {
+            // NOOP - we did not modified any internal state during
+            // requestCommit phase
+           // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+            return Rpcs.getRpcResult(true, null, null);
+            
+        }
+        
+    }
+    
+       
+       final class GroupEventListener implements SalGroupListener {
+           
+        List<GroupAdded> addedGroups = new ArrayList<>();
+        List<GroupRemoved> removedGroups = new ArrayList<>();
+        List<GroupUpdated> updatedGroups = new ArrayList<>();
+       
+
+        @Override
+        public void onGroupAdded(GroupAdded notification) {
+            System.out.println("added Group..........................");
+            addedGroups.add(notification);            
+        }
+
+        @Override
+        public void onGroupRemoved(GroupRemoved notification) {
+            // TODO Auto-generated method stub
+            
+        }
+
+        @Override
+        public void onGroupUpdated(GroupUpdated notification) {
+            // TODO Auto-generated method stub
+            
+        }    
+    }
 }
index 8e77d26ea4afe61eea770873fea7d05a7bbd4818..03e36924e77968ab2815f9b391055945a62dc69b 100644 (file)
@@ -41,6 +41,10 @@ module opendaylight-group-types {
             type string; 
         }
         
+        leaf barrier {
+            type boolean; 
+        }       
+        
         container buckets {
             list bucket {
                 key "order";
index 99d4588cbc85b2491c3f06a346014b9072130b2e..20353af7852bd0b46834e7ad61364b222ec89640 100644 (file)
@@ -85,6 +85,17 @@ module opendaylight-meter-types {
             type meter-id;
         }
         
+        leaf install {
+            type boolean; 
+        }
+        leaf meter-name {
+            type string;
+        }
+        
+        leaf container-name {
+            type string; 
+        }
+        
         container meter-band-headers {
             list meter-band-header {
                 key "order";
index 6a83f75959edd624c35b43bf9de08290197ba89b..8338d185cc36abbbbc34613fe1e3df84d805550a 100644 (file)
@@ -20,10 +20,10 @@ module opendaylight-port-types {
     }
     
     typedef port-state {
-            type enumeration {
-                enum link-down;
-                enum blocked;
-                enum live;
+        type enumeration {
+            enum link-down;
+            enum blocked;
+            enum live;
         }
     }
 
@@ -125,7 +125,7 @@ module opendaylight-port-types {
                 uses common-port;
                 
                 leaf mask {
-                    type uint32;
+                    type port-config;
                     description "Bitmap of OFPPC-* flags to be changed";
                 }      
                 
@@ -135,7 +135,11 @@ module opendaylight-port-types {
             
                 leaf port-name {
                     type string; 
-                }                
+                } 
+
+                leaf barrier {
+                    type boolean; 
+                } 
             }            
         }    
     }
index 579ce70c626227234f7d07fbe7a2451b9fb4f81c..111d3d60faaf29fcfff6e93f05be3bad10b089e5 100644 (file)
@@ -11,11 +11,9 @@ module meter-management {
     }
 
     grouping meter-entry {
-    
         leaf node {
             type inv:node-ref;
         }
-        
         uses meter:meter;
     }   
      
diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang
new file mode 100644 (file)
index 0000000..483c0c9
--- /dev/null
@@ -0,0 +1,46 @@
+module flow-capable-transaction {
+       namespace "urn:opendaylight:flow:transaction";
+    prefix type;
+
+    import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    
+    revision "2013-11-03" {
+        description "Initial revision";
+    }
+
+    typedef transaction-id {
+       type uint64;
+    }
+    
+    grouping transaction-aware {
+        leaf transaction-id {
+            type transaction-id;
+        }
+    }
+
+    rpc get-next-transaction-id {
+        input {
+            leaf node {
+                ext:context-reference "inv:node-context";
+                type inv:node-ref;
+            }
+        }
+        output {
+               uses transaction-aware;
+        }
+    }
+
+    // Barier request?
+    rpc finish-transaction {
+        input {
+            leaf node {
+                ext:context-reference "inv:node-context";
+                type inv:node-ref;
+            }
+            leaf transaction-id {
+                type transaction-id;
+            }
+        }
+    }
+}
\ No newline at end of file
index fba1c0829c96b032f4094f82df13198b8a124730..bb010353280b8fa281c0901dde2e8d771f62ac13 100644 (file)
@@ -6,14 +6,14 @@ module sal-group {
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import ietf-inet-types {prefix inet;revision-date 2010-09-24;}
     import opendaylight-group-types {prefix group-type;revision-date 2013-10-18;}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-09-18" {
         description "Initial revision of group service";
     }        
     
     grouping node-group {
-        uses "inv:node-context-ref";
-        
+        uses "inv:node-context-ref";        
         uses group-type:group;
     }
 
@@ -32,18 +32,30 @@ module sal-group {
     rpc add-group {
         input {
             uses node-group;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc remove-group {
         input {
             uses group-update;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc update-group {
         input {
             uses group-update;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     } 
 
index d3777ff3320468bc55b5307ae6bdff61d016ae23..c187181e5e89099cc4720031cd3fa888629d69a2 100644 (file)
@@ -5,6 +5,7 @@ module sal-meter {
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import opendaylight-meter-types {prefix meter-type;revision-date "2013-09-18";}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-09-18" {
         description "Initial revision of meter service";
@@ -31,18 +32,30 @@ module sal-meter {
     rpc add-meter {
         input {
             uses node-meter;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc remove-meter {
         input {
             uses node-meter;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
 
     rpc update-meter {
         input {
             uses meter-update;
+            uses tr:transaction-aware;            
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }
         
diff --git a/opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang b/opendaylight/md-sal/model/model-flow-service/src/main/yang/port-service.yang
new file mode 100644 (file)
index 0000000..df527ef
--- /dev/null
@@ -0,0 +1,46 @@
+module sal-port {
+    namespace "urn:opendaylight:port:service";
+    prefix port;
+
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+    import opendaylight-port-types {prefix port-type;revision-date "2013-09-25";}
+
+    revision "2013-11-07" {
+        description "Initial revision of port service";
+    }        
+    
+    grouping node-port {
+        uses "inv:node-context-ref";
+        
+        uses port-type:ofp-port-mod;
+    }
+
+    /** Base configuration structure **/
+    grouping port-update {
+        uses "inv:node-context-ref";
+
+        container original-port {
+            uses port-type:ofp-port-mod;
+        }
+        container updated-port {
+            uses port-type:ofp-port-mod;
+        }
+    }
+
+    rpc update-port {
+        input {
+            uses port-update;
+        }
+    }
+     
+    rpc get-port {
+        output {
+            uses port-type:flow-capable-port;
+        }
+    }  
+    
+    notification port-removed {
+        uses node-port;
+    }
+}
\ No newline at end of file
index e740f961d5a83d234342a94aa151d476f001b9cf..3a6f20f77d9554dda1812311e7510414d1a6658a 100644 (file)
@@ -5,13 +5,15 @@ module sal-table {
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";}
+    import flow-capable-transaction {prefix tr;}
 
     revision "2013-10-26" {
         description "Initial revision of table service";
-    }        
+    }
     
     /** Base configuration structure **/
     grouping table-update {
+        uses "inv:node-context-ref";
         container original-table {
             uses table-type:table-features;
         }
@@ -22,11 +24,11 @@ module sal-table {
     
     rpc update-table {
         input {
-            leaf node {
-                ext:context-reference "inv:node-context";
-                type inv:node-ref;
-            }
             uses table-update;
+            uses tr:transaction-aware;
+        }
+        output {
+            uses tr:transaction-aware;
         }
     }     
 }
\ No newline at end of file
index 52f60b3cc28728a7dce4a2435bfe1e97bb6a2e0c..b34c8d4c001b505a3a8e0f4b82d9122d5b6be5ce 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.sal.core.api.model;
 
 import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -39,4 +40,6 @@ public interface SchemaService extends BrokerService {
      * @return
      */
     SchemaContext getGlobalContext();
+    
+    ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener);
 }
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaServiceListener.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaServiceListener.java
new file mode 100644 (file)
index 0000000..d76fd4d
--- /dev/null
@@ -0,0 +1,12 @@
+package org.opendaylight.controller.sal.core.api.model;
+
+import java.util.EventListener;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public interface SchemaServiceListener extends EventListener {
+
+    
+    void onGlobalContextUpdated(SchemaContext context);
+    
+}
index 9383a9e2ff50ee2149d1ce034ed6f195dfb0e7e6..74dd1a99012a0565e16963149fb84f46dc5a6c7f 100644 (file)
@@ -1,79 +1,89 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
-    <modelVersion>4.0.0</modelVersion>\r
-    <parent>\r
-        <groupId>org.opendaylight.controller</groupId>\r
-        <artifactId>sal-parent</artifactId>\r
-        <version>1.0-SNAPSHOT</version>\r
-    </parent>\r
-    <artifactId>sal-broker-impl</artifactId>\r
-    <packaging>bundle</packaging>\r
-    <scm>\r
-        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
-        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
-        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
-    </scm>\r
-\r
-    <dependencies>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-core-api</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-common-util</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-                <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-common-impl</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-common-impl</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.opendaylight.controller</groupId>\r
-            <artifactId>sal-core-spi</artifactId>\r
-            <version>1.0-SNAPSHOT</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.slf4j</groupId>\r
-            <artifactId>slf4j-api</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>com.google.guava</groupId>\r
-            <artifactId>guava</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.eclipse.xtend</groupId>\r
-            <artifactId>org.eclipse.xtend.lib</artifactId>\r
-        </dependency>\r
-    </dependencies>\r
-\r
-    <build>\r
-        <plugins>\r
-            <plugin>\r
-                <groupId>org.apache.felix</groupId>\r
-                <artifactId>maven-bundle-plugin</artifactId>\r
-                <extensions>true</extensions>\r
-                <configuration>\r
-                    <instructions>\r
-                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>\r
-                        <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>\r
-                        <Private-Package>\r
-                            org.opendaylight.controller.sal.dom.broker.*\r
-                        </Private-Package>\r
-                    </instructions>\r
-                </configuration>\r
-            </plugin>\r
-            <plugin>\r
-                <groupId>org.eclipse.xtend</groupId>\r
-                <artifactId>xtend-maven-plugin</artifactId>\r
-            </plugin>\r
-        </plugins>\r
-    </build>\r
-</project>\r
+<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-broker-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-core-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-impl</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-core-spi</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>config-api</artifactId>
+            <version>0.2.2-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <version>0.5.9-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>
+                        <Private-Package>
+                            org.opendaylight.controller.sal.dom.broker.*
+                        </Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
index e3f5e4b4cd15309d85825da7e01ed9e31084a018..2bab4dbd26ca5896f3703978171e5ff72274b9db 100644 (file)
@@ -3,6 +3,10 @@ package org.opendaylight.controller.sal.dom.broker;
 import java.util.Hashtable;
 
 import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
@@ -11,17 +15,35 @@ public class BrokerActivator implements BundleActivator {
 
     BrokerImpl broker;
     private ServiceRegistration<Broker> brokerReg;
-    
+    private ServiceRegistration<SchemaService> schemaReg;
+    private ServiceRegistration<DataBrokerService> dataReg;
+    private ServiceRegistration<DataProviderService> dataProviderReg;
+    private SchemaServiceImpl schemaService;
+    private DataBrokerImpl dataService;
+
     @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, new Hashtable<String,String>());
+        brokerReg = context.registerService(Broker.class, broker, emptyProperties);
+
+        schemaService = new SchemaServiceImpl();
+        schemaService.setContext(context);
+        schemaService.setParser(new YangParserImpl());
+        schemaService.start();
+        schemaReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String, String>());
+        
+        dataService = new DataBrokerImpl();
+        dataReg = context.registerService(DataBrokerService.class, dataService, emptyProperties);
+        dataProviderReg = context.registerService(DataProviderService.class, dataService, emptyProperties);
+        
+        
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        if(brokerReg != null) {
+        if (brokerReg != null) {
             brokerReg.unregister();
         }
     }
index 855ad9bd328d19c79b30e09ba4e485e0d1918044..26fecef688d3cfc748bc1367a5a1e4e5a9d40ac1 100644 (file)
@@ -37,16 +37,13 @@ public class BrokerImpl implements Broker {
     private val Set<ConsumerContextImpl> sessions = Collections.synchronizedSet(new HashSet<ConsumerContextImpl>());
     private val Set<ProviderContextImpl> providerSessions = Collections.synchronizedSet(
         new HashSet<ProviderContextImpl>());
-    private val Set<BrokerModule> modules = Collections.synchronizedSet(new HashSet<BrokerModule>());
-    private val Map<Class<? extends BrokerService>, BrokerModule> serviceProviders = Collections.
-        synchronizedMap(new HashMap<Class<? extends BrokerService>, BrokerModule>());
 
     // Implementation specific
     @Property
     private var ExecutorService executor = Executors.newFixedThreadPool(5);
     @Property
     private var BundleContext bundleContext;
-    
+
     @Property
     private var RpcRouter router;
 
@@ -68,29 +65,6 @@ public class BrokerImpl implements Broker {
         return session;
     }
 
-    public def addModule(BrokerModule module) {
-        log.info("Registering broker module " + module);
-        if(modules.contains(module)) {
-            log.error("Module already registered");
-            throw new IllegalArgumentException("Module already exists.");
-        }
-
-        val provServices = module.getProvidedServices();
-        for (Class<? extends BrokerService> serviceType : provServices) {
-            log.info("  Registering session service implementation: " + serviceType.getCanonicalName());
-            serviceProviders.put(serviceType, module);
-        }
-    }
-
-    public def <T extends BrokerService> T serviceFor(Class<T> service, ConsumerContextImpl session) {
-        val prov = serviceProviders.get(service);
-        if(prov == null) {
-            log.warn("Service " + service.toString() + " is not supported");
-            return null;
-        }
-        return prov.getServiceForSession(service, session);
-    }
-
     protected def Future<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
         val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable<RpcResult<CompositeNode>>);
         return result;
@@ -98,20 +72,20 @@ public class BrokerImpl implements Broker {
 
     // Validation
     private def void checkPredicates(Provider prov) {
-        if(prov == null)
+        if (prov == null)
             throw new IllegalArgumentException("Provider should not be null.");
         for (ProviderContextImpl session : providerSessions) {
-            if(prov.equals(session.getProvider()))
+            if (prov.equals(session.getProvider()))
                 throw new IllegalStateException("Provider already registered");
         }
 
     }
 
     private def void checkPredicates(Consumer cons) {
-        if(cons == null)
+        if (cons == null)
             throw new IllegalArgumentException("Consumer should not be null.");
         for (ConsumerContextImpl session : sessions) {
-            if(cons.equals(session.getConsumer()))
+            if (cons.equals(session.getConsumer()))
                 throw new IllegalStateException("Consumer already registered");
         }
     }
index 6d57a4e2247392089f4a0895b439e8f2d3c84b76..9f21823e3efb33c56e841fc1ad2af52ba481ad7f 100644 (file)
@@ -1,13 +1,15 @@
 package org.opendaylight.controller.sal.dom.broker
 
-import java.util.Collections
 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
-import java.util.HashMap
 import org.opendaylight.controller.sal.core.api.BrokerService
 import org.opendaylight.controller.sal.core.api.Consumer
 import org.osgi.framework.BundleContext
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy
+import com.google.common.collect.ClassToInstanceMap
+import com.google.common.collect.MutableClassToInstanceMap
+import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory
 
 class ConsumerContextImpl implements ConsumerSession {
 
@@ -17,8 +19,7 @@ class ConsumerContextImpl implements ConsumerSession {
     @Property
     private var BrokerImpl broker;
 
-    private val instantiatedServices = Collections.synchronizedMap(
-        new HashMap<Class<? extends BrokerService>, BrokerService>());
+    private val ClassToInstanceMap<BrokerService> instantiatedServices = MutableClassToInstanceMap.create();
     private boolean closed = false;
 
     private BundleContext context;
@@ -33,14 +34,20 @@ class ConsumerContextImpl implements ConsumerSession {
     }
 
     override <T extends BrokerService> T getService(Class<T> service) {
-        val potential = instantiatedServices.get(service);
-        if(potential != null) {
-            val ret = potential as T;
-            return ret;
+        val localProxy = instantiatedServices.getInstance(service);
+        if(localProxy != null) {
+            return localProxy;
         }
-        val ret = broker.serviceFor(service, this);
+        val serviceRef = context.getServiceReference(service);
+        if(serviceRef == null) {
+            return null;
+        }
+        val serviceImpl = context.getService(serviceRef);
+        
+        
+        val ret = ProxyFactory.createProxy(serviceRef,serviceImpl);
         if(ret != null) {
-            instantiatedServices.put(service, ret);
+            instantiatedServices.putInstance(service, ret);
         }
         return ret;
     }
@@ -49,7 +56,9 @@ class ConsumerContextImpl implements ConsumerSession {
         val toStop = instantiatedServices.values();
         this.closed = true;
         for (BrokerService brokerService : toStop) {
-            //brokerService.closeSession();
+            if(brokerService instanceof AbstractBrokerServiceProxy<?>) {
+                (brokerService as AutoCloseable).close();
+            } 
         }
         broker.consumerSessionClosed(this);
     }
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
new file mode 100644 (file)
index 0000000..8a17c83
--- /dev/null
@@ -0,0 +1,63 @@
+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/DataConsumerServiceImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataConsumerServiceImpl.xtend
deleted file mode 100644 (file)
index 3bccc4e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.opendaylight.controller.sal.dom.broker
-
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.common.DataStoreIdentifier
-import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener
-
-class DataConsumerServiceImpl implements DataBrokerService {
-    
-    override beginTransaction() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-
-    override readConfigurationData(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-    
-    override readOperationalData(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-    }
-    
-    override registerDataChangeListener(InstanceIdentifier path, DataChangeListener listener) {
-        throw new UnsupportedOperationException("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/SchemaServiceImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/SchemaServiceImpl.java
new file mode 100644 (file)
index 0000000..ba558c5
--- /dev/null
@@ -0,0 +1,281 @@
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.Checksum;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.*;
+
+public class SchemaServiceImpl implements SchemaService, AutoCloseable {
+    private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class);
+
+    private ListenerRegistry<SchemaServiceListener> listeners;
+    private YangModelParser parser;
+
+    private BundleContext context;
+    private BundleScanner scanner = new BundleScanner();
+
+    /**
+     * Map of currently problematic yang files that should get fixed eventually
+     * after all events are received.
+     */
+    private final Multimap<Bundle, URL> inconsistentBundlesToYangURLs = HashMultimap.create();
+    private final Multimap<Bundle, URL> consistentBundlesToYangURLs = HashMultimap.create();
+    private BundleTracker<Object> bundleTracker;
+    private final YangStoreCache cache = new YangStoreCache();
+
+    public ListenerRegistry<SchemaServiceListener> getListeners() {
+        return listeners;
+    }
+
+    public void setListeners(ListenerRegistry<SchemaServiceListener> listeners) {
+        this.listeners = listeners;
+    }
+
+    public YangModelParser getParser() {
+        return parser;
+    }
+
+    public void setParser(YangModelParser parser) {
+        this.parser = parser;
+    }
+
+    public BundleContext getContext() {
+        return context;
+    }
+
+    public void setContext(BundleContext context) {
+        this.context = context;
+    }
+
+    public void start() {
+        checkState(parser != null);
+        checkState(context != null);
+        if (listeners == null) {
+            listeners = new ListenerRegistry<>();
+        }
+
+        bundleTracker = new BundleTracker<Object>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
+        bundleTracker.open();
+    }
+
+    public SchemaContext getGlobalContext() {
+        return getSchemaContextSnapshot();
+    }
+
+    public synchronized SchemaContext getSchemaContextSnapshot() {
+        Optional<SchemaContext> yangStoreOpt = cache.getCachedSchemaContext(consistentBundlesToYangURLs);
+        if (yangStoreOpt.isPresent()) {
+            return yangStoreOpt.get();
+        }
+        SchemaContext snapshot = createSnapshot(parser, consistentBundlesToYangURLs);
+        updateCache(snapshot);
+        return snapshot;
+    }
+
+    @Override
+    public void addModule(Module module) {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public SchemaContext getSessionContext() {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void removeModule(Module module) {
+        // TODO Auto-generated method stub
+        throw new UnsupportedOperationException();
+    }
+
+    
+    @Override
+    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+        return listeners.register(listener);
+    }
+    
+    @Override
+    public void close() throws Exception {
+        bundleTracker.close();
+        // FIXME: Add listeners.close();
+
+    }
+
+    private synchronized boolean tryToUpdateState(Collection<URL> changedURLs, Multimap<Bundle, URL> proposedNewState,
+            boolean adding) {
+        Preconditions.checkArgument(changedURLs.size() > 0, "No change can occur when no URLs are changed");
+
+        try {
+            // consistent state
+            // merge into
+            SchemaContext snapshot = createSnapshot(parser, proposedNewState);
+            consistentBundlesToYangURLs.clear();
+            consistentBundlesToYangURLs.putAll(proposedNewState);
+            inconsistentBundlesToYangURLs.clear();
+            // update cache
+            updateCache(snapshot);
+            logger.info("SchemaService updated to new consistent state");
+            logger.trace("SchemaService  updated to new consistent state containing {}", consistentBundlesToYangURLs);
+
+            // notifyListeners(changedURLs, adding);
+            return true;
+        } catch (Exception e) {
+            // inconsistent state
+            logger.debug(
+                    "SchemaService is falling back on last consistent state containing {}, inconsistent yang files {}, reason {}",
+                    consistentBundlesToYangURLs, inconsistentBundlesToYangURLs, e.toString());
+            return false;
+        }
+    }
+
+    private static Collection<InputStream> fromUrlsToInputStreams(Multimap<Bundle, URL> multimap) {
+        return Collections2.transform(multimap.values(), new Function<URL, InputStream>() {
+
+            @Override
+            public InputStream apply(URL url) {
+                try {
+                    return url.openStream();
+                } catch (IOException e) {
+                    logger.warn("Unable to open stream from {}", url);
+                    throw new IllegalStateException("Unable to open stream from " + url, e);
+                }
+            }
+        });
+    }
+
+    private static SchemaContext createSnapshot(YangModelParser parser, Multimap<Bundle, URL> multimap) {
+        List<InputStream> models = new ArrayList<>(fromUrlsToInputStreams(multimap));
+        Set<Module> modules = parser.parseYangModelsFromStreams(models);
+        SchemaContext yangStoreSnapshot = parser.resolveSchemaContext(modules);
+        return yangStoreSnapshot;
+    }
+
+    private void updateCache(SchemaContext snapshot) {
+        cache.cacheYangStore(consistentBundlesToYangURLs, snapshot);
+        for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
+            try {
+                listener.getInstance().onGlobalContextUpdated(snapshot);
+            } catch (Exception e) {
+                logger.error("Exception occured during invoking listener",e);
+            }
+        }
+    }
+
+    private class BundleScanner implements BundleTrackerCustomizer<Object> {
+        @Override
+        public Object addingBundle(Bundle bundle, BundleEvent event) {
+
+            // Ignore system bundle:
+            // system bundle might have config-api on classpath &&
+            // config-api contains yang files =>
+            // system bundle might contain yang files from that bundle
+            if (bundle.getBundleId() == 0)
+                return bundle;
+
+            Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
+            if (enumeration != null && enumeration.hasMoreElements()) {
+                synchronized (this) {
+                    List<URL> addedURLs = new ArrayList<>();
+                    while (enumeration.hasMoreElements()) {
+                        URL url = enumeration.nextElement();
+                        addedURLs.add(url);
+                    }
+                    logger.trace("Bundle {} has event {}, bundle state {}, URLs {}", bundle, event, bundle.getState(),
+                            addedURLs);
+                    // test that yang store is consistent
+                    Multimap<Bundle, URL> proposedNewState = HashMultimap.create(consistentBundlesToYangURLs);
+                    proposedNewState.putAll(inconsistentBundlesToYangURLs);
+                    proposedNewState.putAll(bundle, addedURLs);
+                    boolean adding = true;
+                    if (tryToUpdateState(addedURLs, proposedNewState, adding) == false) {
+                        inconsistentBundlesToYangURLs.putAll(bundle, addedURLs);
+                    }
+                }
+            }
+            return bundle;
+        }
+
+        @Override
+        public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+            logger.debug("Modified bundle {} {} {}", bundle, event, object);
+        }
+
+        /**
+         * If removing YANG files makes yang store inconsistent, method
+         * {@link #getYangStoreSnapshot()} will throw exception. There is no
+         * rollback.
+         */
+
+        @Override
+        public synchronized void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+            inconsistentBundlesToYangURLs.removeAll(bundle);
+            Collection<URL> consistentURLsToBeRemoved = consistentBundlesToYangURLs.removeAll(bundle);
+
+            if (consistentURLsToBeRemoved.isEmpty()) {
+                return; // no change
+            }
+            boolean adding = false;
+            // notifyListeners(consistentURLsToBeRemoved, adding);
+        }
+    }
+
+    private static final class YangStoreCache {
+
+        Set<URL> cachedUrls;
+        SchemaContext cachedContextSnapshot;
+
+        Optional<SchemaContext> getCachedSchemaContext(Multimap<Bundle, URL> bundlesToYangURLs) {
+            Set<URL> urls = setFromMultimapValues(bundlesToYangURLs);
+            if (cachedUrls != null && cachedUrls.equals(urls)) {
+                Preconditions.checkState(cachedContextSnapshot != null);
+                return Optional.of(cachedContextSnapshot);
+            }
+            return Optional.absent();
+        }
+
+        private static Set<URL> setFromMultimapValues(Multimap<Bundle, URL> bundlesToYangURLs) {
+            Set<URL> urls = Sets.newHashSet(bundlesToYangURLs.values());
+            Preconditions.checkState(bundlesToYangURLs.size() == urls.size());
+            return urls;
+        }
+
+        void cacheYangStore(Multimap<Bundle, URL> urls, SchemaContext ctx) {
+            this.cachedUrls = setFromMultimapValues(urls);
+            this.cachedContextSnapshot = ctx;
+        }
+
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/AbstractBrokerServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/AbstractBrokerServiceProxy.java
new file mode 100644 (file)
index 0000000..7e3d9be
--- /dev/null
@@ -0,0 +1,68 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.osgi.framework.ServiceReference;
+import static com.google.common.base.Preconditions.*;
+
+public abstract class AbstractBrokerServiceProxy<T extends BrokerService> implements AutoCloseable, BrokerService {
+
+    private T delegate;
+    private final ServiceReference<T> reference;
+
+    public AbstractBrokerServiceProxy(ServiceReference<T> ref, T delegate) {
+        this.delegate = checkNotNull(delegate, "Delegate should not be null.");
+        this.reference = checkNotNull(ref, "Reference should not be null.");
+    }
+
+    protected final T getDelegate() {
+        checkState(delegate != null, "Proxy was closed and unregistered.");
+        return delegate;
+    }
+
+    protected final ServiceReference<T> getReference() {
+        return reference;
+    }
+
+    private Set<Registration<?>> registrations = Collections.synchronizedSet(new HashSet<Registration<?>>());
+
+    protected <R extends Registration<?>> R addRegistration(R registration) {
+        if (registration != null) {
+            registrations.add(registration);
+        }
+        return registration;
+    }
+
+    protected void closeBeforeUnregistrations() {
+        // NOOP
+    }
+
+    protected void closeAfterUnregistrations() {
+        // NOOP
+    }
+
+    @Override
+    public void close() {
+        if (delegate != null) {
+            delegate = null;
+            RuntimeException potentialException = new RuntimeException(
+                    "Uncaught exceptions occured during unregistration");
+            boolean hasSuppressed = false;
+            for (Registration<?> registration : registrations) {
+                try {
+                    registration.close();
+                } catch (Exception e) {
+                    potentialException.addSuppressed(e);
+                    hasSuppressed = true;
+                }
+            }
+            if (hasSuppressed) {
+                throw potentialException;
+            }
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataBrokerServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataBrokerServiceProxy.java
new file mode 100644 (file)
index 0000000..3eb7e22
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataBrokerServiceProxy extends AbstractBrokerServiceProxy<DataBrokerService> implements DataBrokerService {
+
+    public DataBrokerServiceProxy(ServiceReference<DataBrokerService> ref, DataBrokerService delegate) {
+        super(ref, delegate);
+    }
+
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+            DataChangeListener listener) {
+        return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+    }
+
+    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        return getDelegate().readConfigurationData(path);
+    }
+
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        return getDelegate().readOperationalData(path);
+    }
+
+    public DataModificationTransaction beginTransaction() {
+        return getDelegate().beginTransaction();
+    }
+    
+    
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/DataProviderServiceProxy.java
new file mode 100644 (file)
index 0000000..2fded87
--- /dev/null
@@ -0,0 +1,77 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataProviderServiceProxy extends AbstractBrokerServiceProxy<DataProviderService> implements
+        DataProviderService {
+
+    public DataProviderServiceProxy(ServiceReference<DataProviderService> ref, DataProviderService delegate) {
+        super(ref, delegate);
+    }
+
+    public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+            DataChangeListener listener) {
+        return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+    }
+
+    public CompositeNode readConfigurationData(InstanceIdentifier path) {
+        return getDelegate().readConfigurationData(path);
+    }
+
+    public CompositeNode readOperationalData(InstanceIdentifier path) {
+        return getDelegate().readOperationalData(path);
+    }
+
+    public DataModificationTransaction beginTransaction() {
+        return getDelegate().beginTransaction();
+    }
+
+    @Override
+    public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        getDelegate().addRefresher(store, refresher);
+    }
+
+    @Override
+    public void addValidator(DataStoreIdentifier store, DataValidator validator) {
+        getDelegate().addValidator(store, validator);
+    }
+
+    @Override
+    public Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> registerCommitHandler(
+            InstanceIdentifier path, DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
+        return addRegistration(getDelegate().registerCommitHandler(path, commitHandler));
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return addRegistration(getDelegate().registerConfigurationReader(path, reader));
+    }
+
+    @Override
+    public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
+            InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+        return addRegistration(getDelegate().registerOperationalReader(path, reader));
+    }
+
+    @Override
+    public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+        getDelegate().removeRefresher(store, refresher);
+    }
+
+    @Override
+    public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+        getDelegate().removeValidator(store, validator);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationPublishServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationPublishServiceProxy.java
new file mode 100644 (file)
index 0000000..170517b
--- /dev/null
@@ -0,0 +1,29 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationPublishServiceProxy extends AbstractBrokerServiceProxy<NotificationPublishService> implements NotificationPublishService {
+
+    public NotificationPublishServiceProxy(ServiceReference<NotificationPublishService> ref,
+            NotificationPublishService delegate) {
+        super(ref, delegate);
+    }
+
+    public void sendNotification(CompositeNode notification) {
+        getDelegate().sendNotification(notification);
+    }
+
+    public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+        return addRegistration(getDelegate().addNotificationListener(notification, listener));
+
+    }
+
+    public void publish(CompositeNode notification) {
+        getDelegate().publish(notification);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/NotificationServiceProxy.java
new file mode 100644 (file)
index 0000000..d685370
--- /dev/null
@@ -0,0 +1,20 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationServiceProxy extends AbstractBrokerServiceProxy<NotificationService> implements
+        NotificationService {
+
+    public NotificationServiceProxy(ServiceReference<NotificationService> ref, NotificationService delegate) {
+        super(ref, delegate);
+    }
+
+    @Override
+    public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+        return addRegistration(getDelegate().addNotificationListener(notification, listener));
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/ProxyFactory.xtend
new file mode 100644 (file)
index 0000000..eb73867
--- /dev/null
@@ -0,0 +1,41 @@
+package org.opendaylight.controller.sal.dom.broker.osgi
+
+import org.opendaylight.controller.sal.core.api.BrokerService
+import org.osgi.framework.ServiceReference
+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.notify.NotificationPublishService
+import org.opendaylight.controller.sal.core.api.notify.NotificationService
+import org.opendaylight.controller.sal.core.api.model.SchemaService
+
+class ProxyFactory {
+
+    static def <T extends BrokerService> T createProxy(ServiceReference<T> serviceRef, T service) {
+        return createProxyImpl(serviceRef, service) as T;
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, DataBrokerService service) {
+        new DataBrokerServiceProxy(ref as ServiceReference<DataBrokerService>, service);
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, DataProviderService service) {
+        new DataProviderServiceProxy(ref as ServiceReference<DataProviderService>, service);
+    }
+    
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationPublishService service) {
+        new NotificationPublishServiceProxy(ref as ServiceReference<NotificationPublishService>, service);
+    }
+    
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationService service) {
+        new NotificationServiceProxy(ref as ServiceReference<NotificationService>, service);
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> ref, SchemaService service) {
+        new SchemaServiceProxy(ref as ServiceReference<SchemaService>, service);
+    }
+
+    private static def dispatch createProxyImpl(ServiceReference<?> reference, BrokerService service) {
+        throw new IllegalArgumentException("Not supported class");
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java
new file mode 100644 (file)
index 0000000..8938bf2
--- /dev/null
@@ -0,0 +1,45 @@
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.framework.ServiceReference;
+
+public class SchemaServiceProxy extends AbstractBrokerServiceProxy<SchemaService> implements SchemaService {
+
+    public SchemaServiceProxy(ServiceReference<SchemaService> ref, SchemaService delegate) {
+        super(ref, delegate);
+    }
+
+    @Override
+    public void addModule(Module module) {
+        getDelegate().addModule(module);
+    }
+
+    @Override
+    public void removeModule(Module module) {
+        getDelegate().removeModule(module);
+    }
+
+    @Override
+    public SchemaContext getSessionContext() {
+        return null;
+    }
+
+    @Override
+    public SchemaContext getGlobalContext() {
+        return getDelegate().getGlobalContext();
+    }
+
+    @Override
+    public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+        ListenerRegistration<SchemaServiceListener> registration = getDelegate().registerSchemaServiceListener(listener);
+        addRegistration(registration);
+        return registration;
+    }
+
+    
+    
+}
index b4cf6c985b6aa8a9995ccb43ed4c27fe6f494166..c6296eb7ea14ce82726dcd080b548dc375e26940 100644 (file)
@@ -1,15 +1,14 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.*;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
+import javax.ws.rs.WebApplicationException;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
@@ -18,12 +17,13 @@ import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.*;
 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.slf4j.Logger;
@@ -114,5 +114,135 @@ final class TestUtils {
         }
 
     }
+    
+    static String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+        String jsonResult = null;
+        Set<Module> modules = null;
+
+        try {
+            modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("modules can't be null.", modules);
+
+        InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+        CompositeNode compositeNode = null;
+        try {
+            compositeNode = TestUtils.loadCompositeNode(xmlStream);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("Composite node can't be null", compositeNode);
+
+        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+        for (Module module : modules) {
+            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+                try {
+                    structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+                } catch (WebApplicationException | IOException e) {
+                    e.printStackTrace();
+                }
+                assertFalse(
+                        "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+                        byteArrayOS.toString().isEmpty());
+                jsonResult = byteArrayOS.toString();
+                try {
+                    outputToFile(byteArrayOS);
+                } catch (IOException e) {
+                    System.out.println("Output file wasn't cloased sucessfuly.");
+                }
+            }
+        }
+        return jsonResult;
+    }
+    
+    static void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+        FileOutputStream fileOS = null;
+        try {
+            String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+            File outFile = new File(path + "/data.json");
+            fileOS = new FileOutputStream(outFile);
+            try {
+                fileOS.write(outputStream.toByteArray());
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            fileOS.close();
+        } catch (FileNotFoundException e1) {
+            e1.printStackTrace();
+        }
+    }    
+    
+    static String readJsonFromFile(String path,boolean removeWhiteChars) {
+        FileReader fileReader = getFileReader(path);
+
+        StringBuilder strBuilder = new StringBuilder();
+        char[] buffer = new char[1000];
+
+        while (true) {
+            int loadedCharNum;
+            try {
+                loadedCharNum = fileReader.read(buffer);
+            } catch (IOException e) {
+                break;
+            }
+            if (loadedCharNum == -1) {
+                break;
+            }
+            strBuilder.append(buffer, 0, loadedCharNum);
+        }
+        try {
+            fileReader.close();
+        } catch (IOException e) {
+            System.out.println("The file wasn't closed");
+        }
+        String rawStr = strBuilder.toString();
+        if (removeWhiteChars) {        
+            rawStr = rawStr.replace("\n", "");
+            rawStr = rawStr.replace("\r", "");
+            rawStr = rawStr.replace("\t", "");
+            rawStr = removeSpaces(rawStr);
+        }
+
+        return rawStr;
+    }
+    
+    private static FileReader getFileReader(String path) {
+        String fullPath = YangAndXmlToJsonConversionJsonReaderTest.class.getResource(path).getPath();
+        assertNotNull("Path to file can't be null.", fullPath);
+        File file = new File(fullPath);
+        assertNotNull("File can't be null", file);
+        FileReader fileReader = null;
+        try {
+            fileReader = new FileReader(file);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        assertNotNull("File reader can't be null.", fileReader);
+        return fileReader;
+    }
+
+    private static String removeSpaces(String rawStr) {
+        StringBuilder strBuilder = new StringBuilder();
+        int i = 0;
+        int quoteCount = 0;
+        while (i < rawStr.length()) {
+            if (rawStr.substring(i, i + 1).equals("\"")) {
+                quoteCount++;
+            }
+
+            if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
+                strBuilder.append(rawStr.charAt(i));
+            }
+            i++;
+        }
+
+        return strBuilder.toString();
+    }    
+    
+    
 
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionJsonReaderTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/YangAndXmlToJsonConversionJsonReaderTest.java
new file mode 100644 (file)
index 0000000..0f39088
--- /dev/null
@@ -0,0 +1,243 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.*;
+import java.util.*;
+
+import org.junit.Test;
+
+import com.google.gson.stream.JsonReader;
+
+public class YangAndXmlToJsonConversionJsonReaderTest {
+
+    @Test
+    public void simpleYangTypesWithJsonReaderTest() {
+        String jsonOutput;
+        jsonOutput = TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",
+                false);
+
+//        jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+//                "/yang-to-json-conversion/simple-yang-types");
+        
+        StringReader strReader = new StringReader(jsonOutput);
+        JsonReader jReader = new JsonReader(strReader);
+        try {
+            checkCont1(jReader);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void checkCont1(JsonReader jReader) throws IOException {
+        jReader.beginObject();
+        assertNotNull("cont1 is missing.", jReader.hasNext());
+        jReader.nextName();
+        checkCont1Elements(jReader, prepareInputData(jReader), "cont1/");
+        jReader.endObject();
+
+    }
+
+    private Map<String, String> prepareInputData(JsonReader jReader) {
+        Map<String, String> dataMap = new HashMap<>();
+        dataMap.put("cont1/lf11", "lf");
+        dataMap.put("cont1/lflst11.1", "55");
+        dataMap.put("cont1/lflst11.2", "56");
+        dataMap.put("cont1/lflst11.3", "57");
+        dataMap.put("cont1/lflst12.1", "lflst12 str1");
+        dataMap.put("cont1/lflst12.2", "lflst12 str2");
+        dataMap.put("cont1/lflst12.3", "lflst12 str3");
+
+        dataMap.put("cont1/lst11.1/lf111", "140");
+        dataMap.put("cont1/lst11.1/lf112", "lf112 str");
+        dataMap.put("cont1/lst11.1/cont111/lf1111", "lf1111 str");
+        dataMap.put("cont1/lst11.1/cont111/lflst1111.1", "2048");
+        dataMap.put("cont1/lst11.1/cont111/lflst1111.2", "1024");
+        dataMap.put("cont1/lst11.1/cont111/lflst1111.3", "4096");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111A", "lf1111A str11");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111B", "4");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111A", "lf1111A str12");
+        dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111B", "7");
+        dataMap.put("cont1/lst11.1/lst111.1/lf1111", "65");
+        dataMap.put("cont1/lst11.1/lst112.1/lf1121", "lf1121 str11");
+
+        dataMap.put("cont1/lst11.2/lf111", "141");
+        dataMap.put("cont1/lst11.2/lf112", "lf112 str2");
+        dataMap.put("cont1/lst11.2/cont111/lf1111", "lf1111 str2");
+        dataMap.put("cont1/lst11.2/cont111/lflst1111.1", "2049");
+        dataMap.put("cont1/lst11.2/cont111/lflst1111.2", "1025");
+        dataMap.put("cont1/lst11.2/cont111/lflst1111.3", "4097");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111A", "lf1111A str21");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111B", "5");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111A", "lf1111A str22");
+        dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111B", "8");
+        dataMap.put("cont1/lst11.2/lst111.1/lf1111", "55");
+        dataMap.put("cont1/lst11.2/lst111.2/lf1111", "56");
+        dataMap.put("cont1/lst11.2/lst112.1/lf1121", "lf1121 str21");
+        dataMap.put("cont1/lst11.2/lst112.2/lf1121", "lf1121 str22");
+
+        return dataMap;
+
+    }
+
+    private void checkCont1Elements(JsonReader jReader, Map<String, String> dataMap, String pthPref) throws IOException {
+        Set<String> keys = new HashSet<>();
+        jReader.beginObject();
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf11")) {
+                assertEquals("Key " + keyName + " has incorrect value.", dataMap.get(pthPref + keyName),
+                        jReader.nextString());
+                keys.add(keyName);
+            } else if (keyName.equals("lflst11")) {
+                checkLflstValues(jReader, pthPref + keyName, dataMap);
+                keys.add(keyName);
+            } else if (keyName.equals("lflst12")) {
+                checkLflstValues(jReader, pthPref + keyName, dataMap);
+                keys.add(keyName);
+            } else if (keyName.equals("lst11")) {
+                checkLst11(jReader, pthPref + keyName, dataMap);
+                keys.add(keyName);
+            } else {
+                assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+            }
+        }
+        jReader.endObject();
+        assertEquals("Incorrect number of keys in cont1", 4, keys.size());
+
+    }
+
+    private void checkLst11(JsonReader jReader, String pthPref, Map<String, String> dataMap) throws IOException {
+        jReader.beginArray();
+
+        int arrayLength = 0;
+        while (jReader.hasNext()) {
+            checkLst11Elements(jReader, pthPref + "." + ++arrayLength + "/", dataMap);
+        }
+        jReader.endArray();
+        assertEquals("Incorrect number of items in lst11 array.", 2, arrayLength);
+    }
+
+    private void checkLst11Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf111")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            } else if (keyName.equals("lf112")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            } else if (keyName.equals("cont111")) {
+                checkCont111(jReader, pthPref + keyName, data);
+            } else if (keyName.equals("lst111")) {
+                checkLst111(jReader, pthPref + keyName, data);
+            } else if (keyName.equals("lst112")) {
+                checkLst112(jReader, pthPref + keyName, data);
+            } else {
+                assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+            }
+        }
+        jReader.endObject();
+    }
+
+    private void checkLst112(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 0;
+        while (jReader.hasNext()) {
+            checkLst112Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+        }
+        jReader.endArray();
+    }
+
+    private void checkLst112Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        if (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+        }
+        jReader.endObject();
+
+    }
+
+    private void checkLst111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 0;
+        while (jReader.hasNext()) {
+            checkLst111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+        }
+        jReader.endArray();
+    }
+
+    private void checkLst111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        if (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+        }
+        jReader.endObject();
+    }
+
+    private void checkCont111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        checkCont111Elements(jReader, pthPref + "/", data);
+        jReader.endObject();
+    }
+
+    private void checkCont111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf1111")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            } else if (keyName.equals("lflst1111")) {
+                checkLflstValues(jReader, pthPref + keyName, data);
+            } else if (keyName.equals("lst1111")) {
+                checkLst1111(jReader, pthPref + keyName, data);
+            }
+        }
+
+    }
+
+    private void checkLst1111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 0;
+        while (jReader.hasNext()) {
+            checkLst1111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+        }
+        jReader.endArray();
+    }
+
+    private void checkLst1111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginObject();
+        while (jReader.hasNext()) {
+            String keyName = jReader.nextName();
+            if (keyName.equals("lf1111A")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+
+            } else if (keyName.equals("lf1111B")) {
+                assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+            }
+        }
+        jReader.endObject();
+    }
+
+    private void checkLflstValues(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+        jReader.beginArray();
+        int arrayIndex = 1;
+        String keyValue = null;
+        List<String> searchedValues = new ArrayList<>();
+        while ((keyValue = data.get(pthPref + "." + arrayIndex++)) != null) {
+            searchedValues.add(keyValue);
+        }
+
+        while (jReader.hasNext()) {
+            String value = jReader.nextString();
+            assertTrue("Value " + value + " of lflst " + pthPref + " wasn't found", searchedValues.contains(value));
+        }
+
+        jReader.endArray();
+    }
+
+
+
+}
@@ -1,22 +1,14 @@
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
-import java.io.*;
-import java.util.Set;
-import java.util.regex.*;
+import java.util.regex.Pattern;
 
-import javax.ws.rs.WebApplicationException;
+import org.junit.Test;
 
-import org.junit.*;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.model.api.*;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+public class YangAndXmlToJsonConversionRegExTest {
 
-public class YangAndXmlToJsonConversion {
-
-    @Ignore
     @Test
     /**
      * Test for simple yang types (leaf, list, leaf-list, container and various combination of them)
@@ -25,15 +17,14 @@ public class YangAndXmlToJsonConversion {
     public void simpleYangTypesTest() {
         String jsonOutput = null;
 
-        jsonOutput = convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
-                "/yang-to-json-conversion/simple-yang-types");
+//        jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+//                "/yang-to-json-conversion/simple-yang-types");
 
-//         jsonOutput =
-//         readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/output.json");
+         jsonOutput =
+         TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",true);
 
         verifyJsonOutputForSimpleYangTypes(jsonOutput);
-
-    }
+    }    
 
     private void verifyJsonOutputForSimpleYangTypes(String jsonOutput) {
 
@@ -149,125 +140,69 @@ public class YangAndXmlToJsonConversion {
         return null;
     }
 
-    private String readJsonFromFile(String path) {
-        String fullPath = YangAndXmlToJsonConversion.class.getResource(path).getPath();
-        assertNotNull("Path to file can't be null.", fullPath);
-        File file = new File(fullPath);
-        assertNotNull("File can't be null", file);
-        FileReader fileReader = null;
-        try {
-            fileReader = new FileReader(file);
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        assertNotNull("File reader can't be null.", fileReader);
-
-        StringBuilder strBuilder = new StringBuilder();
-        char[] buffer = new char[1000];
-
-        while (true) {
-            int loadedCharNum;
-            try {
-                loadedCharNum = fileReader.read(buffer);
-            } catch (IOException e) {
-                break;
-            }
-            if (loadedCharNum == -1) {
-                break;
-            }
-            strBuilder.append(buffer, 0, loadedCharNum);
-        }
-        try {
-            fileReader.close();
-        } catch (IOException e) {
-            System.out.println("The file wasn't closed");
-            ;
-        }
-        String rawStr = strBuilder.toString();
-        rawStr = rawStr.replace("\n", "");
-        rawStr = rawStr.replace("\r", "");
-        rawStr = rawStr.replace("\t", "");
-        rawStr = removeSpaces(rawStr);
-
-        return rawStr;
-    }
-
-    private String removeSpaces(String rawStr) {
-        StringBuilder strBuilder = new StringBuilder();
-        int i = 0;
-        int quoteCount = 0;
-        while (i < rawStr.length()) {
-            if (rawStr.substring(i, i + 1).equals("\"")) {
-                quoteCount++;
-            }
 
-            if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
-                strBuilder.append(rawStr.charAt(i));
-            }
-            i++;
-        }
-
-        return strBuilder.toString();
-    }
 
-    private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
-        String jsonResult = null;
-        Set<Module> modules = null;
 
-        try {
-            modules = TestUtils.loadModules(YangAndXmlToJsonConversion.class.getResource(yangPath).getPath());
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        assertNotNull("modules can't be null.", modules);
-
-        InputStream xmlStream = YangAndXmlToJsonConversion.class.getResourceAsStream(xmlDataPath);
-        CompositeNode compositeNode = null;
-        try {
-            compositeNode = TestUtils.loadCompositeNode(xmlStream);
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        }
-        assertNotNull("Composite node can't be null", compositeNode);
+//    private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+//        String jsonResult = null;
+//        Set<Module> modules = null;
+//
+//        try {
+//            modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+//        } catch (FileNotFoundException e) {
+//            e.printStackTrace();
+//        }
+//        assertNotNull("modules can't be null.", modules);
+//
+//        InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+//        CompositeNode compositeNode = null;
+//        try {
+//            compositeNode = TestUtils.loadCompositeNode(xmlStream);
+//        } catch (FileNotFoundException e) {
+//            e.printStackTrace();
+//        }
+//        assertNotNull("Composite node can't be null", compositeNode);
+//
+//        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+//        for (Module module : modules) {
+//            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+//                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+//                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+//                try {
+//                    structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+//                } catch (WebApplicationException | IOException e) {
+//                    e.printStackTrace();
+//                }
+//                assertFalse(
+//                        "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+//                        byteArrayOS.toString().isEmpty());
+//                jsonResult = byteArrayOS.toString();
+//                try {
+//                    outputToFile(byteArrayOS);
+//                } catch (IOException e) {
+//                    System.out.println("Output file wasn't cloased sucessfuly.");
+//                }
+//            }
+//        }
+//        return jsonResult;
+//    }
+//
+//    private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+//        FileOutputStream fileOS = null;
+//        try {
+//            String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+//            File outFile = new File(path + "/data.json");
+//            fileOS = new FileOutputStream(outFile);
+//            try {
+//                fileOS.write(outputStream.toByteArray());
+//            } catch (IOException e) {
+//                e.printStackTrace();
+//            }
+//            fileOS.close();
+//        } catch (FileNotFoundException e1) {
+//            e1.printStackTrace();
+//        }
+//    }
+    
 
-        StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
-        for (Module module : modules) {
-            for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
-                StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
-                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
-                try {
-                    structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
-                } catch (WebApplicationException | IOException e) {
-                    e.printStackTrace();
-                }
-                assertFalse(
-                        "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
-                        byteArrayOS.toString().isEmpty());
-                jsonResult = byteArrayOS.toString();
-                try {
-                    outputToFile(byteArrayOS);
-                } catch (IOException e) {
-                    System.out.println("Output file wasn't cloased sucessfuly.");
-                }
-            }
-        }
-        return jsonResult;
-    }
-
-    private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
-        FileOutputStream fileOS = null;
-        try {
-            String path = YangAndXmlToJsonConversion.class.getResource("/yang-to-json-conversion/xml").getPath();
-            File outFile = new File(path + "/data.json");
-            fileOS = new FileOutputStream(outFile);
-            try {
-                fileOS.write(outputStream.toByteArray());
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            fileOS.close();
-        } catch (FileNotFoundException e1) {
-            e1.printStackTrace();
-        }
-    }
 }
index e76e7bd9ef4f20c5405ef8a71046fcd504047d18..a0e5f2f0f2b804d182b9b1f1c310f61e150e9718 100644 (file)
                         "lf1111B": 7
                     }
                     ]
-                }
+                },
+                "lst111" : [
+                {
+                       "lf1111" : 65
+                       }
+                       ],
+                       "lst112" : [
+                       {
+                       "lf1121" : "lf1121 str11"
+                       }
+                       ]
+                
             },
             {
                 "lf111":141,
                         "lf1111B": 8
                     }
                     ]
-                }
+                },
+                "lst111" : [
+                {
+                       "lf1111" : 55
+                       },
+                {
+                       "lf1111" : 56
+                       }
+                       ],
             }        
         ]
+                       "lst112" : [
+                       {
+                       "lf1121" : "lf1121 str21"
+                       },
+                       {
+                       "lf1121" : "lf1121 str22"
+                       }
+                       ]
+            }
+            ]
     }
 }
\ No newline at end of file
index 8497edbd2674ebef735f95e17f6d115ab303048c..ce0036f9afa6024d18282e5e2cfe559b2744cd4a 100644 (file)
@@ -8,8 +8,11 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
 import org.opendaylight.controller.config.yang.store.api.YangStoreService;
@@ -22,10 +25,8 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
 /**
  * Manages life cycle of {@link YangStoreSnapshot}.
index 3c6209485de9499a07a8e077956ccf1e8bae6a3f..902cf2a8632a71dc1eac99ad46b3d79ca9a769c0 100644 (file)
                             javax.management,
                             org.opendaylight.controller.config.api.jmx,
                             org.opendaylight.protocol.framework,
-                            org.w3c.dom
+                            io.netty.channel,
+                            io.netty.util.concurrent,
+                            org.w3c.dom,
+                            org.slf4j
                         </Import-Package>
                         <Export-Package>
                             org.opendaylight.controller.netconf.api,
@@ -46,7 +49,7 @@
                         </Export-Package>
                     </instructions>
                 </configuration>
-            </plugin>
+             </plugin>
         </plugins>
     </build>
 
index 49ca0c010681b6f451d7bb19348b323b84affe21..e2a2d832c779e37f3e26c2d86efc37fb27d1b345 100644 (file)
@@ -12,7 +12,8 @@ import org.w3c.dom.Document;
 
 public interface NetconfOperationRouter extends AutoCloseable {
 
-    Document onNetconfMessage(Document message) throws NetconfDocumentedException;
+    Document onNetconfMessage(Document message, NetconfSession session)
+            throws NetconfDocumentedException;
 
     @Override
     void close();
index a61d6938f6a91ed12c1f3597aad9ec3cac6ce7e9..8b761a85b23b423314a39f8718492a2f5d1f8de0 100644 (file)
  * 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.netconf.api;
 
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+
+import java.io.IOException;
+import java.util.Map;
+
 import org.opendaylight.protocol.framework.AbstractProtocolSession;
+import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
+import org.opendaylight.protocol.framework.ProtocolMessageEncoder;
+import org.opendaylight.protocol.framework.SessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public abstract class NetconfSession extends AbstractProtocolSession<NetconfMessage> {
 
-    public abstract void sendMessage(NetconfMessage netconfMessage);
+    private ChannelHandler exiEncoder;
+    private String exiEncoderName;
+    private String removeAfterMessageSentname;
+    private String pmeName,pmdName;
+    private final  Channel channel;
+    private final  SessionListener sessionListener;
+    private final long sessionId;
+    private boolean up = false;
+    private static final Logger logger = LoggerFactory.getLogger(NetconfSession.class);
+    private static final int T = 0;
+
+    protected NetconfSession(SessionListener sessionListener, Channel channel, long sessionId) {
+        this.sessionListener = sessionListener;
+        this.channel = channel;
+        this.sessionId = sessionId;
+        logger.debug("Session {} created", toString());
+
+        ChannelHandler pmd = channel.pipeline().get(ProtocolMessageDecoder.class);
+        ChannelHandler pme = channel.pipeline().get(ProtocolMessageEncoder.class);
+
+        for (Map.Entry<String, ChannelHandler> entry:channel.pipeline().toMap().entrySet()){
+            if (entry.getValue().equals(pmd)){
+                pmdName = entry.getKey();
+            }
+            if (entry.getValue().equals(pme)){
+                pmeName = entry.getKey();
+            }
+        }
+    }
+    @Override
+    public void close() {
+        channel.close();
+        sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Session closed"));
+    }
+
+    @Override
+    protected void handleMessage(NetconfMessage netconfMessage) {
+        logger.debug("handlign incomming message");
+        sessionListener.onMessage(this, netconfMessage);
+    }
+
+    public void sendMessage(NetconfMessage netconfMessage) {
+        channel.writeAndFlush(netconfMessage);
+        if (exiEncoder!=null){
+            if (channel.pipeline().get(exiEncoderName)== null){
+                channel.pipeline().addBefore(pmeName, exiEncoderName, exiEncoder);
+            }
+        }
+        if (removeAfterMessageSentname!=null){
+            channel.pipeline().remove(removeAfterMessageSentname);
+            removeAfterMessageSentname = null;
+        }
+    }
+
+    @Override
+    protected void endOfInput() {
+        logger.debug("Session {} end of input detected while session was in state {}", toString(), isUp() ? "up"
+                : "initialized");
+        if (isUp()) {
+            this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session."));
+        }
+    }
+
+    @Override
+    protected void sessionUp() {
+        logger.debug("Session {} up", toString());
+        sessionListener.onSessionUp(this);
+        this.up = true;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuffer sb = new StringBuffer("ServerNetconfSession{");
+        sb.append("sessionId=").append(sessionId);
+        sb.append('}');
+        return sb.toString();
+    }
+
+    public boolean isUp() {
+        return up;
+    }
+
+    public long getSessionId() {
+        return sessionId;
+    }
+
+    public <T extends ChannelHandler> T remove(Class<T> handlerType) {
+        return channel.pipeline().remove(handlerType);
+    }
+
+    public <T extends ChannelHandler> T getHandler(Class<T> handlerType) {
+        return channel.pipeline().get(handlerType);
+   }
+
+    public void addFirst(ChannelHandler handler, String name){
+        channel.pipeline().addFirst(name, handler);
+    }
+    public void addLast(ChannelHandler handler, String name){
+        channel.pipeline().addLast(name, handler);
+    }
+
+    public void addExiDecoder(String name,ChannelHandler handler){
+        if (channel.pipeline().get(name)== null){
+            channel.pipeline().addBefore(pmdName, name, handler);
+        }
+    }
+    public void addExiEncoderAfterMessageSent(String name, ChannelHandler handler){
+        this.exiEncoder = handler;
+        this.exiEncoderName = name;
+    }
+
+    public void addExiEncoder(String name, ChannelHandler handler){
+        channel.pipeline().addBefore(pmeName, name, handler);
+    }
+
+    public void removeAfterMessageSent(String handlerName){
+        this.removeAfterMessageSentname = handlerName;
+    }
+
 }
+
index cc8d987a68f5d1aa314b8ec412f78e49d700e9f3..61a9a9b9548bc6eeb771dcf952c61e08e4a669f3 100644 (file)
@@ -8,16 +8,8 @@
 
 package org.opendaylight.controller.netconf.client;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GlobalEventExecutor;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.protocol.framework.NeverReconnectStrategy;
-import org.opendaylight.protocol.framework.ReconnectStrategy;
-import org.opendaylight.protocol.framework.TimedReconnectStrategy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -26,6 +18,16 @@ import java.util.Set;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
 
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.TimedReconnectStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+
 public class NetconfClient implements Closeable {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class);
@@ -121,4 +123,8 @@ public class NetconfClient implements Closeable {
         Preconditions.checkState(clientSession != null, "Client was not initialized successfully");
         return Sets.newHashSet(clientSession.getServerCapabilities());
     }
+
+    public NetconfClientSession getClientSession() {
+        return clientSession;
+    }
 }
index f0180cf78d74a8c47a9697f91480c474601a9759..11c7f3061f9e9b28f34926b482c60a8bbe51a26a 100644 (file)
@@ -9,87 +9,28 @@
 package org.opendaylight.controller.netconf.client;
 
 import io.netty.channel.Channel;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
+
+import java.util.Collection;
+
 import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.SessionListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.util.Collection;
-
 public class NetconfClientSession extends NetconfSession {
 
-    private final SessionListener sessionListener;
-    private final long sessionId;
-    private final Channel channel;
-
     private static final Logger logger = LoggerFactory.getLogger(NetconfClientSession.class);
     private final Collection<String> capabilities;
-    private boolean up;
 
     public NetconfClientSession(SessionListener sessionListener, Channel channel, long sessionId,
             Collection<String> capabilities) {
-        this.sessionListener = sessionListener;
-        this.channel = channel;
-        this.sessionId = sessionId;
+        super(sessionListener,channel,sessionId);
         this.capabilities = capabilities;
         logger.debug("Client Session {} created", toString());
     }
 
-    @Override
-    public void close() {
-        channel.close();
-        sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Client Session closed"));
-    }
-
-    @Override
-    protected void handleMessage(NetconfMessage netconfMessage) {
-        logger.debug("Client Session {} received message {}", toString(),
-                XmlUtil.toString(netconfMessage.getDocument()));
-        sessionListener.onMessage(this, netconfMessage);
-    }
-
-    @Override
-    public void sendMessage(NetconfMessage netconfMessage) {
-        channel.writeAndFlush(netconfMessage);
-    }
-
-    @Override
-    protected void endOfInput() {
-        logger.debug("Client Session {} end of input detected while session was in state {}", toString(), isUp() ? "up"
-                : "initialized");
-        if (isUp()) {
-            this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session."));
-        }
-    }
-
-    @Override
-    protected void sessionUp() {
-        logger.debug("Client Session {} up", toString());
-        sessionListener.onSessionUp(this);
-        this.up = true;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuffer sb = new StringBuffer("ClientNetconfSession{");
-        sb.append("sessionId=").append(sessionId);
-        sb.append('}');
-        return sb.toString();
-    }
-
-    public boolean isUp() {
-        return up;
-    }
-
-    public long getSessionId() {
-        return sessionId;
-    }
-
     public Collection<String> getServerCapabilities() {
         return capabilities;
     }
+
 }
index 1d85b688e5cd51fde186c473791d81a54b057e8f..221953e56e51053af95bc32bd866f2d51b99f05a 100644 (file)
@@ -1,5 +1,6 @@
 <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <capabilities>
         <capability>urn:ietf:params:netconf:base:1.0</capability>
+        <capability>urn:ietf:params:netconf:capability:exi:1.0</capability>
     </capabilities>
 </hello>
\ No newline at end of file
index c355cb0638f2cb02a102e13e5aa1b09c9946783a..1bd3a78326b67aca7f663038c1a15fa430b55cef 100644 (file)
@@ -54,7 +54,6 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
-
         <!-- test dependencies -->
         <dependency>
             <groupId>org.opendaylight.bgpcep</groupId>
                             io.netty.channel.socket,
                             io.netty.util,
                             io.netty.util.concurrent,
+                            io.netty.buffer,
+                            io.netty.handler.codec,
                             javax.management,
                             javax.net.ssl,
                             javax.xml.namespace,
                             org.opendaylight.controller.netconf.util.mapping,
                             org.opendaylight.controller.netconf.util.osgi,
                             org.opendaylight.controller.netconf.util.xml,
+                            org.opendaylight.controller.netconf.util.handler,
                             org.opendaylight.protocol.framework,
                             org.osgi.framework,
                             org.osgi.util.tracker,
                             org.w3c.dom,
                             org.xml.sax,
                             org.opendaylight.controller.netconf.util.messages,
-                            org.opendaylight.controller.config.stat
+                            org.opendaylight.controller.config.stat,
+                            com.siemens.ct.exi.exceptions
                         </Import-Package>
                     </instructions>
                 </configuration>
index 1ae3fabbb9a31bf5275b63f1bc27da15e8a72d88..a4d7e747234ce07804a1405ff4f96ff31ecd35e5 100644 (file)
@@ -9,77 +9,18 @@
 package org.opendaylight.controller.netconf.impl;
 
 import io.netty.channel.Channel;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
+
 import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.SessionListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-
 public class NetconfServerSession extends NetconfSession {
 
-    private final SessionListener sessionListener;
-    private final Channel channel;
-
     private static final Logger logger = LoggerFactory.getLogger(NetconfServerSession.class);
-    private final long sessionId;
-    private boolean up = false;
 
     public NetconfServerSession(SessionListener sessionListener, Channel channel, long sessionId) {
-        this.sessionListener = sessionListener;
-        this.channel = channel;
-        this.sessionId = sessionId;
+        super(sessionListener,channel,sessionId);
         logger.debug("Session {} created", toString());
     }
-
-    @Override
-    public void close() {
-        channel.close();
-        sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Session closed"));
-    }
-
-    @Override
-    protected void handleMessage(NetconfMessage netconfMessage) {
-        logger.debug("Session {} received message {}", toString(), XmlUtil.toString(netconfMessage.getDocument()));
-        sessionListener.onMessage(this, netconfMessage);
-    }
-
-    public void sendMessage(NetconfMessage netconfMessage) {
-        channel.writeAndFlush(netconfMessage);
-    }
-
-    @Override
-    protected void endOfInput() {
-        logger.debug("Session {} end of input detected while session was in state {}", toString(), isUp() ? "up"
-                : "initialized");
-        if (isUp()) {
-            this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session."));
-        }
-    }
-
-    @Override
-    protected void sessionUp() {
-        logger.debug("Session {} up", toString());
-        sessionListener.onSessionUp(this);
-        this.up = true;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuffer sb = new StringBuffer("ServerNetconfSession{");
-        sb.append("sessionId=").append(sessionId);
-        sb.append('}');
-        return sb.toString();
-    }
-
-    public boolean isUp() {
-        return up;
-    }
-
-    public long getSessionId() {
-        return sessionId;
-    }
 }
index 4f71ab9bb55f207f72418338e49b4b4d7c1cfe02..686adcad8550a3401809235cc0bda6e660782738 100644 (file)
@@ -8,10 +8,11 @@
 
 package org.opendaylight.controller.netconf.impl;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
+import static com.google.common.base.Preconditions.checkState;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
 import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil;
@@ -24,7 +25,8 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 
-import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
 
 public class NetconfServerSessionListener implements
         SessionListener<NetconfMessage, NetconfServerSession, NetconfTerminationReason> {
@@ -66,7 +68,8 @@ public class NetconfServerSessionListener implements
             Preconditions.checkState(operationRouter != null, "Cannot handle message, session up was not yet received");
             // FIXME: there is no validation since the document may contain yang
             // schemas
-            final NetconfMessage message = processDocument(netconfMessage);
+            final NetconfMessage message = processDocument(netconfMessage,
+                    session);
             logger.debug("Respondign with message {}", XmlUtil.toString(message.getDocument()));
             session.sendMessage(message);
 
@@ -89,16 +92,18 @@ public class NetconfServerSessionListener implements
         logger.info("Session {} closed successfully", session.getSessionId());
     }
 
-    private NetconfMessage processDocument(final NetconfMessage netconfMessage) throws NetconfDocumentedException {
+    private NetconfMessage processDocument(final NetconfMessage netconfMessage,
+            NetconfSession session) throws NetconfDocumentedException {
 
         final Document incommingDocument = netconfMessage.getDocument();
         final Node rootNode = incommingDocument.getDocumentElement();
 
-        if (rootNode.getNodeName().equals(XmlNetconfConstants.RPC_KEY)) {
+        if (rootNode.getLocalName().equals(XmlNetconfConstants.RPC_KEY)) {
             final String messageId = rootNode.getAttributes().getNamedItem(MESSAGE_ID).getTextContent();
             checkState(messageId != null);
             final Document responseDocument = XmlUtil.newDocument();
-            Document rpcReply = operationRouter.onNetconfMessage(incommingDocument);
+            Document rpcReply = operationRouter.onNetconfMessage(
+                    incommingDocument, session);
             responseDocument.appendChild(responseDocument.importNode(rpcReply.getDocumentElement(), true));
             return new NetconfMessage(responseDocument);
         } else {
index eea6dc19dae9be8897078a7798fd90c3ed7197e1..70ddf299fd5dd0d7ff8c091598c0644a88278342 100644 (file)
@@ -23,7 +23,8 @@ public class NetconfServerSessionListenerFactory implements SessionListenerFacto
     private final SessionIdProvider idProvider;
 
     public NetconfServerSessionListenerFactory(NetconfOperationServiceFactoryListener factoriesListener,
-            DefaultCommitNotificationProducer commitNotifier, SessionIdProvider idProvider) {
+            DefaultCommitNotificationProducer commitNotifier,
+            SessionIdProvider idProvider) {
         this.factoriesListener = factoriesListener;
         this.commitNotifier = commitNotifier;
         this.idProvider = idProvider;
@@ -36,8 +37,9 @@ public class NetconfServerSessionListenerFactory implements SessionListenerFacto
 
         CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot);
 
-        NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl(netconfOperationServiceSnapshot,
-                capabilityProvider, commitNotifier);
+        NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl(
+                netconfOperationServiceSnapshot, capabilityProvider,
+                commitNotifier);
 
         return new NetconfServerSessionListener(operationRouter);
     }
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java
new file mode 100644 (file)
index 0000000..721c0c2
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.channel.ChannelHandlerContext;\r
+import io.netty.handler.codec.ByteToMessageDecoder;\r
+\r
+import java.util.List;\r
+\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class ExiDecoderHandler extends ByteToMessageDecoder {\r
+\r
+    public static final String HANDLER_NAME;\r
+\r
+    static {\r
+        HANDLER_NAME = "exiDecoder";\r
+    }\r
+\r
+    private final static Logger logger = LoggerFactory\r
+            .getLogger(ExiDecoderHandler.class);\r
+\r
+    private ExiParameters parameters;\r
+\r
+    public ExiDecoderHandler(ExiParameters parameters) {\r
+        this.parameters = parameters;\r
+    }\r
+\r
+    @Override\r
+    protected void decode(ChannelHandlerContext ctx, ByteBuf in,\r
+            List<Object> out) {\r
+        try {\r
+            ExiUtil.decode(in, out, this.parameters);\r
+        } catch (Exception e) {\r
+            throw new IllegalStateException("Unable to decode exi message.");\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java
new file mode 100644 (file)
index 0000000..e7a5917
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.channel.ChannelHandlerContext;\r
+import io.netty.handler.codec.MessageToByteEncoder;\r
+\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+\r
+public class ExiEncoderHandler extends MessageToByteEncoder<Object> {\r
+\r
+    public static final String HANDLER_NAME;\r
+    static {\r
+        HANDLER_NAME = "exiEncoder";\r
+    }\r
+\r
+    private ExiParameters parameters;\r
+\r
+    public ExiEncoderHandler(ExiParameters parameters) {\r
+        this.parameters = parameters;\r
+    }\r
+\r
+    @Override\r
+    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)\r
+            throws Exception {\r
+        try {\r
+            ExiUtil.encode(msg, out, this.parameters);\r
+        } catch (Exception e) {\r
+            throw new IllegalStateException("Unable to encode exi message.");\r
+        }\r
+    }\r
+}\r
index 1438515f040e41c547a8742010aec37b6ab2471b..3623ef50325378b1c710d005248be520479c6763 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.controller.netconf.impl.mapping.operations;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
+import org.opendaylight.controller.netconf.api.NetconfSession;
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -17,8 +19,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-public class DefaultCloseSession extends AbstractNetconfOperation {
+public class DefaultCloseSession extends AbstractNetconfOperation implements DefaultNetconfOperation {
     public static final String CLOSE_SESSION = "close-session";
+    private NetconfSession netconfSession;
 
     public DefaultCloseSession(String netconfSessionIdForReporting) {
         super(netconfSessionIdForReporting);
@@ -45,4 +48,13 @@ public class DefaultCloseSession extends AbstractNetconfOperation {
         opRouter.close();
         return document.createElement(XmlNetconfConstants.OK);
     }
+
+    @Override
+    public void setNetconfSession(NetconfSession s) {
+        this.netconfSession = s;
+    }
+
+    public NetconfSession getNetconfSession() {
+        return netconfSession;
+    }
 }
index 8637c0dd7444ca816360bac9beb322bc57108293..9069e87a935784419e0c573f8721d8e31c1b3af8 100644 (file)
@@ -8,7 +8,9 @@
 
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
-import com.google.common.collect.Maps;
+import java.io.InputStream;
+import java.util.Map;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
@@ -24,8 +26,7 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.io.InputStream;
-import java.util.Map;
+import com.google.common.collect.Maps;
 
 public class DefaultCommit implements NetconfOperationFilter {
 
@@ -78,13 +79,13 @@ public class DefaultCommit implements NetconfOperationFilter {
     }
 
     @Override
-    public int getSoringOrder() {
+    public int getSortingOrder() {
         return 0;
     }
 
     @Override
     public int compareTo(NetconfOperationFilter o) {
-        return Integer.compare(getSoringOrder(), o.getSoringOrder());
+        return Integer.compare(getSortingOrder(), o.getSortingOrder());
     }
 
     private boolean canHandle(OperationNameAndNamespace operationNameAndNamespace) {
@@ -117,7 +118,8 @@ public class DefaultCommit implements NetconfOperationFilter {
     }
 
     private Element getConfigSnapshot(NetconfOperationRouter opRouter) throws NetconfDocumentedException {
-        final Document responseDocument = opRouter.onNetconfMessage(getConfigMessage);
+        final Document responseDocument = opRouter.onNetconfMessage(
+                getConfigMessage, null);
 
         XmlElement dataElement;
         try {
index 3e65ed8842f5a0d58fd7d46d7f47f13fbd9b8230..77042855e6525673a69fcce76344d5ea757b4061 100644 (file)
@@ -8,11 +8,14 @@
 
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Maps;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -23,12 +26,13 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.util.HashMap;
-import java.util.Map;
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
 
-public final class DefaultGetSchema extends AbstractNetconfOperation {
+public final class DefaultGetSchema extends AbstractNetconfOperation implements DefaultNetconfOperation {
 
     private final CapabilityProvider cap;
+    private NetconfSession netconfSession;
 
     private static final Logger logger = LoggerFactory.getLogger(DefaultGetSchema.class);
 
@@ -116,4 +120,12 @@ public final class DefaultGetSchema extends AbstractNetconfOperation {
 
         }
     }
+
+    public void setNetconfSession(NetconfSession s) {
+        this.netconfSession = s;
+    }
+
+    public NetconfSession getNetconfSession() {
+        return netconfSession;
+    }
 }
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java
new file mode 100644 (file)
index 0000000..8f08688
--- /dev/null
@@ -0,0 +1,92 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping.operations;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;\r
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+\r
+public class DefaultStartExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+\r
+    public static final String START_EXI = "start-exi";\r
+\r
+    private static NetconfSession netconfSession;\r
+\r
+    private static final Logger logger = LoggerFactory.getLogger(DefaultStartExi.class);\r
+\r
+    public DefaultStartExi(String netconfSessionIdForReporting) {\r
+        super(netconfSessionIdForReporting);\r
+    }\r
+\r
+    @Override\r
+    protected HandlingPriority canHandle(String operationName,\r
+            String netconfOperationNamespace) {\r
+        if (operationName.equals(START_EXI) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+        if (netconfOperationNamespace\r
+                .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+\r
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+    }\r
+\r
+    @Override\r
+    protected Element handle(Document document, XmlElement operationElement,\r
+            NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+\r
+\r
+        Element getSchemaResult = document\r
+                .createElement(XmlNetconfConstants.OK);\r
+        XmlUtil.addNamespaceAttr(getSchemaResult,\r
+                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);\r
+\r
+\r
+        try {\r
+            ExiParameters exiParams = new ExiParameters();\r
+            exiParams.setParametersFromXmlElement(operationElement);\r
+\r
+            netconfSession.addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams));\r
+            netconfSession.addExiEncoderAfterMessageSent(ExiEncoderHandler.HANDLER_NAME,new ExiEncoderHandler(exiParams));\r
+\r
+        } catch (EXIException e) {\r
+            getSchemaResult = document\r
+                    .createElement(XmlNetconfConstants.RPC_ERROR);\r
+        }\r
+\r
+        logger.info("{} operation successful", START_EXI);\r
+        logger.debug("received start-exi message {} ", XmlUtil.toString(document));\r
+        return getSchemaResult;\r
+\r
+    }\r
+\r
+    @Override\r
+    public void setNetconfSession(NetconfSession s) {\r
+        netconfSession = s;\r
+    }\r
+\r
+    public NetconfSession getNetconfSession() {\r
+        return netconfSession;\r
+    }\r
+\r
+\r
+}\r
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java
new file mode 100644 (file)
index 0000000..98a7205
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping.operations;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;\r
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+public class DefaultStopExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+\r
+    public static final String STOP_EXI = "stop-exi";\r
+    private NetconfSession netconfSession;\r
+\r
+    private static final Logger logger = LoggerFactory\r
+            .getLogger(DefaultStartExi.class);\r
+\r
+    public DefaultStopExi(String netconfSessionIdForReporting) {\r
+        super(netconfSessionIdForReporting);\r
+    }\r
+\r
+    @Override\r
+    protected HandlingPriority canHandle(String operationName,\r
+            String netconfOperationNamespace) {\r
+        if (operationName.equals(STOP_EXI) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+        if (netconfOperationNamespace\r
+                .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+\r
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+    }\r
+\r
+    @Override\r
+    protected Element handle(Document document, XmlElement operationElement,\r
+            NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+\r
+        netconfSession.remove(ExiDecoderHandler.class);\r
+        netconfSession.removeAfterMessageSent(ExiEncoderHandler.HANDLER_NAME);\r
+\r
+        Element getSchemaResult = document.createElement(XmlNetconfConstants.OK);\r
+        XmlUtil.addNamespaceAttr(getSchemaResult,\r
+                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);\r
+        logger.info("{} operation successful", STOP_EXI);\r
+        logger.debug("received stop-exi message {} ", XmlUtil.toString(document));\r
+        return getSchemaResult;\r
+    }\r
+\r
+    @Override\r
+    public void setNetconfSession(NetconfSession s) {\r
+        this.netconfSession = s;\r
+    }\r
+\r
+    public NetconfSession getNetconfSession() {\r
+        return netconfSession;\r
+    }\r
+}
\ No newline at end of file
index a9bea344c9471853bc1654f708f8f9d99a61e619..3dd6e6803bda9662b7e54a95849db368931a8452 100644 (file)
@@ -7,16 +7,25 @@
  */
 package org.opendaylight.controller.netconf.impl.osgi;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi;
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
@@ -27,13 +36,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
@@ -46,8 +51,10 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
     private final CapabilityProvider capabilityProvider;
 
+
     public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
-            CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
+            CapabilityProvider capabilityProvider,
+            DefaultCommitNotificationProducer commitNotifier) {
 
         this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
 
@@ -58,6 +65,12 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
                 .getNetconfSessionIdForReporting()));
         defaultNetconfOperations.add(new DefaultCloseSession(netconfOperationServiceSnapshot
                 .getNetconfSessionIdForReporting()));
+        defaultNetconfOperations.add(new DefaultStartExi(
+                netconfOperationServiceSnapshot
+                        .getNetconfSessionIdForReporting()));
+        defaultNetconfOperations.add(new DefaultStopExi(
+                netconfOperationServiceSnapshot
+                        .getNetconfSessionIdForReporting()));
 
         allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot);
 
@@ -101,8 +114,10 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
     }
 
     @Override
-    public synchronized Document onNetconfMessage(Document message) throws NetconfDocumentedException {
-        NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(message);
+    public synchronized Document onNetconfMessage(Document message,
+            NetconfSession session) throws NetconfDocumentedException {
+        NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(
+                message, session);
         logger.debug("Forwarding netconf message {} to {}", XmlUtil.toString(message),
                 netconfOperationExecution.operationWithHighestPriority);
 
@@ -125,10 +140,12 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return chain.getFirst().execute(message, this);
     }
 
-    private NetconfOperationExecution getNetconfOperationWithHighestPriority(Document message) {
+    private NetconfOperationExecution getNetconfOperationWithHighestPriority(
+            Document message, NetconfSession session) {
 
         // TODO test
-        TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(message);
+        TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(
+                message, session);
 
         Preconditions.checkState(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
                 NetconfOperation.class.getName(), XmlUtil.toString(message));
@@ -143,12 +160,16 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return new NetconfOperationExecution(sortedPriority, highestFoundPriority);
     }
 
-    private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(Document message) {
+    private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(
+            Document message, NetconfSession session) {
         TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = Maps.newTreeMap();
 
         for (NetconfOperation netconfOperation : allNetconfOperations) {
             final HandlingPriority handlingPriority = netconfOperation.canHandle(message);
-
+            if (netconfOperation instanceof DefaultNetconfOperation) {
+                ((DefaultNetconfOperation) netconfOperation)
+                        .setNetconfSession(session);
+            }
             if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
                 Set<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
                 netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
@@ -197,4 +218,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot
                 + '}';
     }
+
+
+
 }
index 6a3f911cd4e0ed5958700b05344ccdb3162b03b2..eb4b4b9225b4e8a56f92de3714513d0fcb91a295 100644 (file)
@@ -2,6 +2,7 @@
 <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <capabilities>
         <capability>urn:ietf:params:netconf:base:1.0</capability>
+        <capability>urn:ietf:params:netconf:capability:exi:1.0</capability>
     </capabilities>
     <session-id>1</session-id>
 </hello>
diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java
new file mode 100644 (file)
index 0000000..6b0316b
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opendaylight.controller.netconf.impl;\r
+\r
+import static junit.framework.Assert.assertNotNull;\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.buffer.Unpooled;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.junit.Test;\r
+import org.opendaylight.controller.netconf.api.NetconfMessage;\r
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+\r
+\r
+\r
+public class ExiEncodeDecodeTest  {\r
+    @Test\r
+    public void encodeExi() throws Exception{\r
+\r
+        String startExiString = XmlFileLoader.xmlFileToString("netconfMessages/startExi.xml");\r
+        assertNotNull(startExiString);\r
+\r
+        NetconfMessage startExiMessage = XmlFileLoader.xmlFileToNetconfMessage(("netconfMessages/startExi.xml"));\r
+        assertNotNull(startExiMessage);\r
+\r
+        ExiParameters exiParams = new ExiParameters();\r
+        exiParams.setParametersFromXmlElement(XmlElement.fromDomElement(startExiMessage.getDocument().getDocumentElement()));\r
+        assertNotNull(exiParams);\r
+\r
+        ByteBuf encodedBuf = Unpooled.buffer();\r
+        ByteBuf sourceBuf = Unpooled.copiedBuffer(startExiString.getBytes());\r
+        ExiUtil.encode(sourceBuf, encodedBuf, exiParams);\r
+\r
+        List<Object> newOut = new ArrayList<Object>();\r
+        ExiUtil.decode(encodedBuf, newOut, exiParams);\r
+\r
+        ByteBuf decodedBuf = (ByteBuf)newOut.get(0);\r
+        String decodedString = new String(decodedBuf.array(),"UTF-8");\r
+        assertNotNull(decodedString);\r
+    }\r
+}\r
index 1512d54105af31cf02437ce4f88c4298095d19ce..e9fe857bcac571501900dc2111edc2d4567bbe80 100644 (file)
@@ -44,9 +44,12 @@ 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.mapping.ExiDecoderHandler;
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
@@ -80,9 +83,11 @@ public class NetconfITTest extends AbstractConfigTest {
     // private static final Logger logger =
     // LoggerFactory.getLogger(NetconfITTest.class);
     //
+
     private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
 
-    private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession;
+    private NetconfMessage getConfig, getConfigCandidate, editConfig,
+            closeSession, startExi, stopExi;
     private DefaultCommitNotificationProducer commitNot;
     private NetconfServerDispatcher dispatch;
 
@@ -132,6 +137,10 @@ public class NetconfITTest extends AbstractConfigTest {
         this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml");
         this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
         this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml");
+        this.startExi = XmlFileLoader
+                .xmlFileToNetconfMessage("netconfMessages/startExi.xml");
+        this.stopExi = XmlFileLoader
+                .xmlFileToNetconfMessage("netconfMessages/stopExi.xml");
         this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml");
     }
 
@@ -270,6 +279,7 @@ public class NetconfITTest extends AbstractConfigTest {
             final Element rpcReply = message.getDocument().getDocumentElement();
             final XmlElement resultElement = XmlElement.fromDomElement(rpcReply).getOnlyChildElement();
             assertEquals("result", resultElement.getName());
+
             final String namespace = resultElement.getNamespaceAttribute();
             assertEquals(expectedNamespace, namespace);
         }
@@ -298,15 +308,44 @@ public class NetconfITTest extends AbstractConfigTest {
         });
     }
 
+    @Test
+//    @Ignore
+    public void testStartExi() throws Exception {
+        try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
+
+
+            Document rpcReply = netconfClient.sendMessage(this.startExi)
+                    .getDocument();
+            assertIsOK(rpcReply);
+
+            ExiParameters exiParams = new ExiParameters();
+            exiParams.setParametersFromXmlElement(XmlElement.fromDomDocument(this.startExi.getDocument()));
+
+            netconfClient.getClientSession().addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams));
+            netconfClient.getClientSession().addExiEncoder(ExiEncoderHandler.HANDLER_NAME, new ExiEncoderHandler(exiParams));
+
+            rpcReply = netconfClient.sendMessage(this.editConfig)
+                    .getDocument();
+            assertIsOK(rpcReply);
+
+            rpcReply = netconfClient.sendMessage(this.stopExi)
+                    .getDocument();
+            assertIsOK(rpcReply);
+
+        }
+    }
+
     @Test
     public void testCloseSession() throws Exception {
         try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
 
             // edit config
-            Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument();
+            Document rpcReply = netconfClient.sendMessage(this.editConfig)
+                    .getDocument();
             assertIsOK(rpcReply);
 
-            rpcReply = netconfClient.sendMessage(this.closeSession).getDocument();
+            rpcReply = netconfClient.sendMessage(this.closeSession)
+                    .getDocument();
 
             assertIsOK(rpcReply);
         }
@@ -336,7 +375,7 @@ public class NetconfITTest extends AbstractConfigTest {
     }
 
     private void assertIsOK(final Document rpcReply) {
-        assertEquals("rpc-reply", rpcReply.getDocumentElement().getTagName());
+        assertEquals("rpc-reply", rpcReply.getDocumentElement().getLocalName());
         assertEquals("ok", XmlElement.fromDomDocument(rpcReply).getOnlyChildElement().getName());
     }
 
@@ -398,9 +437,7 @@ public class NetconfITTest extends AbstractConfigTest {
 
     private NetconfClient createSession(final InetSocketAddress address, final String expected) throws Exception {
         final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, NETCONF_CLIENT_DISPATCHER);
-
         assertEquals(expected, Long.toString(netconfClient.getSessionId()));
-
         return netconfClient;
     }
 
diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java
new file mode 100644 (file)
index 0000000..f6f05f6
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.netconf.mapping.api;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+\r
+public interface DefaultNetconfOperation {\r
+    void setNetconfSession(NetconfSession s);\r
+}\r
index 22a730726d60b5ffdef95b0431059a72b466c592..c9e04e3dcd281d1fb8ca45046a42eda0c1d5e4ef 100644 (file)
@@ -21,6 +21,6 @@ public interface NetconfOperationFilter extends Comparable<NetconfOperationFilte
     Document doFilter(Document message, NetconfOperationRouter operationRouter, NetconfOperationFilterChain filterChain)
             throws NetconfDocumentedException;
 
-    int getSoringOrder();
+    int getSortingOrder();
 
 }
index d6bf62413a569949da0ca09de44d5678f3c9a4da..4638a1009e503245c58e78278cd8b0f6f83cd305 100644 (file)
             <artifactId>netty-handler</artifactId>
             <version>${netconf.netty.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.siemens.ct.exi</groupId>
+            <artifactId>exificient</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.thirdparty</groupId>
             <artifactId>ganymed</artifactId>
@@ -71,6 +75,7 @@
                             org.opendaylight.controller.netconf.util.osgi,
                             org.opendaylight.controller.netconf.util.mapping,
                             org.opendaylight.controller.netconf.util.messages,
+                            org.opendaylight.controller.netconf.util.handler,
                         </Export-Package>
                         <Import-Package>
                             org.opendaylight.controller.config.stat,
@@ -93,6 +98,7 @@
                             javax.xml.transform.stream,
                             javax.xml.validation,
                             javax.xml.xpath,
+                            javax.xml.transform.sax,
                             org.opendaylight.controller.netconf.api,
                             org.opendaylight.controller.netconf.mapping.api,
                             org.opendaylight.protocol.framework,
                             org.slf4j,
                             org.w3c.dom,
                             org.xml.sax,
+                            com.siemens.ct.exi,
+                            com.siemens.ct.exi.api.sax,
+                            com.siemens.ct.exi.grammars,
+                            com.siemens.ct.exi.helpers,
+                            com.siemens.ct.exi.exceptions,
+                            com.siemens.ct.exi.api.dom,
+                            org.xml.sax.helpers,
                         </Import-Package>
                     </instructions>
                 </configuration>
index 868ddbd99c37a07a6fd31198cd81fe01c654e662..b67f48f5fcf3014b06f701c18a956bfed0a78e5b 100644 (file)
@@ -8,6 +8,10 @@
 
 package org.opendaylight.controller.netconf.util.handler;
 
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
 import java.util.List;
 
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
@@ -15,10 +19,6 @@ import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ByteToMessageDecoder;
-
 public class NetconfMessageAggregator extends ByteToMessageDecoder {
 
     private final static Logger logger = LoggerFactory.getLogger(NetconfMessageAggregator.class);
@@ -35,7 +35,7 @@ public class NetconfMessageAggregator extends ByteToMessageDecoder {
     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
         int index = indexOfSequence(in, eom);
         if (index == -1) {
-            logger.debug("Message is not complete, read agian.");
+            logger.debug("Message is not complete, read again.");
             ctx.read();
         } else {
             ByteBuf msg = in.readBytes(index);
index 5850e64a0591a4d58c320eb67330e1dc0aa55cae..86081b7f81d0f342669fdb1c7124b74dbff3157b 100644 (file)
@@ -8,8 +8,6 @@
 
 package org.opendaylight.controller.netconf.util.mapping;
 
-import java.util.Map;
-
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
@@ -20,6 +18,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.util.Map;
 
 public abstract class AbstractNetconfOperation implements NetconfOperation {
     private final String netconfSessionIdForReporting;
@@ -76,15 +77,23 @@ public abstract class AbstractNetconfOperation implements NetconfOperation {
         Map<String, Attr> attributes = requestElement.getAttributes();
 
         Element response = handle(document, operationElement, opRouter);
-
         Element rpcReply = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
                 XmlNetconfConstants.RPC_REPLY_KEY);
-        rpcReply.appendChild(response);
 
-        for (String attrName : attributes.keySet()) {
-            rpcReply.setAttribute(attrName, attributes.get(attrName).getNodeValue());
+        if(XmlElement.fromDomElement(response).hasNamespace()) {
+            rpcReply.appendChild(response);
+        } else {
+            Element responseNS = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, response.getNodeName());
+            NodeList list = response.getChildNodes();
+            while(list.getLength()!=0) {
+                responseNS.appendChild(list.item(0));
+            }
+            rpcReply.appendChild(responseNS);
         }
 
+        for (String attrName : attributes.keySet()) {
+            rpcReply.setAttributeNode((Attr) document.importNode(attributes.get(attrName), true));
+        }
         document.appendChild(rpcReply);
         return document;
     }
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java
new file mode 100644 (file)
index 0000000..63dfcde
--- /dev/null
@@ -0,0 +1,128 @@
+package org.opendaylight.controller.netconf.util.xml;\r
+\r
+import com.siemens.ct.exi.CodingMode;\r
+import com.siemens.ct.exi.FidelityOptions;\r
+import com.siemens.ct.exi.GrammarFactory;\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+import com.siemens.ct.exi.grammars.Grammars;\r
+\r
+public class ExiParameters {\r
+\r
+    private static final String EXI_PARAMETER_ALIGNMENT = "alignment";\r
+    private static final String EXI_PARAMETER_BYTE_ALIGNED = "byte-aligned";\r
+    private static final String EXI_PARAMETER_COMPRESSED = "compressed";\r
+\r
+    private static final String EXI_PARAMETER_FIDELITY = "fidelity";\r
+    private static final String EXI_FIDELITY_DTD = "dtd";\r
+    private static final String EXI_FIDELITY_LEXICAL_VALUES = "lexical-values";\r
+    private static final String EXI_FIDELITY_COMMENTS = "comments";\r
+    private static final String EXI_FIDELITY_PIS = "pis";\r
+    private static final String EXI_FIDELITY_PREFIXES = "prefixes";\r
+\r
+    private static final String EXI_PARAMETER_SCHEMA = "schema";\r
+    private static final String EXI_PARAMETER_SCHEMA_NONE = "none";\r
+    private static final String EXI_PARAMETER_SCHEMA_BUILT_IN = "builtin";\r
+    private static final String EXI_PARAMETER_SCHEMA_BASE_1_1 = "base:1.1";\r
+\r
+    private static final String NETCONF_XSD_LOCATION = "";\r
+\r
+    private FidelityOptions fidelityOptions;\r
+    private Grammars grammars;\r
+    private CodingMode codingMode = CodingMode.BIT_PACKED;\r
+\r
+    public void setParametersFromXmlElement(XmlElement operationElement)\r
+            throws EXIException {\r
+\r
+        if (operationElement.getElementsByTagName(EXI_PARAMETER_ALIGNMENT)\r
+                .getLength() > 0) {\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_BYTE_ALIGNED)\r
+                    .getLength() > 0) {\r
+                this.codingMode = CodingMode.BYTE_PACKED;\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_BYTE_ALIGNED).getLength() > 0) {\r
+                this.codingMode = CodingMode.BYTE_PACKED;\r
+            }\r
+            if (operationElement.getElementsByTagName(EXI_PARAMETER_COMPRESSED)\r
+                    .getLength() > 0) {\r
+                this.codingMode = CodingMode.COMPRESSION;\r
+            }\r
+        }\r
+\r
+        if (operationElement.getElementsByTagName(EXI_PARAMETER_FIDELITY)\r
+                .getLength() > 0) {\r
+\r
+            this.fidelityOptions = FidelityOptions.createDefault();\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_DTD)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_DTD,\r
+                        true);\r
+            }\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_FIDELITY_LEXICAL_VALUES)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(\r
+                        FidelityOptions.FEATURE_LEXICAL_VALUE, true);\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_COMMENTS)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(\r
+                        FidelityOptions.FEATURE_COMMENT, true);\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_PIS)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_PI,\r
+                        true);\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_PREFIXES)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(\r
+                        FidelityOptions.FEATURE_PREFIX, true);\r
+            }\r
+\r
+        }\r
+\r
+        if (operationElement.getElementsByTagName(EXI_PARAMETER_SCHEMA)\r
+                .getLength() > 0) {\r
+\r
+            GrammarFactory grammarFactory = GrammarFactory.newInstance();\r
+            if (operationElement\r
+                    .getElementsByTagName(EXI_PARAMETER_SCHEMA_NONE)\r
+                    .getLength() > 0) {\r
+                this.grammars = grammarFactory.createSchemaLessGrammars();\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_SCHEMA_BUILT_IN).getLength() > 0) {\r
+                this.grammars = grammarFactory.createXSDTypesOnlyGrammars();\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_SCHEMA_BASE_1_1).getLength() > 0) {\r
+                this.grammars = grammarFactory\r
+                        .createGrammars(NETCONF_XSD_LOCATION);\r
+            }\r
+\r
+        }\r
+    }\r
+\r
+    public FidelityOptions getFidelityOptions() {\r
+        return fidelityOptions;\r
+    }\r
+\r
+    public Grammars getGrammars() {\r
+        return grammars;\r
+    }\r
+\r
+    public CodingMode getCodingMode() {\r
+        return codingMode;\r
+    }\r
+\r
+}\r
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java
new file mode 100644 (file)
index 0000000..8baa68e
--- /dev/null
@@ -0,0 +1,91 @@
+package org.opendaylight.controller.netconf.util.xml;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.buffer.EmptyByteBuf;\r
+import io.netty.buffer.Unpooled;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+import javax.xml.parsers.ParserConfigurationException;\r
+\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.xml.sax.SAXException;\r
+\r
+import com.siemens.ct.exi.EXIFactory;\r
+import com.siemens.ct.exi.api.dom.DOMBuilder;\r
+import com.siemens.ct.exi.api.dom.DOMWriter;\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+import com.siemens.ct.exi.helpers.DefaultEXIFactory;\r
+\r
+public class ExiUtil {\r
+\r
+    private final static Logger logger = LoggerFactory.getLogger(ExiUtil.class);\r
+\r
+\r
+\r
+    public static void encode(final Object msg, final ByteBuf out,\r
+            ExiParameters parameters)\r
+            throws EXIException, IOException, SAXException {\r
+        final byte[] bytes = toExi(msg, parameters);\r
+        out.writeBytes(bytes);\r
+    }\r
+\r
+    public static void decode(ByteBuf in, List<Object> out,\r
+            ExiParameters parameters) throws ParserConfigurationException, EXIException, IOException\r
+             {\r
+        if (in instanceof EmptyByteBuf){\r
+            return;\r
+        }\r
+\r
+        EXIFactory exiFactory = DefaultEXIFactory.newInstance();\r
+        if (parameters.getGrammars() != null) {\r
+            exiFactory.setGrammars(parameters.getGrammars());\r
+        }\r
+\r
+        if (parameters.getFidelityOptions() != null) {\r
+            exiFactory.setFidelityOptions(parameters.getFidelityOptions());\r
+        }\r
+\r
+        exiFactory.setCodingMode(parameters.getCodingMode());\r
+        try (ByteArrayInputStream exiIS = new ByteArrayInputStream(((ByteBuf)in).readBytes(((ByteBuf)in).readableBytes()).array())){\r
+            DOMBuilder domBuilder = new DOMBuilder(exiFactory);\r
+            ByteBuf result = Unpooled.copiedBuffer(XmlUtil.toString(domBuilder.parse(exiIS)).getBytes());\r
+            exiIS.close();\r
+            out.add(result);\r
+        }\r
+    }\r
+\r
+    private static byte[] toExi(Object msg, ExiParameters parameters) throws EXIException, IOException,\r
+            SAXException {\r
+\r
+        if (!(msg instanceof ByteBuf)){\r
+              return Unpooled.EMPTY_BUFFER.array();\r
+        }\r
+\r
+        EXIFactory exiFactory = DefaultEXIFactory.newInstance();\r
+        if (parameters.getGrammars() != null) {\r
+            exiFactory.setGrammars(parameters.getGrammars());\r
+        }\r
+\r
+        if (parameters.getFidelityOptions() != null) {\r
+            exiFactory.setFidelityOptions(parameters.getFidelityOptions());\r
+        }\r
+\r
+        Document doc = XmlUtil.readXmlToDocument(new String( ((ByteBuf)msg).readBytes(((ByteBuf)msg).readableBytes()).array(),"UTF-8"));\r
+        exiFactory.setCodingMode(parameters.getCodingMode());\r
+\r
+        try (ByteArrayOutputStream exiOS = new ByteArrayOutputStream()){\r
+            DOMWriter domWriter = new DOMWriter(exiFactory);\r
+            domWriter.setOutput(exiOS);\r
+            domWriter.encode(doc) ;\r
+            exiOS.close();\r
+            return exiOS.toByteArray();\r
+        }\r
+    }\r
+\r
+}\r
index 7cb0bb02859afd89418db41a69c60993671deeeb..c37b4abc6215906f1a1a98f5b088e63633f81e16 100644 (file)
@@ -103,6 +103,9 @@ public class XmlElement {
     }
 
     public String getName() {
+        if (element.getLocalName()!=null && !element.getLocalName().equals("")){
+            return element.getLocalName();
+        }
         return element.getTagName();
     }
 
@@ -114,6 +117,10 @@ public class XmlElement {
         return element.getAttributeNS(namespace, attributeName);
     }
 
+    public NodeList getElementsByTagName(String name) {
+        return element.getElementsByTagName(name);
+    }
+
     public void appendChild(Element element) {
         this.element.appendChild(element);
         // Element newElement = (Element) element.cloneNode(true);
@@ -273,8 +280,8 @@ public class XmlElement {
 
     public String getNamespaceAttribute() {
         String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY);
-        Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify a %s attribute",
-                toString(), XmlUtil.XMLNS_ATTRIBUTE_KEY);
+        Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify namespace",
+                toString());
         return attribute;
     }
 
@@ -369,6 +376,20 @@ public class XmlElement {
         return element.hashCode();
     }
 
+    public boolean hasNamespace() {
+        try {
+            getNamespaceAttribute();
+        } catch (IllegalStateException e) {
+            try {
+                getNamespace();
+            } catch (IllegalStateException e1) {
+                return false;
+            }
+            return true;
+        }
+        return true;
+    }
+
     private static interface ElementFilteringStrategy {
         boolean accept(Element e);
     }
index 0791812910f96067d5de3dadbcc73da12d1e9816..3e862faa7b34c96378002d17d79350fb0d4f45d7 100644 (file)
@@ -35,6 +35,7 @@ public class XmlNetconfConstants {
     //
     public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0";
     public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0";
+
     public static final String URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring";
     // TODO where to store namespace of config ?
     public static final String URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG = "urn:opendaylight:params:xml:ns:yang:controller:config";
index 298038996eddf08382ebcabcb929d6a15ff2e5a6..5e3a7ac54f49444ac8a2278f85ed82c20a052a7a 100644 (file)
@@ -8,11 +8,12 @@
 
 package org.opendaylight.controller.netconf.util.xml;
 
-import com.google.common.base.Charsets;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
 
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
@@ -32,12 +33,13 @@ import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.Charsets;
 
 public class XmlUtil {
 
@@ -79,7 +81,6 @@ public class XmlUtil {
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         factory.setNamespaceAware(true);
         factory.setCoalescing(true);
-        // factory.setValidating(true);
         factory.setIgnoringElementContentWhitespace(true);
         factory.setIgnoringComments(true);
         return factory;
index 8b60719ebe2df0028166deab0d3a38011bb59d4b..28cb4d8194b6c6b67d8afe17790974a5584de4f2 100644 (file)
@@ -8,20 +8,22 @@
 
 package org.opendaylight.controller.netconf.util.test;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Preconditions;
-import com.google.common.io.CharStreams;
-import com.google.common.io.InputSupplier;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
+import com.google.common.io.CharStreams;
+import com.google.common.io.InputSupplier;
 
 public class XmlFileLoader {
 
diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml
new file mode 100644 (file)
index 0000000..6b9e945
--- /dev/null
@@ -0,0 +1,9 @@
+<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" message-id="a">\r
+<start-exi>\r
+<alignment>pre-compression</alignment>\r
+<fidelity>\r
+<dtd/>\r
+<lexical-values/>\r
+</fidelity>\r
+</start-exi>\r
+</rpc>
\ No newline at end of file
diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml
new file mode 100644 (file)
index 0000000..4168d21
--- /dev/null
@@ -0,0 +1,3 @@
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\r
+    <stop-exi/>\r
+</rpc>
\ No newline at end of file
index 5447f7f5d057c71eba0e08369986c46c31013903..5efff5d9a0dbcbb455a0193dcc24402478c30261 100644 (file)
@@ -27,6 +27,7 @@
         <module>netconf-mapping-api</module>
         <module>netconf-client</module>
         <module>../../third-party/ganymed</module>
+        <module>../../third-party/com.siemens.ct.exi</module>
     </modules>
 
     <profiles>
@@ -46,6 +47,7 @@
         <maven.bundle.version>2.3.7</maven.bundle.version>
         <slf4j.version>1.7.2</slf4j.version>
         <netconf.netty.version>4.0.10.Final</netconf.netty.version>
+        <ct.exi.version>0.9.2</ct.exi.version>
     </properties>
 
     <dependencies>
                 <artifactId>logback-config</artifactId>
                 <version>${config.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.siemens.ct.exi</groupId>
+                <artifactId>exificient</artifactId>
+                <version>${ct.exi.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
index e0c7dcd2ac7a9e85bc293786b6fd8b1d606fa2cb..df56dbae360654b8252502c19ae3d433a6f5a854 100644 (file)
@@ -3,7 +3,7 @@
     xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
 
   <services>
-    <rest defaultRestSubcontext="/controller/nb/v2/host"/>
+    <rest defaultRestSubcontext="/controller/nb/v2/hosttracker"/>
   </services>
 
   <modules>
index 12a49f0996b2652123ce0eb810a5c685801dbf26..74c13d11f129943ba45e449411adfbc9f09d41e3 100644 (file)
@@ -394,8 +394,8 @@ public class HostTrackerNorthbound {
      * &#x20;&lt;nodeId&gt;00:00:00:00:00:00:00:01&lt;/nodeId&gt;
      * &#x20;&lt;nodeConnectorType&gt;OF&lt;/nodeConnectorType&gt;
      * &#x20;&lt;nodeConnectorId&gt;9&lt;/nodeConnectorId&gt;
-     * &#x20;&lt;vlan&gt;0&lt;/vlan&gt;
-     * &#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
+     * &#x20;&lt;vlan&gt;1&lt;/vlan&gt;
+     * &#x20;&lt;staticHost&gt;true&lt;/staticHost&gt;
      * &lt;/hostConfig&gt;
      *
      * Request body in JSON:
@@ -406,8 +406,8 @@ public class HostTrackerNorthbound {
      * &#x20;"nodeId":"00:00:00:00:00:00:00:01",
      * &#x20;"nodeConnectorType":"OF",
      * &#x20;"nodeConnectorId":"9",
-     * &#x20;"vlan":"0",
-     * &#x20;"staticHost":"false",
+     * &#x20;"vlan":"1",
+     * &#x20;"staticHost":"true",
      * &#x20;"networkAddress":"1.1.1.1"
      * }
      * </pre>
diff --git a/third-party/com.siemens.ct.exi/pom.xml b/third-party/com.siemens.ct.exi/pom.xml
new file mode 100644 (file)
index 0000000..237222c
--- /dev/null
@@ -0,0 +1,69 @@
+<?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/maven-v4_0_0.xsd">
+  <!-- Get some common settings for the project we are using it in -->
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.thirdparty</artifactId>
+    <version>1.1.1-SNAPSHOT</version>
+    <relativePath>../commons/thirdparty</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>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.controller.thirdparty</groupId>
+  <artifactId>exificient</artifactId>
+  <version>0.9.2</version>
+  <packaging>bundle</packaging>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Embed-Dependency>*;scope=!provided;type=!pom;inline=false</Embed-Dependency>
+            <Embed-Transitive>false</Embed-Transitive>
+            <Export-Package>
+              com.siemens.ct.exi.*,
+            </Export-Package>
+            <Import-Package>
+                javax.xml.namespace,
+                javax.xml.parsers,
+                javax.xml.stream,
+                javax.xml.stream.events,
+                javax.xml.transform.sax,
+                org.apache.xerces.impl.xs,
+                org.apache.xerces.impl.xs.models,
+                org.apache.xerces.xni,
+                org.apache.xerces.xni.grammars,
+                org.apache.xerces.xni.parser,
+                org.apache.xerces.xs,
+                org.w3c.dom,
+                org.xml.sax,
+                org.xml.sax.ext,
+                org.xml.sax.helpers
+            </Import-Package>
+          </instructions>
+          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+
+  <dependencies>
+    <dependency>
+        <groupId>com.siemens.ct.exi</groupId>
+        <artifactId>exificient</artifactId>
+        <version>0.9.2</version>
+    </dependency>
+  </dependencies>
+
+</project>