Merge "Fix discrepancy between command line maven build and the one initiated by...
authorAlessandro Boch <aboch@cisco.com>
Tue, 12 Nov 2013 18:52:52 +0000 (18:52 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 12 Nov 2013 18:52:52 +0000 (18:52 +0000)
32 files changed:
opendaylight/config/netty-event-executor-config/pom.xml [new file with mode: 0644]
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java [new file with mode: 0644]
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java [new file with mode: 0644]
opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang [new file with mode: 0644]
opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java [new file with mode: 0644]
opendaylight/config/pom.xml
opendaylight/config/threadpool-config-api/pom.xml
opendaylight/config/threadpool-config-api/src/main/yang/threadpool.yang
opendaylight/md-sal/clustered-data-store/implementation/pom.xml
opendaylight/md-sal/clustered-data-store/implementation/src/main/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImpl.java
opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreImplTest.java
opendaylight/md-sal/clustered-data-store/implementation/src/test/java/org/opendaylight/controller/datastore/internal/ClusteredDataStoreManagerTest.java
opendaylight/md-sal/clustered-data-store/integrationtest/pom.xml
opendaylight/md-sal/clustered-data-store/integrationtest/src/test/java/org/opendaylight/controller/datastore/ClusteredDataStoreIT.java
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang [new file with mode: 0644]
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/meter-statistics.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java
opendaylight/netconf/config-persister-impl/pom.xml
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/AbstractNetconfClientNotifySessionListener.java [new file with mode: 0644]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITSecureTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractChannelInitializer.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractSslChannelInitializer.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java

diff --git a/opendaylight/config/netty-event-executor-config/pom.xml b/opendaylight/config/netty-event-executor-config/pom.xml
new file mode 100644 (file)
index 0000000..a2ce94f
--- /dev/null
@@ -0,0 +1,106 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+   <parent>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-subsystem</artifactId>
+      <version>0.2.3-SNAPSHOT</version>
+   </parent>
+   <modelVersion>4.0.0</modelVersion>
+   <artifactId>netty-event-executor-config</artifactId>
+   <description>Configuration Wrapper around netty's event executor</description>
+   <packaging>bundle</packaging>
+   <name>${project.artifactId}</name>
+   <prerequisites>
+      <maven>3.0.4</maven>
+   </prerequisites>
+
+   <dependencies>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-api</artifactId>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>threadpool-config-api</artifactId>
+         <version>${project.version}</version>
+      </dependency>
+      <dependency>
+         <groupId>org.slf4j</groupId>
+         <artifactId>slf4j-api</artifactId>
+      </dependency>
+      <dependency>
+         <groupId>com.google.guava</groupId>
+         <artifactId>guava</artifactId>
+      </dependency>
+
+      <!--test dependencies -->
+      <dependency>
+         <groupId>junit</groupId>
+         <artifactId>junit</artifactId>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-manager</artifactId>
+         <scope>test</scope>
+         <type>test-jar</type>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-manager</artifactId>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>config-util</artifactId>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.opendaylight.bgpcep</groupId>
+         <artifactId>mockito-configuration</artifactId>
+         <scope>test</scope>
+      </dependency>
+
+   </dependencies>
+
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-maven-plugin</artifactId>
+         </plugin>
+         <plugin>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>maven-bundle-plugin</artifactId>
+            <extensions>true</extensions>
+            <configuration>
+               <instructions>
+                  <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                  <Export-Package>
+                  </Export-Package>
+                  <Import-Package>
+                     com.google.common.base,
+                     org.opendaylight.controller.config.yang.threadpool,
+                     io.netty.util.concurrent,
+                     org.opendaylight.controller.config.api,
+                     org.opendaylight.controller.config.api.annotations,
+                     org.opendaylight.controller.config.api.runtime,
+                     org.opendaylight.controller.config.spi,
+                     org.slf4j,
+                     org.osgi.framework
+                  </Import-Package>
+               </instructions>
+            </configuration>
+         </plugin>
+      </plugins>
+   </build>
+
+   <distributionManagement>
+      <site>
+         <id>${project.artifactId}</id>
+         <name>NETTY-EVENT-EXECUTOR-CONFIG Module site</name>
+         <url>${basedir}/target/site/${project.artifactId}</url>
+      </site>
+   </distributionManagement>
+
+</project>
\ No newline at end of file
diff --git a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java
new file mode 100644 (file)
index 0000000..3707f01
--- /dev/null
@@ -0,0 +1,113 @@
+/**
+ * Generated file
+
+ * Generated from: yang module name: netty-event-executor  yang module local name: netty-global-event-executor
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Tue Nov 12 10:44:21 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.netty.eventexecutor;
+
+import io.netty.util.concurrent.AbstractEventExecutor;
+import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.concurrent.EventExecutorGroup;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GlobalEventExecutor;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+*
+*/
+public final class GlobalEventExecutorModule extends
+        org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModule {
+
+    public GlobalEventExecutorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public GlobalEventExecutorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+            org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+            GlobalEventExecutorModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void validate() {
+        super.validate();
+        // Add custom validation for module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new GlobalEventExecutorCloseable(GlobalEventExecutor.INSTANCE);
+    }
+
+    static final private class GlobalEventExecutorCloseable extends AbstractEventExecutor implements AutoCloseable {
+
+        private EventExecutor executor;
+
+        public GlobalEventExecutorCloseable(EventExecutor executor) {
+            this.executor = executor;
+        }
+
+        @Override
+        public EventExecutorGroup parent() {
+            return this.executor.parent();
+        }
+
+        @Override
+        public boolean inEventLoop(Thread thread) {
+            return this.executor.inEventLoop(thread);
+        }
+
+        @Override
+        public boolean isShuttingDown() {
+            return this.executor.isShuttingDown();
+        }
+
+        @Override
+        public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
+            return this.executor.shutdownGracefully(quietPeriod, timeout, unit);
+        }
+
+        @Override
+        public Future<?> terminationFuture() {
+            return this.executor.terminationFuture();
+        }
+
+        @Override
+        public boolean isShutdown() {
+            return this.executor.isShutdown();
+        }
+
+        @Override
+        public boolean isTerminated() {
+            return this.executor.isTerminated();
+        }
+
+        @Override
+        public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+            return this.executor.awaitTermination(timeout, unit);
+        }
+
+        @Override
+        public void execute(Runnable command) {
+            this.executor.execute(command);
+        }
+
+        @Override
+        public void close() throws Exception {
+            shutdownGracefully();
+        }
+
+        @SuppressWarnings("deprecation")
+        @Override
+        public void shutdown() {
+            this.executor.shutdown();
+        }
+
+    }
+}
diff --git a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java
new file mode 100644 (file)
index 0000000..79a5121
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+* Generated file
+
+* Generated from: yang module name: netty-event-executor  yang module local name: netty-global-event-executor
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Tue Nov 12 10:44:21 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.netty.eventexecutor;
+
+/**
+*
+*/
+public class GlobalEventExecutorModuleFactory extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModuleFactory
+{
+
+
+}
diff --git a/opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang b/opendaylight/config/netty-event-executor-config/src/main/yang/netty-event-executor.yang
new file mode 100644 (file)
index 0000000..d45eccd
--- /dev/null
@@ -0,0 +1,44 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module netty-event-executor {
+    yang-version 1;
+       namespace "urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor";
+    prefix "netty-t";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import threadpool { prefix th; revision-date 2013-04-09; }
+
+    organization "Cisco Systems, Inc.";
+
+    contact "Milos Fabian <milfabia@cisco.com>";
+
+    description
+        "This module contains the base YANG definitions for NS-OS
+         thread-related services.
+
+        Copyright (c)2013 Cisco Systems, Inc. All rights reserved.;
+        
+        This program and the accompanying materials are made available
+               under the terms of the Eclipse Public License v1.0 which
+               accompanies this distribution, and is available at
+               http://www.eclipse.org/legal/epl-v10.html";
+
+    revision "2013-11-12" {
+        description
+            "Initial revision";
+    }
+    
+    identity netty-global-event-executor {
+        base config:module-type;
+        config:provided-service th:netty-event-executor;
+        config:java-name-prefix GlobalEventExecutor;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case netty-global-event-executor {
+            when "/config:modules/config:module/config:type = 'netty-global-event-executor'";
+
+        }
+    }
+
+
+}
diff --git a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java
new file mode 100644 (file)
index 0000000..6af5088
--- /dev/null
@@ -0,0 +1,64 @@
+package org.opendaylight.controller.config.yang.netty.eventexecutor;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+public class GlobalEventExecutorModuleTest extends AbstractConfigTest {
+
+    private GlobalEventExecutorModuleFactory factory;
+    private final String instanceName = "netty1";
+
+    @Before
+    public void setUp() {
+        factory = new GlobalEventExecutorModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+    }
+
+    @Test
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,
+            ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        createInstance(transaction, instanceName);
+        createInstance(transaction, instanceName + 2);
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(2, factory.getImplementationName());
+        assertStatus(status, 2, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,
+            ValidationException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName);
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 0, 0, 1);
+    }
+
+    private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        transaction.newMBeanProxy(nameCreated, GlobalEventExecutorModuleMXBean.class);
+        return nameCreated;
+    }
+
+}
index 2842b5c450712f5a78d8df67abf534027620a6c3..3f27ff1055882d1352e27f7208d4571919f06e71 100755 (executable)
@@ -32,6 +32,7 @@
         <module>threadpool-config-api</module>
         <module>threadpool-config-impl</module>
         <module>netty-threadgroup-config</module>
+        <module>netty-event-executor-config</module>
     </modules>
 
     <profiles>
index d8ddc4f24d3d843270fb3704a1098e3012dcef33..cddfb6483099d3e8e4e5127484866d102ef86e2c 100644 (file)
@@ -39,6 +39,7 @@
                      org.opendaylight.controller.config.api.*,
                      com.google.common.eventbus,
                      io.netty.channel,
+                     io.netty.util.concurrent
                   </Import-Package>
                   <Export-Package>
                      org.opendaylight.controller.config.threadpool,
index 5cc17e52ffa728ac03924708a804f055157b6ad9..9c73711c17bf98e0547b87674be96fd6451a64f1 100644 (file)
@@ -82,6 +82,14 @@ module threadpool {
         base "config:service-type";
         config:java-class "io.netty.channel.EventLoopGroup";
     }
+    
+    identity netty-event-executor {
+        description
+            "Configuration wrapper around netty's event executor";
+
+        base "config:service-type";
+        config:java-class "io.netty.util.concurrent.EventExecutor";
+    }
 
 
 }
index bb43809a5c63c4bdb08d8bc6cf2e2ca2a3a492f3..a3d11d0374cade2eec78f10440700d3b262754dd 100644 (file)
@@ -29,6 +29,7 @@
         <configuration>
           <instructions>
             <Export-Package>
+              org.opendaylight.controller.datastore
             </Export-Package>
             <Import-Package>
               javax.xml.bind.annotation,
@@ -38,6 +39,7 @@
               org.opendaylight.controller.sal.topology,
               org.opendaylight.controller.clustering.services,
               org.opendaylight.controller.md.sal.common.api.data,
+              org.opendaylight.controller.sal.common.util,
               org.opendaylight.yangtools.yang.binding,
               org.osgi.service.component,
               org.slf4j,
@@ -45,7 +47,8 @@
               org.apache.commons.lang3.builder,
               org.apache.commons.lang3.tuple,
               org.eclipse.osgi.framework.console,
-              org.osgi.framework
+              org.osgi.framework,
+              com.google.common.base
             </Import-Package>
             <Bundle-Activator>
               org.opendaylight.controller.datastore.internal.Activator
index f2e7773a454565e537053f72889cc0ebfb0a3f6a..18b98925637cb1c2d5fc9dbfd39a8c0a72001a48 100644 (file)
@@ -35,19 +35,19 @@ public class ClusteredDataStoreImpl implements ClusteredDataStore {
     public static final String OPERATIONAL_DATA_CACHE = "clustered_data_store.operational_data_cache";
     public static final String CONFIGURATION_DATA_CACHE = "clustered_data_store.configuration_data_cache";
 
-    private ConcurrentMap operationalDataCache;
-    private ConcurrentMap configurationDataCache;
+    private final ConcurrentMap operationalDataCache;
+    private final ConcurrentMap configurationDataCache;
 
     public ClusteredDataStoreImpl(IClusterGlobalServices clusterGlobalServices) throws CacheExistException, CacheConfigException {
         Preconditions.checkNotNull(clusterGlobalServices, "clusterGlobalServices cannot be null");
 
-        operationalDataCache = clusterGlobalServices.createCache(OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+        operationalDataCache = getOrCreateCache(clusterGlobalServices, OPERATIONAL_DATA_CACHE);
 
         if(operationalDataCache == null){
             Preconditions.checkNotNull(operationalDataCache, "operationalDataCache cannot be null");
         }
 
-        configurationDataCache = clusterGlobalServices.createCache(CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+        configurationDataCache = getOrCreateCache(clusterGlobalServices, CONFIGURATION_DATA_CACHE);
 
         if(configurationDataCache == null){
             Preconditions.checkNotNull(configurationDataCache, "configurationDataCache cannot be null");
@@ -95,6 +95,20 @@ public class ClusteredDataStoreImpl implements ClusteredDataStore {
       return Rpcs.<Void>getRpcResult(true, null, _emptySet);
     }
 
+
+    private ConcurrentMap getOrCreateCache(IClusterGlobalServices clusterGlobalServices, String name) throws CacheConfigException {
+        ConcurrentMap cache = clusterGlobalServices.getCache(name);
+
+        if(cache == null) {
+            try {
+                cache = clusterGlobalServices.createCache(name, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+            } catch (CacheExistException e) {
+                cache = clusterGlobalServices.getCache(name);
+            }
+        }
+        return cache;
+    }
+
     private class ClusteredDataStoreTransaction implements DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> {
         private final DataModification<InstanceIdentifier<? extends Object>,Object> modification;
 
index 8049bae5af602845c0b1b34616aef7a0cc1f6b30..d7ae4bf2e5d18797f092acb274dab972bd90bbd1 100644 (file)
@@ -64,6 +64,31 @@ public class ClusteredDataStoreImplTest {
         }
     }
 
+    @Test
+    public void constructor_WhenOperationalDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException {
+        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
+
+        new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+    }
+
+    @Test
+    public void constructor_WhenConfigurationDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException {
+        IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
+        Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
+
+        new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+        verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+    }
+
+
     @Test
     public void constructor_WhenPassedAValidClusteringServices_ShouldNotThrowAnyExceptions() throws CacheExistException, CacheConfigException {
         IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
index 84b07e7cd4dfd971d3e53ee938333e33e7913004..5609134a1a672c4c7eda1e3e3928ab1ca4af75da 100644 (file)
@@ -1,3 +1,12 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
 package org.opendaylight.controller.datastore.internal;
 
 import org.apache.felix.dm.Component;
index 407b46bed1641d5b6b59f2675620d49a79bee5a9..9615decbe9fed710acc0c6674ec0eff3d020ee9d 100644 (file)
   <artifactId>clustered-datastore.integrationtest</artifactId>
   <version>0.4.0-SNAPSHOT</version>
   <dependencies>
+
+      <dependency>
+        <groupId>com.google.guava</groupId>
+        <artifactId>guava</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-common-api</artifactId>
+          <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-common-util</artifactId>
+        <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-common-impl</artifactId>
+        <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-binding-broker-impl</artifactId>
+        <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal</artifactId>
+        <version>0.5.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>clustering.services</artifactId>
+        <version>0.4.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yang-binding</artifactId>
+      </dependency>
+
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>protocol_plugins.stub</artifactId>
       <version>0.4.1-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal</artifactId>
-      <version>0.5.0-SNAPSHOT</version>
     </dependency>
      <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>containermanager.it.implementation</artifactId>
       <version>0.5.0-SNAPSHOT</version>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>clustering.services</artifactId>
-      <version>0.4.0-SNAPSHOT</version>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>clustering.stub</artifactId>
       <version>0.4.1-SNAPSHOT</version>
     </dependency>
 
-  </dependencies>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-common</artifactId>
+          <version>1.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>yang-common</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>concepts</artifactId>
+          <version>0.1.1-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+       <groupId>org.mockito</groupId>
+       <artifactId>mockito-all</artifactId>
+       <version>1.9.5</version>
+       <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.osgi</groupId>
+          <artifactId>org.osgi.core</artifactId>
+          <version>5.0.0</version>
+      </dependency>
+
+</dependencies>
   <properties>
     <!-- Sonar jacoco plugin to get integration test coverage info -->
     <sonar.jacoco.reportPath>../implementation/target/jacoco.exec</sonar.jacoco.reportPath>
index ddf275ec14897d9059cd2fc61236418fa06b694d..e5861ab3c0af825806bd8951684dcf4f1a7a0250 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.controller.datastore;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Configuration;
@@ -16,18 +21,26 @@ import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.util.PathUtils;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.inject.Inject;
 
-import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
 import static org.ops4j.pax.exam.CoreOptions.junitBundles;
 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 import static org.ops4j.pax.exam.CoreOptions.options;
 import static org.ops4j.pax.exam.CoreOptions.systemPackages;
 import static org.ops4j.pax.exam.CoreOptions.systemProperty;
 
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import static org.mockito.Mockito.mock;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
 
 @RunWith(PaxExam.class)
 public class ClusteredDataStoreIT {
@@ -36,7 +49,8 @@ public class ClusteredDataStoreIT {
     // get the OSGI bundle context
     @Inject
     private BundleContext bc;
-
+    @Inject
+    private ClusteredDataStore clusteredDS;
     // Configure the OSGi container
     @Configuration
     public Option[] config() {
@@ -49,6 +63,7 @@ public class ClusteredDataStoreIT {
                 systemProperty("osgi.console").value("2401"),
                 // Set the systemPackages (used by clustering)
                 systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
+                systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG"),
                 // List framework bundles
                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
@@ -83,6 +98,32 @@ public class ClusteredDataStoreIT {
                 mavenBundle("org.opendaylight.controller", "protocol_plugins.stub")
                     .versionAsInProject(),
 
+                //clustered-data-store-implementation dependencies
+                mavenBundle("com.google.guava", "guava")
+                    .versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "sal-common-api")
+                    .versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "sal-common-util")
+                    .versionAsInProject(),
+                mavenBundle("org.opendaylight.controller", "sal-common-impl")
+                    .versionAsInProject(),
+                mavenBundle("org.opendaylight.yangtools", "yang-binding")
+                    .versionAsInProject(),
+
+
+                //sal-common-api dependencies
+                mavenBundle("org.opendaylight.controller", "sal-common")
+                    .versionAsInProject(),
+                mavenBundle("org.opendaylight.yangtools", "yang-common")
+                    .versionAsInProject(),
+                mavenBundle("org.opendaylight.yangtools", "concepts")
+                    .versionAsInProject(),
+                mavenBundle("org.osgi", "org.osgi.core")
+                    .versionAsInProject(),
+                //adding new maven bundles
+                mavenBundle("org.mockito", "mockito-all")
+                    .versionAsInProject(),
+
                 // needed by hosttracker
                 mavenBundle("org.opendaylight.controller", "clustered-datastore-implementation")
                         .versionAsInProject(),
@@ -110,9 +151,137 @@ public class ClusteredDataStoreIT {
         }
     }
 
+    @Before
+    public void areWeReady() {
+        assertNotNull(bc);
+        boolean debugit = false;
+        Bundle b[] = bc.getBundles();
+        for (int i = 0; i < b.length; i++) {
+            int state = b[i].getState();
+            if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
+                log.debug("Bundle:" + b[i].getSymbolicName() + " state:"
+                          + stateToString(state));
+                debugit = true;
+            }
+        }
+        if (debugit) {
+            log.debug("Do some debugging because some bundle is "
+                      + "unresolved");
+        }
+    }
+
+    @Test
+    public void testBundleContextClusteredDS_NotNull() throws Exception{
+        ServiceReference serviceReference = bc.getServiceReference(ClusteredDataStore.class);
+        ClusteredDataStore store = ClusteredDataStore.class.cast(bc.getService(serviceReference));
+        assertNotNull(store);
+    }
+
+    @Test
+    public void testInjected_ClusteredDS_NotNull(){
+        assertNotNull(clusteredDS);
+    }
+
     @Test
-    public void testDoNothing() throws Exception{
-        assertTrue(true);
+    public void requestCommit_readConfigurationData_ShouldVerifyDataAndNoException(){
+        DataModification dataModification = mock(DataModification.class);
+        HashMap map = new HashMap();
+        List list = new ArrayList();
+        list.add("key");
+        InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+        map.put(key, "value");
+        when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
+        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+        dataCommitTrans.finish();
+        String value = (String)clusteredDS.readConfigurationData(key);
+        assertEquals("value",value);
     }
 
+    @Test(expected = NullPointerException.class)
+    public void requestCommit_ShouldThrowException(){
+        DataModification dataModification = null;
+        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+        dataCommitTrans.finish();
+    }
+
+    @Test
+    public void requestCommit_readOperationalData_ShouldVerifyDataAndNoException(){
+        DataModification dataModification = mock(DataModification.class);
+        HashMap map = new HashMap();
+        List list = new ArrayList();
+        list.add("key");
+        InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+        map.put(key, "value");
+        when(dataModification.getUpdatedOperationalData()).thenReturn(map);
+        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+        dataCommitTrans.finish();
+        String value = (String)clusteredDS.readOperationalData(key);
+        assertEquals("value",value);
+    }
+
+    @Test
+    public void requestCommit_readConfigurationData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException(){
+        DataModification dataModification = mock(DataModification.class);
+        HashMap map = new HashMap();
+        List list = new ArrayList();
+        list.add("key");
+        InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+        map.put(key, "value");
+        when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
+        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+        dataCommitTrans.finish();
+        list = new ArrayList();
+        list.add("key1");
+        InstanceIdentifier key1 = new InstanceIdentifier(list,String.class);
+
+        String value = (String)clusteredDS.readConfigurationData(key1);
+        assertNull(value);
+    }
+
+    @Test
+    public void requestCommit_readOperationalData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException(){
+        DataModification dataModification = mock(DataModification.class);
+        HashMap map = new HashMap();
+        List list = new ArrayList();
+        list.add("key");
+        InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+        map.put(key, "value");
+        when(dataModification.getUpdatedOperationalData()).thenReturn(map);
+        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+        dataCommitTrans.finish();
+        list = new ArrayList();
+        list.add("key1");
+        InstanceIdentifier key1 = new InstanceIdentifier(list,String.class);
+
+        String value = (String)clusteredDS.readOperationalData(key1);
+        assertNull(value);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void requestCommit_readConfigurationData_WithNullPathShouldThrowException(){
+        DataModification dataModification = mock(DataModification.class);
+        HashMap map = new HashMap();
+        List list = new ArrayList();
+        list.add("key");
+        InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+        map.put(key, "value");
+        when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
+        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+        dataCommitTrans.finish();
+        String value = (String)clusteredDS.readConfigurationData(null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void requestCommit_readOperationalData_WithNullPathShouldThrowException(){
+        DataModification dataModification = mock(DataModification.class);
+        HashMap map = new HashMap();
+        List list = new ArrayList();
+        list.add("key");
+        InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+        map.put(key, "value");
+        when(dataModification.getOriginalOperationalData()).thenReturn(map);
+        DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+        dataCommitTrans.finish();
+        String value = (String)clusteredDS.readOperationalData(null);
+    }
 }
diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/group-statistics.yang
new file mode 100644 (file)
index 0000000..d589f45
--- /dev/null
@@ -0,0 +1,85 @@
+module opendaylight-group-statistics {
+    namespace "urn:opendaylight:group:statistics";
+    prefix groupstat;
+
+    import yang-ext {prefix ext; revision-date "2013-07-09";}
+    import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+    import opendaylight-group-types {prefix group-types;revision-date "2013-10-18";}
+    import flow-capable-transaction {prefix tr;}
+    
+    revision "2013-11-11" {
+        description "Initial revision of group statistics service";
+    }
+
+       // RPC calls
+       rpc get-all-group-statistics {
+               input {
+            uses inv:node-context-ref;
+        }
+        output {
+            list group-statistics {
+                uses group-types:group-statistics;
+            }
+            uses tr:transaction-aware;
+        }
+       
+       }
+       
+       rpc get-group-statistics {
+               input {
+            uses inv:node-context-ref;
+            leaf group-id{
+               type group-types:group-id;
+            }
+        }
+        output {
+            uses group-types:group-statistics;
+            uses tr:transaction-aware;
+        }
+       
+       }
+       
+       rpc get-group-description {
+               input {
+            uses inv:node-context-ref;
+            leaf group-id{
+               type group-types:group-id;
+            }
+        }
+        output {
+               uses group-types:group-desc-stats;
+            uses tr:transaction-aware;
+        }
+       }
+       
+       rpc get-group-features {
+               input {
+            uses inv:node-context-ref;
+            leaf group-id{
+               type group-types:group-id;
+            }
+        }
+        output {
+               uses group-types:group-features;
+            uses tr:transaction-aware;
+        }
+       }
+       
+
+       //Notification calls
+       
+       notification group-statistics-updated {
+               uses group-types:group-statistics;
+        uses tr:transaction-aware;
+       }
+       
+       notification group-desc-stats-updated {
+               uses group-types:group-desc-stats;
+        uses tr:transaction-aware;
+       }
+
+       notification group-features {
+               uses group-types:group-features;
+        uses tr:transaction-aware;
+       }
+}
diff --git a/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/meter-statistics.yang b/opendaylight/md-sal/model/model-flow-statistics/src/main/yang/meter-statistics.yang
new file mode 100644 (file)
index 0000000..5aea6b7
--- /dev/null
@@ -0,0 +1,87 @@
+module opendaylight-meter-statistics {
+    namespace "urn:opendaylight:meter:statistics";
+    prefix meterstat;
+
+    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-types;revision-date "2013-09-18";}
+    import flow-capable-transaction {prefix tr;}
+    
+
+    revision "2013-11-11" {
+        description "Initial revision of meter statistics service";
+    }
+
+       // RPC calls
+       rpc get-all-meter-statistics {
+               input {
+            uses inv:node-context-ref;
+        }
+        output {
+            list meter-statistics {
+                uses meter-types:meter-statistics;
+                uses tr:transaction-aware;
+            }
+        }
+       
+       }
+       
+       rpc get-meter-statistics {
+               description "RPC Method to send meter statistics request to the give switch for specific meter"; 
+               input {
+            uses inv:node-context-ref;
+            leaf meter-id{
+               type meter-types:meter-id;
+            }
+        }
+        output {
+            uses meter-types:meter-statistics;
+            uses tr:transaction-aware;
+        }
+       
+       }
+       
+       rpc get-meter-config-statistics {
+               input {
+            uses inv:node-context-ref;
+            leaf meter-id{
+               type meter-types:meter-id;
+            }
+        }
+        output {
+               uses meter-types:meter-config-stats;
+            uses tr:transaction-aware;
+        }
+       }
+       
+       rpc get-meter-features {
+               input {
+            uses inv:node-context-ref;
+            leaf meter-id{
+               type meter-types:meter-id;
+               }
+        }
+        output {
+               uses meter-types:meter-features;
+            uses tr:transaction-aware;
+        }
+       }
+       
+
+       //Notification calls
+       
+       notification meter-statistics-updated {
+               uses meter-types:meter-statistics;
+        uses tr:transaction-aware;
+       }
+       
+       notification meter-config-stats-updated {
+               uses meter-types:meter-config-stats;
+        uses tr:transaction-aware;
+       }
+
+       notification meter-features {
+               uses meter-types:meter-features;
+        uses tr:transaction-aware;
+       }
+}
index 55751e5ac7c33a583ea8d4ea36fdf2a4dbe2ce14..04556bbe547a8d22acd9d8584be1ff4386c1ed5f 100644 (file)
@@ -7,6 +7,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import javax.activation.UnsupportedDataTypeException;
+
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
@@ -33,8 +35,18 @@ class JsonMapper {
     
     public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema) throws IOException {
         writer.beginObject();
-        writeChildrenOfParent(writer, data, schema);
+        
+        if (schema instanceof ContainerSchemaNode) {
+            writeContainer(writer, (CompositeNode) data, (ContainerSchemaNode) schema);
+        } else if (schema instanceof ListSchemaNode) {
+            writeList(writer, (CompositeNode) data, (ListSchemaNode) schema);
+        } else {
+            throw new UnsupportedDataTypeException(
+                    "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
+        }
+        
         writer.endObject();
+        
         foundLeafLists.clear();
         foundLists.clear();
     }
@@ -45,6 +57,11 @@ class JsonMapper {
         
         for (Node<?> child : parent.getChildren()) {
             DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes());
+            if (childSchema == null) {
+                throw new UnsupportedDataTypeException("Probably the data node \"" + child.getNodeType().getLocalName()
+                        + "\" is not conform to schema");
+            }
+            
             if (childSchema instanceof ContainerSchemaNode) {
                 writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
             } else if (childSchema instanceof ListSchemaNode) {
@@ -59,6 +76,9 @@ class JsonMapper {
                 }
             } else if (childSchema instanceof LeafSchemaNode) {
                 writeLeaf(writer, (SimpleNode<?>) child, (LeafSchemaNode) childSchema);
+            } else {
+                throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode, ListSchemaNode, "
+                        + "LeafListSchemaNode, or LeafSchemaNode. Other types are not supported yet.");
             }
         }
         
@@ -145,7 +165,9 @@ class JsonMapper {
         } else if (type instanceof BooleanTypeDefinition) {
             writer.value(Boolean.parseBoolean(value));
         } else if (type instanceof EmptyTypeDefinition) {
-            writer.value("[null]");
+            writer.beginArray();
+            writer.nullValue();
+            writer.endArray();
         } else {
             writer.value(value);
         }
index 85592e5aa209a717f32c1144a839e8c23eed4e47..21ecd3133949f2665a7132a417b929951692efc5 100644 (file)
@@ -78,6 +78,9 @@
                             org.opendaylight.controller.netconf.client,
                             org.opendaylight.controller.netconf.util.osgi,
                             org.opendaylight.controller.netconf.util.xml,
+                            io.netty.channel,
+                            io.netty.channel.nio,
+                            io.netty.util.concurrent,
                             org.osgi.framework,
                             org.slf4j,
                             org.w3c.dom,
index d390161affd49ac510ac66fe7cca699b2418f2eb..a20e00bcffcc114ab9849b821898280bc743b4b2 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.controller.netconf.persist.impl;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Sets;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
 import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification;
@@ -53,6 +55,7 @@ public class ConfigPersisterNotificationHandler implements NotificationListener,
 
     private final InetSocketAddress address;
     private final NetconfClientDispatcher dispatcher;
+    private final EventLoopGroup nettyThreadgroup;
 
     private NetconfClient netconfClient;
 
@@ -76,7 +79,9 @@ public class ConfigPersisterNotificationHandler implements NotificationListener,
         this.address = address;
         this.mbeanServer = mbeanServer;
         this.timeout = timeout;
-        this.dispatcher = new NetconfClientDispatcher(Optional.<SSLContext>absent());
+
+        this.nettyThreadgroup = new NioEventLoopGroup();
+        this.dispatcher = new NetconfClientDispatcher(Optional.<SSLContext>absent(), nettyThreadgroup, nettyThreadgroup);
     }
 
     public void init() throws InterruptedException {
@@ -314,9 +319,9 @@ public class ConfigPersisterNotificationHandler implements NotificationListener,
         }
 
         try {
-            dispatcher.close();
+            nettyThreadgroup.shutdownGracefully();
         } catch (Exception e) {
-            logger.warn("Unable to close netconf client dispatcher {}", dispatcher, e);
+            logger.warn("Unable to close netconf client thread group {}", dispatcher, e);
         }
 
         // unregister from JMX
diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/AbstractNetconfClientNotifySessionListener.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/AbstractNetconfClientNotifySessionListener.java
new file mode 100644 (file)
index 0000000..48109d1
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.client;
+
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+
+/**
+ * Class extending {@link NetconfClientSessionListener} to provide notification capability.
+ */
+public abstract class AbstractNetconfClientNotifySessionListener extends NetconfClientSessionListener {
+    /*
+     * Maybe some capabilities could be expressed as internal NetconfClientSessionListener handlers.
+     * It would enable NetconfClient functionality to be extended by using namespace handlers.
+     * So far let just enable notification capability by extending and let parent class intact.
+     */
+
+    /**
+     * As class purpose is to provide notification capability to session listener
+     * onMessage method is not allowed to be further overridden.
+     * {@see #onNotification(NetconfClientSession, NetconfMessage)}
+     *
+     * @param session {@see NetconfClientSessionListener#onMessage(NetconfClientSession, NetconfMessage)}
+     * @param message {@see NetconfClientSessionListener#onMessage(NetconfClientSession, NetconfMessage)}
+     */
+    @Override
+    public final synchronized void onMessage(NetconfClientSession session, NetconfMessage message) {
+        if (isNotification(message)) {
+            onNotification(session, message);
+        } else {
+            super.onMessage(session, message);
+        }
+    }
+
+    /**
+     * Method intended to customize notification processing.
+     *
+     * @param session {@see NetconfClientSessionListener#onMessage(NetconfClientSession, NetconfMessage)}
+     * @param message {@see NetconfClientSessionListener#onMessage(NetconfClientSession, NetconfMessage)}
+     */
+    public abstract void onNotification(NetconfClientSession session, NetconfMessage message);
+
+    private boolean isNotification(NetconfMessage message) {
+        XmlElement xmle = XmlElement.fromDomDocument(message.getDocument());
+        return XmlNetconfConstants.NOTIFICATION_ELEMENT_NAME.equals(xmle.getName()) ;
+    }
+}
index 4df8235441b582f5650edfa6dbd4aca346daf2c2..6fc4da026f38acc3add7538f3c172e2c6ee01a0f 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.client;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import io.netty.channel.EventLoopGroup;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.concurrent.Future;
@@ -17,7 +18,7 @@ import io.netty.util.concurrent.Promise;
 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.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.util.AbstractSslChannelInitializer;
 import org.opendaylight.protocol.framework.AbstractDispatcher;
 import org.opendaylight.protocol.framework.ReconnectStrategy;
 import org.opendaylight.protocol.framework.SessionListener;
@@ -32,7 +33,8 @@ public class NetconfClientDispatcher extends AbstractDispatcher<NetconfClientSes
     private final Optional<SSLContext> maybeContext;
     private final NetconfClientSessionNegotiatorFactory negotatorFactory;
 
-    public NetconfClientDispatcher(final Optional<SSLContext> maybeContext) {
+    public NetconfClientDispatcher(final Optional<SSLContext> maybeContext, EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
+        super(bossGroup, workerGroup);
         this.maybeContext = Preconditions.checkNotNull(maybeContext);
         this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(new HashedWheelTimer());
     }
@@ -48,18 +50,18 @@ public class NetconfClientDispatcher extends AbstractDispatcher<NetconfClientSes
             }
 
             private void initialize(SocketChannel ch, Promise<NetconfClientSession> promise) {
-                new ClientChannelInitializer(maybeContext, negotatorFactory, sessionListener).initialize(ch, promise);
+                new ClientSslChannelInitializer(maybeContext, negotatorFactory, sessionListener).initialize(ch, promise);
             }
         });
     }
 
-    private static class ClientChannelInitializer extends AbstractChannelInitializer {
+    private static class ClientSslChannelInitializer extends AbstractSslChannelInitializer {
 
         private final NetconfClientSessionNegotiatorFactory negotiatorFactory;
         private final NetconfClientSessionListener sessionListener;
 
-        private ClientChannelInitializer(Optional<SSLContext> maybeContext,
-                NetconfClientSessionNegotiatorFactory negotiatorFactory, NetconfClientSessionListener sessionListener) {
+        private ClientSslChannelInitializer(Optional<SSLContext> maybeContext,
+                                            NetconfClientSessionNegotiatorFactory negotiatorFactory, NetconfClientSessionListener sessionListener) {
             super(maybeContext);
             this.negotiatorFactory = negotiatorFactory;
             this.sessionListener = sessionListener;
diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java
new file mode 100644 (file)
index 0000000..ce0f427
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.client;
+
+import io.netty.channel.EventLoopGroup;
+
+public class NetconfSshClientDispatcher extends NetconfClientDispatcher {
+
+    public NetconfSshClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
+        super(null, bossGroup, workerGroup);
+    }
+}
index 33fa675a926677245ae6583acc5106c9327f179c..f1e3f891ee3ff70bda9cfd9fefcc73c714a824e3 100644 (file)
                             io.netty.util.concurrent,
                             io.netty.buffer,
                             io.netty.handler.codec,
+                            io.netty.channel.nio,
                             javax.management,
                             javax.net.ssl,
                             javax.xml.namespace,
index 324da56ca58474ecc2b338e0b4e8a3cc29755d1f..882d368a1af3648b06579903769d48026ecdf38c 100644 (file)
@@ -10,11 +10,12 @@ package org.opendaylight.controller.netconf.impl;
 
 import com.google.common.base.Optional;
 import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.concurrent.Promise;
 import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.impl.util.DeserializerExceptionHandler;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.util.AbstractSslChannelInitializer;
 import org.opendaylight.protocol.framework.AbstractDispatcher;
 
 import javax.net.ssl.SSLContext;
@@ -23,16 +24,14 @@ import java.net.InetSocketAddress;
 
 public class NetconfServerDispatcher extends AbstractDispatcher<NetconfSession, NetconfServerSessionListener> {
 
-    private final ServerChannelInitializer initializer;
+    private final ServerSslChannelInitializer initializer;
 
-    public NetconfServerDispatcher(final Optional<SSLContext> maybeContext,
-            NetconfServerSessionNegotiatorFactory serverNegotiatorFactory,
-            NetconfServerSessionListenerFactory listenerFactory) {
-        this.initializer = new ServerChannelInitializer(maybeContext, serverNegotiatorFactory, listenerFactory);
+    public NetconfServerDispatcher(ServerSslChannelInitializer serverChannelInitializer, EventLoopGroup bossGroup,
+            EventLoopGroup workerGroup) {
+        super(bossGroup, workerGroup);
+        this.initializer = serverChannelInitializer;
     }
 
-    // FIXME change headers for all new source code files
-
     // TODO test create server with same address twice
     public ChannelFuture createServer(InetSocketAddress address) {
 
@@ -44,14 +43,14 @@ public class NetconfServerDispatcher extends AbstractDispatcher<NetconfSession,
         });
     }
 
-    private static class ServerChannelInitializer extends AbstractChannelInitializer {
+    public static class ServerSslChannelInitializer extends AbstractSslChannelInitializer {
 
         private final NetconfServerSessionNegotiatorFactory negotiatorFactory;
         private final NetconfServerSessionListenerFactory listenerFactory;
 
-        private ServerChannelInitializer(Optional<SSLContext> maybeContext,
-                NetconfServerSessionNegotiatorFactory negotiatorFactory,
-                NetconfServerSessionListenerFactory listenerFactory) {
+        public ServerSslChannelInitializer(Optional<SSLContext> maybeContext,
+                                            NetconfServerSessionNegotiatorFactory negotiatorFactory,
+                                            NetconfServerSessionListenerFactory listenerFactory) {
             super(maybeContext);
             this.negotiatorFactory = negotiatorFactory;
             this.listenerFactory = listenerFactory;
index fc240f91c9d168397a82c82f42577310aeb5b408..1a4888ba93b69081ab0d584a1730c7b74d84ed37 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.netconf.impl.osgi;
 
 import com.google.common.base.Optional;
+import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
@@ -35,6 +36,7 @@ public class NetconfImplActivator implements BundleActivator {
     private NetconfOperationServiceFactoryTracker factoriesTracker;
     private DefaultCommitNotificationProducer commitNot;
     private NetconfServerDispatcher dispatch;
+    private NioEventLoopGroup eventLoopGroup;
 
     @Override
     public void start(final BundleContext context) throws Exception {
@@ -56,10 +58,14 @@ public class NetconfImplActivator implements BundleActivator {
         NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
                 factoriesListener, commitNot, idProvider);
 
+        eventLoopGroup = new NioEventLoopGroup();
+
         if (maybeTCPAddress.isPresent()) {
             Optional<SSLContext> maybeSSLContext = Optional.absent();
             InetSocketAddress address = maybeTCPAddress.get();
-            dispatch = new NetconfServerDispatcher(maybeSSLContext, serverNegotiatorFactory, listenerFactory);
+            NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(
+                    maybeSSLContext, serverNegotiatorFactory, listenerFactory);
+            dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup);
 
             logger.info("Starting TCP netconf server at {}", address);
             dispatch.createServer(address);
@@ -67,7 +73,9 @@ public class NetconfImplActivator implements BundleActivator {
         if (maybeTLSConfiguration.isPresent()) {
             Optional<SSLContext> maybeSSLContext = Optional.of(maybeTLSConfiguration.get().getSslContext());
             InetSocketAddress address = maybeTLSConfiguration.get().getAddress();
-            dispatch = new NetconfServerDispatcher(maybeSSLContext, serverNegotiatorFactory, listenerFactory);
+            NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(
+                    maybeSSLContext, serverNegotiatorFactory, listenerFactory);
+            dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup);
 
             logger.info("Starting TLS netconf server at {}", address);
             dispatch.createServer(address);
@@ -79,6 +87,6 @@ public class NetconfImplActivator implements BundleActivator {
         logger.info("Shutting down netconf because YangStoreService service was removed");
 
         commitNot.close();
-        dispatch.close();
+        eventLoopGroup.shutdownGracefully();
     }
 }
index 1295149c0262a7982226c3ae71195b5538fe0155..b363976aaed6b6afd8f3aa4c9844ffb5357a661c 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.controller.netconf.impl;
 import com.google.common.base.Optional;
 import com.google.common.collect.Sets;
 import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
 import org.apache.commons.io.IOUtils;
 import org.junit.After;
@@ -64,7 +66,10 @@ import static org.mockito.Mockito.mock;
 public class ConcurrentClientsTest {
 
     private static final int CONCURRENCY = 16;
-    public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher(Optional.<SSLContext>absent());
+    private static EventLoopGroup nettyGroup = new NioEventLoopGroup();
+    public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher(
+            Optional.<SSLContext> absent(), nettyGroup, nettyGroup);
+
     @Mock
     private YangStoreService yangStoreService;
     @Mock
@@ -77,6 +82,7 @@ public class ConcurrentClientsTest {
     private DefaultCommitNotificationProducer commitNot;
     private NetconfServerDispatcher dispatch;
 
+
     @Before
     public void setUp() throws Exception {
         { // init mocks
@@ -103,7 +109,9 @@ public class ConcurrentClientsTest {
 
         NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
                 factoriesListener, commitNot, idProvider);
-        dispatch = new NetconfServerDispatcher(Optional.<SSLContext> absent(), serverNegotiatorFactory, listenerFactory);
+        NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(
+                Optional.<SSLContext> absent(), serverNegotiatorFactory, listenerFactory);
+        dispatch = new NetconfServerDispatcher(serverChannelInitializer, nettyGroup, nettyGroup);
 
         ChannelFuture s = dispatch.createServer(netconfAddress);
         s.await();
@@ -111,7 +119,7 @@ public class ConcurrentClientsTest {
 
     @AfterClass
     public static void tearDownStatic() {
-        NETCONF_CLIENT_DISPATCHER.close();
+        nettyGroup.shutdownGracefully();
     }
 
     private NetconfOperationServiceFactory mockOpF() {
@@ -160,7 +168,6 @@ public class ConcurrentClientsTest {
     @After
     public void cleanUp() throws Exception {
         commitNot.close();
-        dispatch.close();
     }
 
     @Test
index 233fffda024a30deedcd2bd9ad5a9a343ea327c7..e43febec793f6ad43029169ed083c7ede7f22a4d 100644 (file)
@@ -8,22 +8,35 @@
 
 package org.opendaylight.controller.netconf.impl;
 
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-
-import javax.net.ssl.SSLContext;
-
+import com.google.common.base.Optional;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
 
-import com.google.common.base.Optional;
-
-import io.netty.channel.ChannelFuture;
-import io.netty.util.HashedWheelTimer;
+import javax.net.ssl.SSLContext;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
 
 public class NetconfDispatcherImplTest {
 
+    private EventLoopGroup nettyGroup;
+
+    @Before
+    public void setUp() throws Exception {
+        nettyGroup = new NioEventLoopGroup();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        nettyGroup.shutdownGracefully();
+    }
+
     @Test
     public void test() throws Exception {
 
@@ -37,13 +50,15 @@ public class NetconfDispatcherImplTest {
 
         NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
                 factoriesListener, commitNot, idProvider);
-        NetconfServerDispatcher dispatch = new NetconfServerDispatcher(Optional.<SSLContext> absent(),
-                serverNegotiatorFactory, listenerFactory);
+        NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(Optional.<SSLContext>absent(), serverNegotiatorFactory, listenerFactory);
+
+
+        NetconfServerDispatcher dispatch = new NetconfServerDispatcher(
+                serverChannelInitializer, nettyGroup, nettyGroup);
 
         InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 8333);
         ChannelFuture s = dispatch.createServer(addr);
 
         commitNot.close();
-        dispatch.close();
     }
 }
index 9a4bc2aa5dee09092f7cf04412383d4f62d00dc1..0c22a71c6b38e20b96da5163a26bed1a1b94e30b 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.controller.netconf.it;
 
 import com.google.common.base.Optional;
 import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
 import org.junit.After;
 import org.junit.Before;
@@ -51,6 +53,8 @@ public class NetconfITSecureTest extends AbstractConfigTest {
 
     private DefaultCommitNotificationProducer commitNot;
     private NetconfServerDispatcher dispatchS;
+    private EventLoopGroup nettyThreadgroup;
+
 
     @Before
     public void setUp() throws Exception {
@@ -62,6 +66,8 @@ public class NetconfITSecureTest extends AbstractConfigTest {
 
         commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
 
+        nettyThreadgroup = new NioEventLoopGroup();
+
         dispatchS = createDispatcher(Optional.of(getSslContext()), factoriesListener);
         ChannelFuture s = dispatchS.createServer(tlsAddress);
         s.await();
@@ -76,13 +82,15 @@ public class NetconfITSecureTest extends AbstractConfigTest {
         NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
                 factoriesListener, commitNot, idProvider);
 
-        return new NetconfServerDispatcher(sslC, serverNegotiatorFactory, listenerFactory);
+        NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(
+                sslC, serverNegotiatorFactory, listenerFactory);
+        return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
     }
 
     @After
     public void tearDown() throws Exception {
         commitNot.close();
-        dispatchS.close();
+        nettyThreadgroup.shutdownGracefully();
     }
 
     private SSLContext getSslContext() throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
@@ -106,8 +114,8 @@ public class NetconfITSecureTest extends AbstractConfigTest {
 
     @Test
     public void testSecure() throws Exception {
-        try (NetconfClientDispatcher dispatch = new NetconfClientDispatcher(Optional.of(getSslContext()));
-             NetconfClient netconfClient = new NetconfClient("tls-client", tlsAddress, 4000, dispatch))  {
+        NetconfClientDispatcher dispatch = new NetconfClientDispatcher(Optional.of(getSslContext()), nettyThreadgroup, nettyThreadgroup);
+        try (NetconfClient netconfClient = new NetconfClient("tls-client", tlsAddress, 4000, dispatch))  {
 
         }
     }
index e9fe857bcac571501900dc2111edc2d4567bbe80..403ba3d0fc090ea06e9ce73c4ff4acc2b7fc32c5 100644 (file)
@@ -12,9 +12,10 @@ import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
 import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -90,8 +91,9 @@ public class NetconfITTest extends AbstractConfigTest {
             closeSession, startExi, stopExi;
     private DefaultCommitNotificationProducer commitNot;
     private NetconfServerDispatcher dispatch;
+    private EventLoopGroup nettyThreadgroup;
 
-    private static NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher(Optional.<SSLContext>absent());
+    private NetconfClientDispatcher clientDispatcher;
 
     @Before
     public void setUp() throws Exception {
@@ -103,11 +105,15 @@ public class NetconfITTest extends AbstractConfigTest {
         NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
         factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
 
+        nettyThreadgroup = new NioEventLoopGroup();
+
         commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
 
         dispatch = createDispatcher(Optional.<SSLContext> absent(), factoriesListener);
         ChannelFuture s = dispatch.createServer(tcpAddress);
         s.await();
+
+        clientDispatcher = new NetconfClientDispatcher(Optional.<SSLContext>absent(), nettyThreadgroup, nettyThreadgroup);
     }
 
     private NetconfServerDispatcher createDispatcher(Optional<SSLContext> sslC,
@@ -119,18 +125,15 @@ public class NetconfITTest extends AbstractConfigTest {
         NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
                 factoriesListener, commitNot, idProvider);
 
-        return new NetconfServerDispatcher(sslC, serverNegotiatorFactory, listenerFactory);
+        NetconfServerDispatcher.ServerSslChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerSslChannelInitializer(
+                sslC, serverNegotiatorFactory, listenerFactory);
+        return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
     }
 
     @After
     public void tearDown() throws Exception {
         commitNot.close();
-        dispatch.close();
-    }
-
-    @AfterClass
-    public static void tearDownStatic() {
-        NETCONF_CLIENT_DISPATCHER.close();
+        nettyThreadgroup.shutdownGracefully();
     }
 
     private void loadMessages() throws IOException, SAXException, ParserConfigurationException {
@@ -171,7 +174,7 @@ public class NetconfITTest extends AbstractConfigTest {
 
     @Test
     public void testNetconfClientDemonstration() throws Exception {
-        try (NetconfClient netconfClient = new NetconfClient("client", tcpAddress, 4000, NETCONF_CLIENT_DISPATCHER)) {
+        try (NetconfClient netconfClient = new NetconfClient("client", tcpAddress, 4000, clientDispatcher)) {
 
             Set<String> capabilitiesFromNetconfServer = netconfClient.getCapabilities();
             long sessionId = netconfClient.getSessionId();
@@ -186,8 +189,8 @@ public class NetconfITTest extends AbstractConfigTest {
 
     @Test
     public void testTwoSessions() throws Exception {
-        try (NetconfClient netconfClient = new NetconfClient("1", tcpAddress, 4000, NETCONF_CLIENT_DISPATCHER))  {
-            try (NetconfClient netconfClient2 = new NetconfClient("2", tcpAddress, 4000, NETCONF_CLIENT_DISPATCHER))  {
+        try (NetconfClient netconfClient = new NetconfClient("1", tcpAddress, 4000, clientDispatcher))  {
+            try (NetconfClient netconfClient2 = new NetconfClient("2", tcpAddress, 4000, clientDispatcher))  {
             }
         }
     }
@@ -387,7 +390,7 @@ public class NetconfITTest extends AbstractConfigTest {
         // final InputStream resourceAsStream =
         // AbstractListenerTest.class.getResourceAsStream(fileName);
         // assertNotNull(resourceAsStream);
-        try (NetconfClient netconfClient = new NetconfClient("test", tcpAddress, 5000, NETCONF_CLIENT_DISPATCHER)) {
+        try (NetconfClient netconfClient = new NetconfClient("test", tcpAddress, 5000, clientDispatcher)) {
             // IOUtils.copy(resourceAsStream, netconfClient.getStream());
             // netconfClient.getOutputStream().write(NetconfMessageFactory.endOfMessage);
             // server should not write anything back
@@ -436,7 +439,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);
+        final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, clientDispatcher);
         assertEquals(expected, Long.toString(netconfClient.getSessionId()));
         return netconfClient;
     }
index 5d082c92cda6c59a86fdd557206cb6817a4d4f6e..caee5421525515a2b9cef2b136cf00d2f5944fd5 100644 (file)
@@ -8,73 +8,14 @@
 
 package org.opendaylight.controller.netconf.util;
 
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
-import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory;
-import org.opendaylight.protocol.framework.ProtocolHandlerFactory;
-import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
-import org.opendaylight.protocol.framework.ProtocolMessageEncoder;
-
-import com.google.common.base.Optional;
-
-import io.netty.channel.ChannelHandler;
 import io.netty.channel.socket.SocketChannel;
-import io.netty.handler.ssl.SslHandler;
 import io.netty.util.concurrent.Promise;
+import org.opendaylight.controller.netconf.api.NetconfSession;
 
 public abstract class AbstractChannelInitializer {
 
-    private final Optional<SSLContext> maybeContext;
-    private final NetconfHandlerFactory handlerFactory;
-
-    public AbstractChannelInitializer(Optional<SSLContext> maybeContext) {
-        this.maybeContext = maybeContext;
-        this.handlerFactory = new NetconfHandlerFactory(new NetconfMessageFactory());
-    }
-
-    public void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise) {
-        if (maybeContext.isPresent()) {
-            initSsl(ch);
-        }
-
-        ch.pipeline().addLast("aggregator", new NetconfMessageAggregator(FramingMechanism.EOM));
-        ch.pipeline().addLast(handlerFactory.getDecoders());
-        initializeAfterDecoder(ch, promise);
-        ch.pipeline().addLast("frameEncoder", FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM));
-        ch.pipeline().addLast(handlerFactory.getEncoders());
-    }
+    public abstract void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise);
 
     protected abstract void initializeAfterDecoder(SocketChannel ch, Promise<? extends NetconfSession> promise);
 
-    private void initSsl(SocketChannel ch) {
-        SSLEngine sslEngine = maybeContext.get().createSSLEngine();
-        initSslEngine(sslEngine);
-        final SslHandler handler = new SslHandler(sslEngine);
-        ch.pipeline().addLast("ssl", handler);
-    }
-
-    protected abstract void initSslEngine(SSLEngine sslEngine);
-
-    private static final class NetconfHandlerFactory extends ProtocolHandlerFactory<NetconfMessage> {
-
-        public NetconfHandlerFactory(final NetconfMessageFactory msgFactory) {
-            super(msgFactory);
-        }
-
-        @Override
-        public ChannelHandler[] getEncoders() {
-            return new ChannelHandler[] { new ProtocolMessageEncoder(this.msgFactory) };
-        }
-
-        @Override
-        public ChannelHandler[] getDecoders() {
-            return new ChannelHandler[] { new ProtocolMessageDecoder(this.msgFactory) };
-        }
-    }
 }
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractSslChannelInitializer.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractSslChannelInitializer.java
new file mode 100644 (file)
index 0000000..d490eb2
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.util;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfSession;
+import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
+import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolHandlerFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
+import org.opendaylight.protocol.framework.ProtocolMessageEncoder;
+
+import com.google.common.base.Optional;
+
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.util.concurrent.Promise;
+
+public abstract class AbstractSslChannelInitializer extends AbstractChannelInitializer {
+
+    private final Optional<SSLContext> maybeContext;
+    private final NetconfHandlerFactory handlerFactory;
+
+    public AbstractSslChannelInitializer(Optional<SSLContext> maybeContext) {
+        this.maybeContext = maybeContext;
+        this.handlerFactory = new NetconfHandlerFactory(new NetconfMessageFactory());
+    }
+
+    @Override
+    public void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise) {
+        if (maybeContext.isPresent()) {
+            initSsl(ch);
+        }
+
+        ch.pipeline().addLast("aggregator", new NetconfMessageAggregator(FramingMechanism.EOM));
+        ch.pipeline().addLast(handlerFactory.getDecoders());
+        initializeAfterDecoder(ch, promise);
+        ch.pipeline().addLast("frameEncoder", FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM));
+        ch.pipeline().addLast(handlerFactory.getEncoders());
+    }
+
+    private void initSsl(SocketChannel ch) {
+        SSLEngine sslEngine = maybeContext.get().createSSLEngine();
+        initSslEngine(sslEngine);
+        final SslHandler handler = new SslHandler(sslEngine);
+        ch.pipeline().addLast("ssl", handler);
+    }
+
+    protected abstract void initSslEngine(SSLEngine sslEngine);
+
+    private static final class NetconfHandlerFactory extends ProtocolHandlerFactory<NetconfMessage> {
+
+        public NetconfHandlerFactory(final NetconfMessageFactory msgFactory) {
+            super(msgFactory);
+        }
+
+        @Override
+        public ChannelHandler[] getEncoders() {
+            return new ChannelHandler[] { new ProtocolMessageEncoder(this.msgFactory) };
+        }
+
+        @Override
+        public ChannelHandler[] getDecoders() {
+            return new ChannelHandler[] { new ProtocolMessageDecoder(this.msgFactory) };
+        }
+    }
+}
index 3e862faa7b34c96378002d17d79350fb0d4f45d7..2a900e052bcf9ba378c5e7a39c1de8f8bfd0dbbf 100644 (file)
@@ -31,6 +31,8 @@ public class XmlNetconfConstants {
     public static final String RPC_REPLY_KEY = "rpc-reply";
     public static final String RPC_ERROR = "rpc-error";
     public static final String NAME_KEY = "name";
+    public static final String NOTIFICATION_ELEMENT_NAME = "notification";
+
     //
     //
     public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0";