out/
.externalToolBuilders
maven-eclipse.xml
+.DS_STORE
+.metadata
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.2-SNAPSHOT</version>
+ <relativePath>../../opendaylight/commons/opendaylight</relativePath>
+ </parent>
+ <artifactId>base-features</artifactId>
+ <packaging>kar</packaging>
+ <name>${project.artifactId}</name>
+ <description>Base Features POM</description>
+ <properties>
+ <features.file>features.xml</features.file>
+ </properties>
+ <build>
+ <resources>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <version>${karaf.version}</version>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>features-create-kar</id>
+ <goals>
+ <goal>features-create-kar</goal>
+ </goals>
+ <configuration>
+ <featuresFile>${project.build.directory}/classes/${features.file}</featuresFile>
+ </configuration>
+ </execution>
+ </executions>
+ <!-- There is no useful configuration for the kar mojo. The features-generate-descriptor mojo configuration may be useful -->
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>filter</id>
+ <goals>
+ <goal>resources</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/${features.file}</file>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<features name="base-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+
+ <feature name="base-all" description="OpenDaylight Controller"
+ version="${project.version}">
+ <feature>http</feature>
+ <feature>transaction</feature>
+ <feature>base-felix-dm</feature>
+ <feature>base-aries-spi-fly</feature>
+ <feature>base-dummy-console</feature>
+ <feature>base-apache-commons</feature>
+ <feature>base-eclipselink-persistence</feature>
+ <feature>base-gemini-web</feature>
+ <feature>base-tomcat</feature>
+ <feature>base-netty</feature>
+ <feature>base-jersey</feature>
+ <feature>base-spring-security</feature>
+ </feature>
+ <feature name="base-dummy-console" description="Temporary Dummy Console" version="1.1.0-SNAPSHOT">
+ <bundle>mvn:org.opendaylight.controller/dummy-console/1.1.0-SNAPSHOT</bundle>
+ </feature>
+ <feature name="base-felix-dm" description="Felix Dependency Manager"
+ version="${felix.dependencymanager.version}">
+ <bundle start-level="35">mvn:org.osgi/org.osgi.compendium/${osgi.compendium.version}</bundle>
+ <bundle start-level="35">mvn:org.apache.felix/org.apache.felix.dependencymanager/${felix.dependencymanager.version}</bundle>
+ <bundle start-level="35">mvn:org.apache.felix/org.apache.felix.dependencymanager.shell/${felix.dependencymanager.shell.version}</bundle>
+ </feature>
+ <feature name="base-aries-spi-fly" description="Aries SPI Fly"
+ version="${spifly.version}">
+ <bundle start-level="35">mvn:org.apache.aries/org.apache.aries.util/1.1.0</bundle>
+ <bundle start-level="35">mvn:org.apache.aries.spifly/org.apache.aries.spifly.dynamic.bundle/${spifly.version}</bundle>
+ <bundle start-level="35">mvn:org.ow2.asm/asm-all/4.0</bundle>
+ </feature>
+ <feature name='base-netty' version='${netty.version}'>
+ <bundle>wrap:mvn:io.netty/netty-buffer/${netty.version}</bundle>
+ <bundle>wrap:mvn:io.netty/netty-codec/${netty.version}</bundle>
+ <bundle>wrap:mvn:io.netty/netty-transport/${netty.version}</bundle>
+ <bundle>wrap:mvn:io.netty/netty-common/${netty.version}</bundle>
+ <bundle>wrap:mvn:io.netty/netty-handler/${netty.version}</bundle>
+ <bundle>wrap:mvn:io.netty/netty-codec-http/${netty.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.thirdparty/ganymed/1.1-SNAPSHOT</bundle>
+ </feature>
+ <feature name="base-jersey" description="Jersey" version="${jersey.version}">
+ <feature>base-gemini-web</feature>
+ <bundle>mvn:org.opendaylight.controller.thirdparty/com.sun.jersey.jersey-servlet/${jersey.version}</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-server/${jersey.version}</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-client/${jersey.version}</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-servlet/${jersey.version}</bundle>
+ </feature>
+ <feature name="base-jackson" description="Jackson JAX-RS" version="${jackson.version}">
+ <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-annotations/${jackson.version}</bundle>
+ <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-core/${jackson.version}</bundle>
+ <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.core/jackson-databind/${jackson.version}</bundle>
+ <bundle start="true" start-level="35">mvn:org.codehaus.jettison/jettison/${jettison.version}</bundle>
+ <bundle start="true" start-level="35">mvn:javax.ws.rs/jsr311-api/${jsr311.api.version}</bundle>
+ <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.module/jackson-module-jaxb-annotations/${jackson.version}</bundle>
+ <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/${jackson.version}</bundle>
+ <bundle start="true" start-level="35">mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/${jackson.version}</bundle>
+ </feature>
+ <feature name="base-slf4j" description="SLF4J Logging" version="${slf4j.version}">
+ <bundle start-level="35">mvn:org.slf4j/slf4j-jdk14/1.7.2</bundle>
+ <bundle start-level="35">mvn:org.slf4j/slf4j-nop/1.7.2</bundle>
+ <bundle start-level="35">mvn:org.slf4j/slf4j-simple/1.7.2</bundle>
+ <bundle start="true" start-level="35">mvn:org.slf4j/slf4j-api/1.7.2</bundle>
+ </feature>
+ <feature name="base-apache-commons" description="Apache Commons Libraries"
+ version="${project.version}">
+ <bundle start="true" start-level="35">mvn:com.google.guava/guava/${guava.version}</bundle>
+ <bundle start="true" start-level="35">mvn:org.javassist/javassist/${javassist.version}</bundle>
+ <bundle start="true" start-level="35">mvn:commons-io/commons-io/${commons.io.version}</bundle>
+ <bundle start="true" start-level="35">mvn:commons-codec/commons-codec/${commons.codec.version}</bundle>
+ <bundle start="true" start-level="35">mvn:org.apache.commons/commons-lang3/${commons.lang.version}</bundle>
+ <bundle start="true" start-level="35">mvn:commons-net/commons-net/${commons.net.version}</bundle>
+ </feature>
+ <feature name="base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
+ <bundle start="true" start-level="35">mvn:eclipselink/javax.persistence/2.0.4.v201112161009</bundle>
+ <bundle start="true" start-level="35">mvn:eclipselink/javax.resource/1.5.0.v200906010428</bundle>
+ </feature>
+ <feature name="base-gemini-web" description="Gemini Web" version="${geminiweb.version}">
+ <feature>http</feature>
+ <feature>transaction</feature>
+ <feature>base-slf4j</feature>
+ <feature>base-felix-dm</feature>
+ <feature>base-jackson</feature>
+ <feature>base-apache-commons</feature>
+ <bundle start="true" start-level="35">mvn:com.google.code.gson/gson/${gson.version}</bundle>
+ <bundle start="true" start-level="35">mvn:commons-fileupload/commons-fileupload/${commons.fileupload.version}</bundle>
+ <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.core/${geminiweb.version}</bundle>
+ <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.extender/${geminiweb.version}</bundle>
+ <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.common/${virgo.version}</bundle>
+ <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.io/${virgo.version}</bundle>
+ <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.math/${virgo.version}</bundle>
+ <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.osgi/${virgo.version}</bundle>
+ <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.osgi.manifest/${virgo.version}</bundle>
+ <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.virgo.util.parser.manifest/${virgo.version}</bundle>
+ <bundle start="true" start-level="35">mvn:org.apache.felix/org.apache.felix.fileinstall/3.1.6</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/javax.activation/1.1.0.v201211130549</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/javax.annotation/1.1.0.v201209060031</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/javax.ejb/3.1.1.v201204261316</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/javax.el/2.2.0.v201108011116</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/javax.mail.glassfish/1.4.1.v201108011116</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/javax.xml.rpc/1.1.0.v201005080400</bundle>
+ <bundle start="true" start-level="35">mvn:org.eclipse.jetty.orbit/javax.servlet.jsp/2.2.0.v201112011158</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/javax.servlet.jsp.jstl/1.2.0.v201105211821</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/javax.servlet.jsp.jstl.impl/1.2.0.v201210211230</bundle>
+ </feature>
+ <feature name="base-tomcat" description="OpenDaylight Tomcat" version="7.0.32">
+ <feature>base-gemini-web</feature>
+ <feature>base-eclipselink-persistence</feature>
+ <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina/7.0.32.v201211201336</bundle>
+ <bundle start="true" start-level="35">mvn:geminiweb/org.eclipse.gemini.web.tomcat/${geminiweb.version}</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina.ha/7.0.32.v201211201952</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/org.apache.catalina.tribes/7.0.32.v201211201952</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/org.apache.coyote/7.0.32.v201211201952</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/org.apache.el/7.0.32.v201211081135</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/org.apache.jasper/7.0.32.v201211201952</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/org.apache.juli.extras/7.0.32.v201211081135</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/org.apache.tomcat.api/7.0.32.v201211081135</bundle>
+ <bundle start="true" start-level="35">mvn:orbit/org.apache.tomcat.util/7.0.32.v201211201952</bundle>
+ <bundle start="true" start-level="35">wrap:mvn:virgomirror/org.eclipse.jdt.core.compiler.batch/3.8.0.I20120518-2145</bundle>
+ </feature>
+ <feature name="base-spring" description="Opendaylight Spring Support" version="${spring.version}">
+ <bundle>mvn:org.ow2.asm/asm-all/${asm.version}</bundle>
+ <bundle>mvn:org.aopalliance/com.springsource.org.aopalliance/${aopalliance.version}</bundle>
+ <bundle>mvn:org.springframework/org.springframework.aop/${spring.version}</bundle>
+ <bundle>mvn:org.springframework/org.springframework.asm/${spring.version}</bundle>
+ <bundle>mvn:org.springframework/org.springframework.beans/${spring.version}</bundle>
+ <bundle>mvn:org.springframework/org.springframework.context/${spring.version}</bundle>
+ <bundle>mvn:org.springframework/org.springframework.context.support/${spring.version}</bundle>
+ <bundle>mvn:org.springframework/org.springframework.core/${spring.version}</bundle>
+ <bundle>mvn:org.springframework/org.springframework.expression/${spring.version}</bundle>
+ <bundle>mvn:org.springframework/org.springframework.transaction/${spring.version}</bundle>
+ </feature>
+ <feature name="base-spring-web" description="OpenDaylight Spring Web" version="${spring.version}">
+ <feature>base-spring</feature>
+ <feature>base-gemini-web</feature>
+ <bundle>mvn:org.springframework/org.springframework.web/${spring.version}</bundle>
+ <bundle>mvn:org.springframework/org.springframework.web.servlet/${spring.version}</bundle>
+ </feature>
+ <feature name="base-spring-security" description="OpenDaylight Spring Security" version="${spring-security.version}">
+ <feature>base-spring-web</feature>
+ <bundle>mvn:org.springframework.security/spring-security-config/${spring-security.version}</bundle>
+ <bundle>mvn:org.springframework.security/spring-security-core/${spring-security.version}</bundle>
+ <bundle>mvn:org.springframework.security/spring-security-taglibs/${spring-security.version}</bundle>
+ <bundle>mvn:org.springframework.security/spring-security-web/${spring-security.version}</bundle>
+ </feature>
+</features>
<appauth.version>0.4.2-SNAPSHOT</appauth.version>
<!-- Controller Modules Versions -->
<arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
+ <aries.util.version>1.1.0</aries.util.version>
<asm.version>4.1</asm.version>
<!-- Plugin Versions -->
<bouncycastle.version>1.50</bouncycastle.version>
<artifactId>ietf-netconf-monitoring-extension</artifactId>
<version>${netconf.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ <version>${netconf.version}</version>
+ <type>test-jar</type>
+ </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<artifactId>concepts</artifactId>
<version>${yangtools.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>object-cache-api</artifactId>
+ <version>${yangtools.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>object-cache-guava</artifactId>
+ <version>${yangtools.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>restconf-client-api</artifactId>
-
-
package org.opendaylight.controller.config.yang.test.impl;
public class DepTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModule {
public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-
-
package org.opendaylight.controller.config.yang.test.impl;
public class IdentityTestModule extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModule {
public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-
-
package org.opendaylight.controller.config.yang.test.impl;
public class NetconfTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModule {
public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
-
-
package org.opendaylight.controller.config.yang.test.impl;
public class TestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModule {
public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
<!-- scope is runtime so the feature repo is listed in the features
service config file, and features may be installed using the
karaf-maven-plugin configuration -->
- <!-- dependencies commented out till we can get them in
<dependency>
<groupId>org.apache.karaf.features</groupId>
<artifactId>standard</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
+ <!-- scope is compile so all features (there is only one) are installed
+ into startup.properties and the feature repo itself is not installed -->
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>base-features</artifactId>
+ <version>${project.version}</version>
+ <type>kar</type>
+ <scope>runtime</scope>
+ </dependency>
+ <!--<dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>base-features</artifactId>
+ <version>${project.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>-->
+ <!-- <dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>controller-features</artifactId>
<version>${project.version}</version>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netconf-monitoring</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netconf-ssh</artifactId>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>concepts</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>object-cache-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>object-cache-guava</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>restconf-client-api</artifactId>
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
-import java.util.concurrent.Callable;
import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
// to augmentation class
// if child is referenced - so we will reference child and then shorten
// path.
+ LOG.trace("Looking for candidates to match {}", normalized);
for (QName child : lastArgument.getPossibleChildNames()) {
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
ImmutableList.<PathArgument> builder().addAll(normalized.getPath()).add(new NodeIdentifier(child))
.build());
try {
- if (!isNotRepresentable(childPath)) {
- InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(toBindingImpl(
- childPath).get());
- int potentialAugmentCount = getAugmentationCount(potentialPath);
- if(potentialAugmentCount == normalizedCount) {
- return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
- }
+ if (isNotRepresentable(childPath)) {
+ LOG.trace("Path {} is not BI-representable, skipping it", childPath);
+ continue;
}
- } catch (Exception e) {
- LOG.trace("Unable to deserialize aug. child path for {}", childPath, e);
+ } catch (DataNormalizationException e) {
+ LOG.warn("Failed to denormalize path {}, skipping it", childPath, e);
+ continue;
+ }
+
+ Optional<InstanceIdentifier<? extends DataObject>> baId = toBindingImpl(childPath);
+ if (!baId.isPresent()) {
+ LOG.debug("No binding-aware identifier found for path {}, skipping it", childPath);
+ continue;
+ }
+
+ InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(baId.get());
+ int potentialAugmentCount = getAugmentationCount(potentialPath);
+ if (potentialAugmentCount == normalizedCount) {
+ LOG.trace("Found matching path {}", potentialPath);
+ return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
}
+
+ LOG.trace("Skipping mis-matched potential path {}", potentialPath);
}
+
+ LOG.trace("Failed to find augmentation matching {}", normalized);
return Optional.absent();
}
} else if (List.class.isAssignableFrom(returnType)) {
try {
return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(),
- new Callable<Class>() {
-
- @SuppressWarnings("rawtypes")
+ new Supplier<Class>() {
@Override
- public Class call() throws Exception {
+ public Class get() {
Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
.getGenericReturnType());
if (listResult instanceof Class
import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
*/
package org.opendaylight.controller.test.sal.binding.it;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.options.DefaultCompositeOption;
-import org.ops4j.pax.exam.util.PathUtils;
-
import static org.ops4j.pax.exam.CoreOptions.frameworkProperty;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.options.DefaultCompositeOption;
+import org.ops4j.pax.exam.util.PathUtils;
+
public class TestHelper {
public static final String CONTROLLER = "org.opendaylight.controller";
mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), //
mavenBundle(CONTROLLER, "netconf-util").versionAsInProject(), //
+ mavenBundle(CONTROLLER, "netconf-netty-util").versionAsInProject(), //
mavenBundle("org.openexi", "nagasena").versionAsInProject(), //
mavenBundle("org.openexi", "nagasena-rta").versionAsInProject(), //
mavenBundle(CONTROLLER + ".thirdparty", "ganymed").versionAsInProject(), //
+++ /dev/null
-/*
- * Copyright (c) 2014 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.md.sal.dom.store.impl;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-import com.google.common.base.Optional;
-
-class DataAndMetadataSnapshot {
-
- private final StoreMetadataNode metadataTree;
- private final Optional<SchemaContext> schemaContext;
-
- private DataAndMetadataSnapshot(final StoreMetadataNode metadataTree, final Optional<SchemaContext> schemaCtx) {
- this.metadataTree = metadataTree;
- this.schemaContext = schemaCtx;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static DataAndMetadataSnapshot createEmpty() {
- return createEmpty(new NodeIdentifier(SchemaContext.NAME));
- }
-
-
- public static DataAndMetadataSnapshot createEmpty(final NodeIdentifier rootNode) {
- NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(rootNode).build();
- StoreMetadataNode metadata = StoreMetadataNode.createEmpty(data);
- return new DataAndMetadataSnapshot(metadata,Optional.<SchemaContext>absent());
- }
-
- public static DataAndMetadataSnapshot createEmpty(final SchemaContext ctx) {
- NodeIdentifier rootNodeIdentifier = new NodeIdentifier(ctx.getQName());
- NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(rootNodeIdentifier).build();
- StoreMetadataNode metadata = StoreMetadataNode.createEmpty(data);
- return new DataAndMetadataSnapshot(metadata, Optional.of(ctx));
- }
-
- public Optional<SchemaContext> getSchemaContext() {
- return schemaContext;
- }
-
- public NormalizedNode<?, ?> getDataTree() {
- return metadataTree.getData();
- }
-
- public StoreMetadataNode getMetadataTree() {
- return metadataTree;
- }
-
- public Optional<StoreMetadataNode> read(final InstanceIdentifier path) {
- return TreeNodeUtils.findNode(metadataTree, path);
- }
-
- public static class Builder {
- private StoreMetadataNode metadataTree;
- private SchemaContext schemaContext;
-
- public Builder setMetadataTree(final StoreMetadataNode metadataTree) {
- this.metadataTree = metadataTree;
- return this;
- }
-
- public Builder setSchemaContext(final SchemaContext schemaContext) {
- this.schemaContext = schemaContext;
- return this;
- }
-
- public DataAndMetadataSnapshot build() {
- return new DataAndMetadataSnapshot(metadataTree, Optional.fromNullable(schemaContext));
- }
-
- }
-}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.md.sal.dom.store.impl;
+
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * Read-only snapshot of the data tree.
+ */
+final class DataTree {
+ public static final class Snapshot {
+ private final SchemaContext schemaContext;
+ private final StoreMetadataNode rootNode;
+
+ @VisibleForTesting
+ Snapshot(final SchemaContext schemaContext, final StoreMetadataNode rootNode) {
+ this.schemaContext = Preconditions.checkNotNull(schemaContext);
+ this.rootNode = Preconditions.checkNotNull(rootNode);
+ }
+
+ public SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
+ public Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
+ return NormalizedNodeUtils.findNode(rootNode.getData(), path);
+ }
+
+ // FIXME: this is a leak of information
+ @Deprecated
+ StoreMetadataNode getRootNode() {
+ return rootNode;
+ }
+
+ @Override
+ public String toString() {
+ return rootNode.getSubtreeVersion().toString();
+ }
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(DataTree.class);
+ private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
+ private StoreMetadataNode rootNode;
+ private SchemaContext currentSchemaContext;
+
+ private DataTree(StoreMetadataNode rootNode, final SchemaContext schemaContext) {
+ this.rootNode = Preconditions.checkNotNull(rootNode);
+ this.currentSchemaContext = schemaContext;
+ }
+
+ public synchronized void setSchemaContext(final SchemaContext newSchemaContext) {
+ Preconditions.checkNotNull(newSchemaContext);
+
+ LOG.info("Attepting to install schema context {}", newSchemaContext);
+
+ /*
+ * FIXME: we should walk the schema contexts, both current and new and see
+ * whether they are compatible here. Reject incompatible changes.
+ */
+
+ // Ready to change the context now, make sure no operations are running
+ rwLock.writeLock().lock();
+ try {
+ this.currentSchemaContext = newSchemaContext;
+ } finally {
+ rwLock.writeLock().unlock();
+ }
+ }
+
+ public static DataTree create(final SchemaContext schemaContext) {
+ final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
+ final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
+
+ return new DataTree(StoreMetadataNode.createEmpty(data), schemaContext);
+ }
+
+ public Snapshot takeSnapshot() {
+ rwLock.readLock().lock();
+
+ try {
+ return new Snapshot(currentSchemaContext, rootNode);
+ } finally {
+ rwLock.readLock().unlock();
+ }
+ }
+
+ public void commitSnapshot(Snapshot currentSnapshot, StoreMetadataNode newDataTree) {
+ // Ready to change the context now, make sure no operations are running
+ rwLock.writeLock().lock();
+ try {
+ Preconditions.checkState(currentSnapshot.rootNode == rootNode,
+ String.format("Store snapshot %s and transaction snapshot %s differ.",
+ rootNode, currentSnapshot.rootNode));
+
+ this.rootNode = newDataTree;
+ } finally {
+ rwLock.writeLock().unlock();
+ }
+ }
+}
import java.util.Collections;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.slf4j.Logger;
private final ListeningExecutorService executor;
private final String name;
private final AtomicLong txCounter = new AtomicLong(0);
- private final ListenerTree listenerTree;
- private final AtomicReference<DataAndMetadataSnapshot> snapshot;
-
- private ModificationApplyOperation operationTree;
-
- private SchemaContext schemaContext;
+ private final ListenerTree listenerTree = ListenerTree.create();
+ private final DataTree dataTree = DataTree.create(null);
+ private ModificationApplyOperation operationTree = new AlwaysFailOperation();
public InMemoryDOMDataStore(final String name, final ListeningExecutorService executor) {
this.name = Preconditions.checkNotNull(name);
this.executor = Preconditions.checkNotNull(executor);
- this.listenerTree = ListenerTree.create();
- this.snapshot = new AtomicReference<DataAndMetadataSnapshot>(DataAndMetadataSnapshot.createEmpty());
- this.operationTree = new AlwaysFailOperation();
}
@Override
@Override
public DOMStoreReadTransaction newReadOnlyTransaction() {
- return new SnapshotBackedReadTransaction(nextIdentifier(), snapshot.get());
+ return new SnapshotBackedReadTransaction(nextIdentifier(), dataTree.takeSnapshot());
}
@Override
public DOMStoreReadWriteTransaction newReadWriteTransaction() {
- return new SnapshotBackedReadWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree);
+ return new SnapshotBackedReadWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this, operationTree);
}
@Override
public DOMStoreWriteTransaction newWriteOnlyTransaction() {
- return new SnapshotBackedWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree);
+ return new SnapshotBackedWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this, operationTree);
}
@Override
public synchronized void onGlobalContextUpdated(final SchemaContext ctx) {
- operationTree = SchemaAwareApplyOperationRoot.from(ctx);
- schemaContext = ctx;
+ /*
+ * Order of operations is important: dataTree may reject the context
+ * and creation of ModificationApplyOperation may fail. So pre-construct
+ * the operation, then update the data tree and then move the operation
+ * into view.
+ */
+ final ModificationApplyOperation newOperationTree = SchemaAwareApplyOperationRoot.from(ctx);
+ dataTree.setSchemaContext(ctx);
+ operationTree = newOperationTree;
}
@Override
reg = listenerTree.registerDataChangeListener(path, listener, scope);
- Optional<StoreMetadataNode> currentState = snapshot.get().read(path);
+ Optional<NormalizedNode<?, ?>> currentState = dataTree.takeSnapshot().readNode(path);
if (currentState.isPresent()) {
- final NormalizedNode<?, ?> data = currentState.get().getData();
+ final NormalizedNode<?, ?> data = currentState.get();
final DOMImmutableDataChangeEvent event = DOMImmutableDataChangeEvent.builder(DataChangeScope.BASE) //
.setAfter(data) //
return name + "-" + txCounter.getAndIncrement();
}
- private void commit(final DataAndMetadataSnapshot currentSnapshot, final StoreMetadataNode newDataTree,
+ private void commit(final DataTree.Snapshot currentSnapshot, final StoreMetadataNode newDataTree,
final ResolveDataChangeEventsTask listenerResolver) {
- LOG.debug("Updating Store snaphot version: {} with version:{}", currentSnapshot.getMetadataTree()
- .getSubtreeVersion(), newDataTree.getSubtreeVersion());
+ LOG.debug("Updating Store snaphot version: {} with version:{}", currentSnapshot, newDataTree.getSubtreeVersion());
if (LOG.isTraceEnabled()) {
LOG.trace("Data Tree is {}", StoreUtils.toStringTree(newDataTree.getData()));
}
- final DataAndMetadataSnapshot newSnapshot = DataAndMetadataSnapshot.builder() //
- .setMetadataTree(newDataTree) //
- .setSchemaContext(schemaContext) //
- .build();
-
/*
* The commit has to occur atomically with regard to listener
* registrations.
*/
synchronized (this) {
- final boolean success = snapshot.compareAndSet(currentSnapshot, newSnapshot);
- checkState(success, "Store snapshot and transaction snapshot differ. This should never happen.");
+ dataTree.commitSnapshot(currentSnapshot, newDataTree);
for (ChangeListenerNotifyTask task : listenerResolver.call()) {
LOG.trace("Scheduling invocation of listeners: {}", task);
}
}
- private static class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements
+ private static final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements
DOMStoreReadTransaction {
- private DataAndMetadataSnapshot stableSnapshot;
+ private DataTree.Snapshot stableSnapshot;
- public SnapshotBackedReadTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot) {
+ public SnapshotBackedReadTransaction(final Object identifier, final DataTree.Snapshot snapshot) {
super(identifier);
this.stableSnapshot = Preconditions.checkNotNull(snapshot);
- LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree()
- .getSubtreeVersion());
+ LOG.debug("ReadOnly Tx: {} allocated with snapshot {}", identifier, snapshot);
}
@Override
public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final InstanceIdentifier path) {
checkNotNull(path, "Path must not be null.");
checkState(stableSnapshot != null, "Transaction is closed");
- return Futures.immediateFuture(NormalizedNodeUtils.findNode(stableSnapshot.getDataTree(), path));
+ return Futures.immediateFuture(stableSnapshot.readNode(path));
}
}
private InMemoryDOMDataStore store;
private boolean ready = false;
- public SnapshotBackedWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot,
+ public SnapshotBackedWriteTransaction(final Object identifier, final DataTree.Snapshot snapshot,
final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
super(identifier);
mutableTree = MutableDataTree.from(snapshot, applyOper);
this.store = store;
- LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree()
- .getSubtreeVersion());
+ LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot);
}
@Override
private static class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction implements
DOMStoreReadWriteTransaction {
- protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot,
+ protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataTree.Snapshot snapshot,
final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
super(identifier, snapshot, store, applyOper);
}
private final SnapshotBackedWriteTransaction transaction;
private final NodeModification modification;
- private DataAndMetadataSnapshot storeSnapshot;
+ private DataTree.Snapshot storeSnapshot;
private Optional<StoreMetadataNode> proposedSubtree;
private ResolveDataChangeEventsTask listenerResolver;
@Override
public ListenableFuture<Boolean> canCommit() {
- final DataAndMetadataSnapshot snapshotCapture = snapshot.get();
+ final DataTree.Snapshot snapshotCapture = dataTree.takeSnapshot();
final ModificationApplyOperation snapshotOperation = operationTree;
return executor.submit(new Callable<Boolean>() {
Boolean applicable = false;
try {
snapshotOperation.checkApplicable(PUBLIC_ROOT_PATH, modification,
- Optional.of(snapshotCapture.getMetadataTree()));
+ Optional.of(snapshotCapture.getRootNode()));
applicable = true;
} catch (DataPreconditionFailedException e) {
LOG.warn("Store Tx: {} Data Precondition failed for {}.",transaction.getIdentifier(),e.getPath(),e);
@Override
public ListenableFuture<Void> preCommit() {
- storeSnapshot = snapshot.get();
+ storeSnapshot = dataTree.takeSnapshot();
if (modification.getModificationType() == ModificationType.UNMODIFIED) {
return Futures.immediateFuture(null);
}
@Override
public Void call() throws Exception {
- StoreMetadataNode metadataTree = storeSnapshot.getMetadataTree();
+ StoreMetadataNode metadataTree = storeSnapshot.getRootNode();
proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree),
increase(metadataTree.getSubtreeVersion()));
private static final Logger LOG = LoggerFactory.getLogger(MutableDataTree.class);
private final AtomicBoolean sealed = new AtomicBoolean();
private final ModificationApplyOperation strategyTree;
- private final DataAndMetadataSnapshot snapshot;
private final NodeModification rootModification;
+ private final DataTree.Snapshot snapshot;
- private MutableDataTree(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation strategyTree) {
- this.snapshot = snapshot;
- this.strategyTree = strategyTree;
- this.rootModification = NodeModification.createUnmodified(snapshot.getMetadataTree());
+ private MutableDataTree(final DataTree.Snapshot snapshot, final ModificationApplyOperation strategyTree) {
+ this.snapshot = Preconditions.checkNotNull(snapshot);
+ this.strategyTree = Preconditions.checkNotNull(strategyTree);
+ this.rootModification = NodeModification.createUnmodified(snapshot.getRootNode());
}
public void write(final InstanceIdentifier path, final NormalizedNode<?, ?> value) {
return potentialSnapshot.get();
}
return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
- StoreUtils.increase(snapshot.getMetadataTree().getSubtreeVersion()));
+ StoreUtils.increase(snapshot.getRootNode().getSubtreeVersion()));
} catch (Exception e) {
LOG.error("Could not create snapshot for {}:{}", path,modification,e);
throw e;
return OperationWithModification.from(operation, modification);
}
- public static MutableDataTree from(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation resolver) {
+ public static MutableDataTree from(final DataTree.Snapshot snapshot, final ModificationApplyOperation resolver) {
return new MutableDataTree(snapshot, resolver);
}
@Override
public ListenableFuture<RpcResult<CompositeNode>> rpc(QName type, CompositeNode input) {
- return null;
+ return rpcs.invokeRpc( type, input );
}
@Override
@Test
public void basicReadWrites() {
- MutableDataTree modificationTree = MutableDataTree.from(
- DataAndMetadataSnapshot.builder() //
- .setMetadataTree(StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))) //
- .setSchemaContext(schemaContext) //
- .build(), new SchemaAwareApplyOperationRoot(schemaContext));
+ MutableDataTree modificationTree = MutableDataTree.from(new DataTree.Snapshot(schemaContext,
+ StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))),
+ new SchemaAwareApplyOperationRoot(schemaContext));
Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.read(OUTER_LIST_2_PATH);
assertTrue(originalBarNode.isPresent());
assertSame(BAR_NODE, originalBarNode.get());
/**
* Creates empty Snapshot with associated schema context.
*/
- DataAndMetadataSnapshot emptySnapshot = DataAndMetadataSnapshot.createEmpty(schemaContext);
+ DataTree t = DataTree.create(schemaContext);
/**
*
* context.
*
*/
- MutableDataTree modificationTree = MutableDataTree.from(emptySnapshot, new SchemaAwareApplyOperationRoot(
+ MutableDataTree modificationTree = MutableDataTree.from(t.takeSnapshot(), new SchemaAwareApplyOperationRoot(
schemaContext));
return modificationTree;
}
import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.LoginPassword;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-remote</artifactId>
<instructions>
<Bundle-Name>MD SAL Restconf Connector</Bundle-Name>
<Private-Package>org.opendaylight.controller.sal.rest.*,
+ org.opendaylight.controller.sal.restconf.rpc.*,
org.opendaylight.controller.sal.restconf.impl,</Private-Package>
<Import-Package>*,
com.sun.jersey.spi.container.servlet</Import-Package>
/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2014 Brocade Communication Systems, Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.rpc.impl.BrokerRpcExecutor;
+import org.opendaylight.controller.sal.restconf.rpc.impl.MountPointRpcExecutor;
+import org.opendaylight.controller.sal.restconf.rpc.impl.RpcExecutor;
import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.controller.sal.streams.listeners.Notificator;
import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
public class RestconfImpl implements RestconfService {
private final static RestconfImpl INSTANCE = new RestconfImpl();
+ private static final int CHAR_NOT_FOUND = -1;
+
private final static String MOUNT_POINT_MODULE_NAME = "ietf-netconf";
private final static SimpleDateFormat REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
@Override
public StructuredData invokeRpc(final String identifier, final CompositeNode payload) {
- final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
- if (Objects.equal(rpc.getQName().getNamespace().toString(), SAL_REMOTE_NAMESPACE) &&
- Objects.equal(rpc.getQName().getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
+ final RpcExecutor rpc = this.resolveIdentifierInInvokeRpc(identifier);
+ QName rpcName = rpc.getRpcDefinition().getQName();
+ URI rpcNamespace = rpcName.getNamespace();
+ if (Objects.equal(rpcNamespace.toString(), SAL_REMOTE_NAMESPACE) &&
+ Objects.equal(rpcName.getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
- final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
- final SimpleNode<? extends Object> pathNode = value == null ? null :
- value.getFirstSimpleByName( QName.create(rpc.getQName(), "path") );
- final Object pathValue = pathNode == null ? null : pathNode.getValue();
+ return invokeSalRemoteRpcSubscribeRPC(payload, rpc.getRpcDefinition());
+ }
- if (!(pathValue instanceof InstanceIdentifier)) {
- throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
- "Instance identifier was not normalized correctly.");
- }
+ return callRpc(rpc, payload);
+ }
- final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
- String streamName = null;
- if (!Iterables.isEmpty(pathIdentifier.getPath())) {
- String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
- streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
- }
+ private StructuredData invokeSalRemoteRpcSubscribeRPC(final CompositeNode payload,
+ final RpcDefinition rpc) {
+ final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
+ final SimpleNode<? extends Object> pathNode = value == null ? null :
+ value.getFirstSimpleByName( QName.create(rpc.getQName(), "path") );
+ final Object pathValue = pathNode == null ? null : pathNode.getValue();
- if (Strings.isNullOrEmpty(streamName)) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Path is empty or contains data node which is not Container or List build-in type.");
- }
+ if (!(pathValue instanceof InstanceIdentifier)) {
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+ "Instance identifier was not normalized correctly.");
+ }
- final SimpleNode<String> streamNameNode = NodeFactory.<String>createImmutableSimpleNode(
- QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
- final List<Node<?>> output = new ArrayList<Node<?>>();
- output.add(streamNameNode);
+ final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
+ String streamName = null;
+ if (!Iterables.isEmpty(pathIdentifier.getPath())) {
+ String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
+ streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
+ }
- final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
- rpc.getOutput().getQName(), null, output, null, null);
+ if (Strings.isNullOrEmpty(streamName)) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Path is empty or contains data node which is not Container or List build-in type.");
+ }
- if (!Notificator.existListenerFor(pathIdentifier)) {
- Notificator.createListener(pathIdentifier, streamName);
- }
+ final SimpleNode<String> streamNameNode = NodeFactory.<String>createImmutableSimpleNode(
+ QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
+ final List<Node<?>> output = new ArrayList<Node<?>>();
+ output.add(streamNameNode);
- return new StructuredData(responseData, rpc.getOutput(), null);
+ final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
+ rpc.getOutput().getQName(), null, output, null, null);
+
+ if (!Notificator.existListenerFor(pathIdentifier)) {
+ Notificator.createListener(pathIdentifier, streamName);
}
- RpcDefinition rpcDefinition = this.controllerContext.getRpcDefinition(identifier);
- return this.callRpc(rpcDefinition, payload);
+ return new StructuredData(responseData, rpc.getOutput(), null);
}
@Override
public StructuredData invokeRpc(final String identifier, final String noPayload) {
- if (!Strings.isNullOrEmpty(noPayload)) {
- throw new ResponseException(Status.UNSUPPORTED_MEDIA_TYPE,
- "Content-Type contains unsupported Media Type.");
+ if (StringUtils.isNotBlank(noPayload)) {
+ throw new ResponseException(
+ Status.UNSUPPORTED_MEDIA_TYPE, "Content-Type contains unsupported Media Type.");
}
-
- final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
- return this.callRpc(rpc, null);
+ final RpcExecutor rpc = resolveIdentifierInInvokeRpc(identifier);
+ return callRpc(rpc, null);
}
- private RpcDefinition resolveIdentifierInInvokeRpc(final String identifier) {
- if (identifier.indexOf("/") < 0) {
- final String identifierDecoded = this.controllerContext.urlPathArgDecode(identifier);
- final RpcDefinition rpc = this.controllerContext.getRpcDefinition(identifierDecoded);
- if (rpc != null) {
- return rpc;
- }
+ private RpcExecutor resolveIdentifierInInvokeRpc(final String identifier) {
+ String identifierEncoded = null;
+ MountInstance mountPoint = null;
+ if (identifier.contains(ControllerContext.MOUNT)) {
+ // mounted RPC call - look up mount instance.
+ InstanceIdWithSchemaNode mountPointId = controllerContext
+ .toMountPointIdentifier(identifier);
+ mountPoint = mountPointId.getMountPoint();
+ int startOfRemoteRpcName = identifier.lastIndexOf(ControllerContext.MOUNT)
+ + ControllerContext.MOUNT.length() + 1;
+ String remoteRpcName = identifier.substring(startOfRemoteRpcName);
+ identifierEncoded = remoteRpcName;
+
+ } else if (identifier.indexOf("/") != CHAR_NOT_FOUND) {
+ final String slashErrorMsg = String
+ .format("Identifier %n%s%ncan\'t contain slash "
+ + "character (/).%nIf slash is part of identifier name then use %%2F placeholder.",
+ identifier);
+ throw new ResponseException(Status.NOT_FOUND, slashErrorMsg);
+ } else {
+ identifierEncoded = identifier;
+ }
+
+ final String identifierDecoded = controllerContext.urlPathArgDecode(identifierEncoded);
+ RpcDefinition rpc = controllerContext.getRpcDefinition(identifierDecoded);
+
+ if (rpc == null) {
throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
}
- final String slashErrorMsg = String.format(
- "Identifier %n%s%ncan\'t contain slash character (/).%nIf slash is part of identifier name then use %%2F placeholder.",
- identifier);
+ if (mountPoint == null) {
+ return new BrokerRpcExecutor(rpc, broker);
+ } else {
+ return new MountPointRpcExecutor(rpc, mountPoint);
+ }
- throw new ResponseException(Status.NOT_FOUND, slashErrorMsg);
}
- private StructuredData callRpc(final RpcDefinition rpc, final CompositeNode payload) {
- if (rpc == null) {
+ private StructuredData callRpc(final RpcExecutor rpcExecutor, final CompositeNode payload) {
+ if (rpcExecutor == null) {
throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
}
CompositeNode rpcRequest = null;
+ RpcDefinition rpc = rpcExecutor.getRpcDefinition();
+ QName rpcName = rpc.getQName();
+
if (payload == null) {
- rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, null, null, null);
- }
- else {
+ rpcRequest = NodeFactory.createMutableCompositeNode(rpcName, null, null, null, null);
+ } else {
final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
- final List<Node<?>> input = new ArrayList<Node<?>>();
- input.add(value);
-
- rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, input, null, null);
+ List<Node<?>> input = Collections.<Node<?>> singletonList(value);
+ rpcRequest = NodeFactory.createMutableCompositeNode(rpcName, null, input, null, null);
}
- final RpcResult<CompositeNode> rpcResult = broker.invokeRpc(rpc.getQName(), rpcRequest);
+ RpcResult<CompositeNode> rpcResult = rpcExecutor.invokeRpc(rpcRequest);
- if (!rpcResult.isSuccessful()) {
- throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Operation failed");
- }
+ checkRpcSuccessAndThrowException(rpcResult);
- CompositeNode result = rpcResult.getResult();
- if (result == null) {
+ if (rpcResult.getResult() == null) {
return null;
}
- return new StructuredData(result, rpc.getOutput(), null);
+ if( rpc.getOutput() == null )
+ {
+ return null; //no output, nothing to send back.
+ }
+
+ return new StructuredData(rpcResult.getResult(), rpc.getOutput(), null);
+ }
+
+ private void checkRpcSuccessAndThrowException(RpcResult<CompositeNode> rpcResult) {
+ if (rpcResult.isSuccessful() == false) {
+ //TODO: Get smart about what error code we are return (Future Bug coming)
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+ "The operation was not successful and there were no RPC errors returned");
+ }
}
@Override
status = future == null ? null : future.get();
}
}
- catch( ResponseException e) { throw e; }
+ catch( ResponseException e ){ throw e; }
catch( Exception e ) {
throw new ResponseException( e, "Error creating data" );
}
status = future == null ? null : future.get();
}
}
- catch( ResponseException e) { throw e; }
+ catch( ResponseException e ){ throw e; }
catch( Exception e ) {
throw new ResponseException( e, "Error creating data" );
}
--- /dev/null
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public abstract class AbstractRpcExecutor implements RpcExecutor {
+ private final RpcDefinition rpcDef;
+
+ public AbstractRpcExecutor( RpcDefinition rpcDef ){
+ this.rpcDef = rpcDef;
+ }
+
+ @Override
+ public RpcDefinition getRpcDefinition() {
+ return rpcDef;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public class BrokerRpcExecutor extends AbstractRpcExecutor {
+ private final BrokerFacade broker;
+
+ public BrokerRpcExecutor( RpcDefinition rpcDef, BrokerFacade broker )
+ {
+ super( rpcDef );
+ this.broker = broker;
+ }
+
+ @Override
+ public RpcResult<CompositeNode> invokeRpc(CompositeNode rpcRequest) {
+ return broker.invokeRpc( getRpcDefinition().getQName(), rpcRequest );
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import java.util.concurrent.ExecutionException;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Provides an implementation which invokes rpc methods via a mounted yang data model.
+ * @author Devin Avery
+ *
+ */
+public class MountPointRpcExecutor extends AbstractRpcExecutor {
+ private final MountInstance mountPoint;
+
+ public MountPointRpcExecutor(RpcDefinition rpcDef, MountInstance mountPoint) {
+ super( rpcDef );
+ this.mountPoint = mountPoint;
+ Preconditions.checkNotNull( mountPoint, "MountInstance can not be null." );
+ }
+
+ @Override
+ public RpcResult<CompositeNode> invokeRpc( CompositeNode rpcRequest ) throws ResponseException {
+ ListenableFuture<RpcResult<CompositeNode>> rpcFuture =
+ mountPoint.rpc( getRpcDefinition().getQName(), rpcRequest);
+ try {
+ return rpcFuture.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+ e.getCause().getMessage() );
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public interface RpcExecutor {
+ RpcResult<CompositeNode> invokeRpc( CompositeNode rpcRequest );
+
+ RpcDefinition getRpcDefinition();
+}
\ No newline at end of file
/*
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2014 Brocade Communications Systems, Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
+import java.io.FileNotFoundException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Set;
+import javax.ws.rs.core.Response.Status;
+
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.ModifyAction;
import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import com.google.common.util.concurrent.ListenableFuture;
public class InvokeRpcMethodTest {
- private static Set<Module> modules;
+ private RestconfImpl restconfImpl = null;
+ private static ControllerContext controllerContext = null;
private class AnswerImpl implements Answer<RpcResult<CompositeNode>> {
@Override
}
@BeforeClass
- public static void initialization() {
- modules = TestUtils.loadModulesFrom("/invoke-rpc");
- assertEquals(1, modules.size());
- Module module = TestUtils.resolveModule("invoke-rpc-module", modules);
+ public static void init() throws FileNotFoundException {
+ Set<Module> allModules = new HashSet<Module>( TestUtils
+ .loadModulesFrom("/full-versions/yangs") );
+ allModules.addAll( TestUtils.loadModulesFrom("/invoke-rpc") );
+ assertNotNull(allModules);
+ Module module = TestUtils.resolveModule("invoke-rpc-module", allModules);
assertNotNull(module);
+ SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
+ controllerContext = spy( ControllerContext.getInstance() );
+ controllerContext.setSchemas(schemaContext);
+
+ }
+
+ @Before
+ public void initMethod()
+ {
+ restconfImpl = RestconfImpl.getInstance();
+ restconfImpl.setControllerContext( controllerContext );
}
/**
* from string - first argument).
*/
@Test
- public void invokeRpcMethodTest() {
- ControllerContext contContext = ControllerContext.getInstance();
- contContext.onGlobalContextUpdated(TestUtils.loadSchemaContext(modules));
+ public void invokeRpcMtethodTest() {
+ ControllerContext contContext = controllerContext;
try {
contContext.findModuleNameByNamespace(new URI("invoke:rpc:module"));
} catch (URISyntaxException e) {
when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenAnswer(new AnswerImpl());
StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", preparePayload());
-
- CompositeNode rpcCompNode = structData.getData();
- CompositeNode cont = null;
- assertEquals("invoke:rpc:module", rpcCompNode.getNodeType().getNamespace().toString());
- assertEquals("rpc-test", rpcCompNode.getNodeType().getLocalName());
-
- for (Node<?> node : rpcCompNode.getChildren()) {
- if (node.getNodeType().getLocalName().equals("cont")
- && node.getNodeType().getNamespace().toString().equals("nmspc")) {
- if (node instanceof CompositeNode) {
- cont = (CompositeNode) node;
- }
- }
- }
- assertNotNull(cont);
+ assertTrue(structData == null);
}
return cont;
}
+ @Test
+ public void testInvokeRpcWithNoPayloadRpc_FailNoErrors() {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(false);
+
+ ArgumentCaptor<CompositeNode> payload = ArgumentCaptor
+ .forClass(CompositeNode.class);
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when(
+ brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)cancel-toast")),
+ payload.capture())).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ try {
+ restconfImpl.invokeRpc("toaster:cancel-toast", "");
+ fail("Expected an exception to be thrown.");
+ } catch (ResponseException e) {
+ assertEquals(e.getMessage(),
+ Status.INTERNAL_SERVER_ERROR.getStatusCode(), e
+ .getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNoPayloadRpc_FailWithRpcError() {
+ List<RpcError> rpcErrors = new LinkedList<RpcError>();
+
+ RpcError unknownError = mock(RpcError.class);
+ when( unknownError.getTag() ).thenReturn( "bogusTag" );
+ rpcErrors.add( unknownError );
+
+ RpcError knownError = mock( RpcError.class );
+ when( knownError.getTag() ).thenReturn( "in-use" );
+ rpcErrors.add( knownError );
+
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(false);
+ when(rpcResult.getErrors()).thenReturn( rpcErrors );
+
+ ArgumentCaptor<CompositeNode> payload = ArgumentCaptor
+ .forClass(CompositeNode.class);
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when(
+ brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)cancel-toast")),
+ payload.capture())).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ try {
+ restconfImpl.invokeRpc("toaster:cancel-toast", "");
+ fail("Expected an exception to be thrown.");
+ } catch (ResponseException e) {
+ //TODO: Change to a 409 in the future - waiting on additional BUG to enhance this.
+ assertEquals(e.getMessage(), 500, e.getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNoPayload_Success() {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(true);
+
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when(
+ brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)cancel-toast")),
+ any( CompositeNode.class ))).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ StructuredData output = restconfImpl.invokeRpc("toaster:cancel-toast",
+ "");
+ assertEquals(null, output);
+ //additional validation in the fact that the restconfImpl does not throw an exception.
+ }
+
+ @Test
+ public void testInvokeRpcMethodExpectingNoPayloadButProvidePayload() {
+ try {
+ restconfImpl.invokeRpc("toaster:cancel-toast", " a payload ");
+ fail("Expected an exception");
+ } catch (ResponseException e) {
+ assertEquals(e.getMessage(),
+ Status.UNSUPPORTED_MEDIA_TYPE.getStatusCode(), e
+ .getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcMethodWithBadMethodName() {
+ try {
+ restconfImpl.invokeRpc("toaster:bad-method", "");
+ fail("Expected an exception");
+ } catch (ResponseException e) {
+ assertEquals(e.getMessage(), Status.NOT_FOUND.getStatusCode(), e
+ .getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcMethodWithInput() {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(true);
+
+ CompositeNode payload = mock(CompositeNode.class);
+
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when(
+ brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)make-toast")),
+ any(CompositeNode.class))).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ StructuredData output = restconfImpl.invokeRpc("toaster:make-toast",
+ payload);
+ assertEquals(null, output);
+ //additional validation in the fact that the restconfImpl does not throw an exception.
+ }
+
+ @Test
+ public void testThrowExceptionWhenSlashInModuleName() {
+ try {
+ restconfImpl.invokeRpc("toaster/slash", "");
+ fail("Expected an exception.");
+ } catch (ResponseException e) {
+ assertEquals(e.getMessage(), Status.NOT_FOUND.getStatusCode(), e
+ .getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNoPayloadWithOutput_Success() {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(true);
+
+ CompositeNode compositeNode = mock( CompositeNode.class );
+ when( rpcResult.getResult() ).thenReturn( compositeNode );
+
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when( brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)testOutput")),
+ any( CompositeNode.class ))).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ StructuredData output = restconfImpl.invokeRpc("toaster:testOutput",
+ "");
+ assertNotNull( output );
+ assertSame( compositeNode, output.getData() );
+ assertNotNull( output.getSchema() );
+ }
+
+ @Test
+ public void testMountedRpcCallNoPayload_Success() throws Exception
+ {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(true);
+
+ ListenableFuture<RpcResult<CompositeNode>> mockListener = mock( ListenableFuture.class );
+ when( mockListener.get() ).thenReturn( rpcResult );
+
+ QName cancelToastQName = QName.create( "cancelToast" );
+
+ RpcDefinition mockRpc = mock( RpcDefinition.class );
+ when( mockRpc.getQName() ).thenReturn( cancelToastQName );
+
+ MountInstance mockMountPoint = mock( MountInstance.class );
+ when( mockMountPoint.rpc( eq( cancelToastQName ), any( CompositeNode.class ) ) )
+ .thenReturn( mockListener );
+
+ InstanceIdWithSchemaNode mockedInstanceId = mock( InstanceIdWithSchemaNode.class );
+ when( mockedInstanceId.getMountPoint() ).thenReturn( mockMountPoint );
+
+ ControllerContext mockedContext = mock( ControllerContext.class );
+ String cancelToastStr = "toaster:cancel-toast";
+ when( mockedContext.urlPathArgDecode( cancelToastStr ) ).thenReturn( cancelToastStr );
+ when( mockedContext.getRpcDefinition( cancelToastStr ) ).thenReturn( mockRpc );
+ when( mockedContext.toMountPointIdentifier( "opendaylight-inventory:nodes/node/"
+ + "REMOTE_HOST/yang-ext:mount/toaster:cancel-toast" ) ).thenReturn( mockedInstanceId );
+
+ restconfImpl.setControllerContext( mockedContext );
+ StructuredData output = restconfImpl.invokeRpc(
+ "opendaylight-inventory:nodes/node/REMOTE_HOST/yang-ext:mount/toaster:cancel-toast",
+ "");
+ assertEquals(null, output);
+
+ //additional validation in the fact that the restconfImpl does not throw an exception.
+ }
+
+
}
*/
package org.opendaylight.controller.sal.restconf.impl.test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
import java.io.FileNotFoundException;
import java.util.Set;
+
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+/**
+ * @See {@link InvokeRpcMethodTest}
+ *
+ */
public class RestconfImplTest {
- private static final RestconfImpl restconfImpl = RestconfImpl.getInstance();
+ private RestconfImpl restconfImpl = null;
+ private static ControllerContext controllerContext = null;
@BeforeClass
public static void init() throws FileNotFoundException {
- Set<Module> allModules = TestUtils.loadModulesFrom("/full-versions/yangs");
+ Set<Module> allModules = TestUtils
+ .loadModulesFrom("/full-versions/yangs");
assertNotNull(allModules);
SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
- ControllerContext controllerContext = ControllerContext.getInstance();
+ controllerContext = spy( ControllerContext.getInstance() );
controllerContext.setSchemas(schemaContext);
- restconfImpl.setControllerContext(controllerContext);
+
+ }
+
+ @Before
+ public void initMethod()
+ {
+ restconfImpl = RestconfImpl.getInstance();
+ restconfImpl.setControllerContext( controllerContext );
}
@Test
public void testExample() throws FileNotFoundException {
- CompositeNode loadedCompositeNode = TestUtils.readInputToCnSn("/parts/ietf-interfaces_interfaces.xml", XmlToCompositeNodeProvider.INSTANCE);
+ CompositeNode loadedCompositeNode = TestUtils.readInputToCnSn(
+ "/parts/ietf-interfaces_interfaces.xml",
+ XmlToCompositeNodeProvider.INSTANCE);
BrokerFacade brokerFacade = mock(BrokerFacade.class);
- when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode);
- assertEquals(loadedCompositeNode, brokerFacade.readOperationalData(null));
+ when(brokerFacade.readOperationalData(any(InstanceIdentifier.class)))
+ .thenReturn(loadedCompositeNode);
+ assertEquals(loadedCompositeNode,
+ brokerFacade.readOperationalData(null));
}
+
}
--- /dev/null
+ module toaster {
+
+ yang-version 1;
+
+ namespace
+ "http://netconfcentral.org/ns/toaster";
+
+ prefix toast;
+
+ organization "Netconf Central";
+
+ contact
+ "Andy Bierman <andy@netconfcentral.org>";
+
+ description
+ "YANG version of the TOASTER-MIB.";
+
+ revision "2009-11-20" {
+ description
+ "Toaster module in progress.";
+ }
+
+
+ identity toast-type {
+ description
+ "Base for all bread types supported by the toaster.
+ New bread types not listed here nay be added in the
+ future.";
+ }
+
+ identity white-bread {
+ base toast:toast-type;
+ description "White bread.";
+ }
+
+ identity wheat-bread {
+ base toast-type;
+ description "Wheat bread.";
+ }
+
+ identity wonder-bread {
+ base toast-type;
+ description "Wonder bread.";
+ }
+
+ identity frozen-waffle {
+ base toast-type;
+ description "Frozen waffle.";
+ }
+
+ identity frozen-bagel {
+ base toast-type;
+ description "Frozen bagel.";
+ }
+
+ identity hash-brown {
+ base toast-type;
+ description "Hash browned potatos.";
+ }
+
+ typedef DisplayString {
+ type string {
+ length "0 .. 255";
+ }
+ description
+ "YANG version of the SMIv2 DisplayString TEXTUAL-CONVENTION.";
+ reference
+ "RFC 2579, section 2.";
+
+ }
+
+ container toaster {
+ presence
+ "Indicates the toaster service is available";
+ description
+ "Top-level container for all toaster database objects.";
+ leaf toasterManufacturer {
+ type DisplayString;
+ config false;
+ mandatory true;
+ description
+ "The name of the toaster's manufacturer. For instance,
+ Microsoft Toaster.";
+ }
+
+ leaf toasterModelNumber {
+ type DisplayString;
+ config false;
+ mandatory true;
+ description
+ "The name of the toaster's model. For instance,
+ Radiant Automatic.";
+ }
+
+ leaf toasterStatus {
+ type enumeration {
+ enum "up" {
+ value 1;
+ description
+ "The toaster knob position is up.
+ No toast is being made now.";
+ }
+ enum "down" {
+ value 2;
+ description
+ "The toaster knob position is down.
+ Toast is being made now.";
+ }
+ }
+ config false;
+ mandatory true;
+ description
+ "This variable indicates the current state of
+ the toaster.";
+ }
+ } // container toaster
+
+ rpc make-toast {
+ description
+ "Make some toast.
+ The toastDone notification will be sent when
+ the toast is finished.
+ An 'in-use' error will be returned if toast
+ is already being made.
+ A 'resource-denied' error will be returned
+ if the toaster service is disabled.";
+ input {
+ leaf toasterDoneness {
+ type uint32 {
+ range "1 .. 10";
+ }
+ default '5';
+ description
+ "This variable controls how well-done is the
+ ensuing toast. It should be on a scale of 1 to 10.
+ Toast made at 10 generally is considered unfit
+ for human consumption; toast made at 1 is warmed
+ lightly.";
+ }
+
+ leaf toasterToastType {
+ type identityref {
+ base toast:toast-type;
+ }
+ default 'wheat-bread';
+ description
+ "This variable informs the toaster of the type of
+ material that is being toasted. The toaster
+ uses this information, combined with
+ toasterDoneness, to compute for how
+ long the material must be toasted to achieve
+ the required doneness.";
+ }
+ }
+ } // rpc make-toast
+
+ rpc testOutput {
+ output {
+ leaf textOut {
+ type string;
+ }
+ }
+ }
+
+ rpc cancel-toast {
+ description
+ "Stop making toast, if any is being made.
+ A 'resource-denied' error will be returned
+ if the toaster service is disabled.";
+ } // rpc cancel-toast
+
+ notification toastDone {
+ description
+ "Indicates that the toast in progress has completed.";
+ leaf toastStatus {
+ type enumeration {
+ enum "done" {
+ value 0;
+ description "The toast is done.";
+ }
+ enum "cancelled" {
+ value 1;
+ description
+ "The toast was cancelled.";
+ }
+ enum "error" {
+ value 2;
+ description
+ "The toaster service was disabled or
+ the toaster is broken.";
+ }
+ }
+ description
+ "Indicates the final toast status";
+ }
+ } // notification toastDone
+ } // module toaster
package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
+import java.lang.ref.SoftReference;
import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
import javax.annotation.concurrent.GuardedBy;
public class YangStoreServiceImpl implements YangStoreService {
private final SchemaContextProvider service;
@GuardedBy("this")
- private YangStoreSnapshotImpl cache = null;
+ private SoftReference<YangStoreSnapshotImpl> cache = new SoftReference<>(null);
public YangStoreServiceImpl(SchemaContextProvider service) {
this.service = service;
@Override
public synchronized YangStoreSnapshotImpl getYangStoreSnapshot() throws YangStoreException {
- if (cache == null) {
- cache = new YangStoreSnapshotImpl(service.getSchemaContext());
+ YangStoreSnapshotImpl yangStoreSnapshot = cache.get();
+ if (yangStoreSnapshot == null) {
+ yangStoreSnapshot = new YangStoreSnapshotImpl(service.getSchemaContext());
+ cache = new SoftReference<>(yangStoreSnapshot);
}
- return cache;
+ return yangStoreSnapshot;
}
/**
* Called when schema context changes, invalidates cache.
*/
public synchronized void refresh() {
- cache = null;
+ cache.clear();
}
}
throw new IllegalStateException(e);
}
logger.info("Configuration Persister initialization completed.");
+
+ /*
+ * We have completed initial configuration. At this point
+ * it is good idea to perform garbage collection to prune
+ * any garbage we have accumulated during startup.
+ */
+ logger.debug("Running post-initialization garbage collection...");
+ System.gc();
+ logger.debug("Post-initialization garbage collection completed.");
+
ConfigPersisterNotificationHandler jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator);
synchronized (ConfigPersisterActivator.this) {
autoCloseables.add(jmxNotificationHandler);
synchronized (ConfigPersisterActivator.this) {
autoCloseables.add(new AutoCloseable() {
@Override
- public void close() throws Exception {
+ public void close() {
pushingThread.interrupt();
}
});
* 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 org.opendaylight.controller.netconf.api.NetconfMessage;
+package org.opendaylight.controller.netconf.api;
/**
* Session capable of exi communication according to http://tools.ietf.org/html/draft-varga-netconf-exi-capability-02
<groupId>${project.groupId}</groupId>
<artifactId>netconf-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netconf-util</artifactId>
javax.xml.parsers,
javax.xml.xpath,
org.opendaylight.controller.netconf.api,
- org.opendaylight.controller.netconf.util,
org.opendaylight.controller.netconf.util.*,
+ org.opendaylight.controller.netconf.nettyutil.*,
org.opendaylight.protocol.framework,
org.openexi.*,
org.slf4j,
package org.opendaylight.controller.netconf.client;
+import io.netty.channel.Channel;
import java.util.Collection;
-
-import org.opendaylight.controller.netconf.util.AbstractNetconfSession;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXIToMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToEXIEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSession;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXIToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToEXIEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.netty.channel.Channel;
-
public final class NetconfClientSession extends AbstractNetconfSession<NetconfClientSession, NetconfClientSessionListener> {
private static final Logger logger = LoggerFactory.getLogger(NetconfClientSession.class);
package org.opendaylight.controller.netconf.client;
+import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
import java.util.Collection;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
-
import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
-import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSessionNegotiator;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
-import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import io.netty.channel.Channel;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
-
public class NetconfClientSessionNegotiator extends
AbstractNetconfSessionNegotiator<NetconfClientSessionPreferences, NetconfClientSession, NetconfClientSessionListener>
{
import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
-import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.protocol.framework.SessionListenerFactory;
import org.opendaylight.protocol.framework.SessionNegotiator;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
-import org.opendaylight.controller.netconf.util.handler.ssh.SshHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker;
-import org.opendaylight.protocol.framework.SessionListenerFactory;
-
import java.io.IOException;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.SshHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.Invoker;
+import org.opendaylight.protocol.framework.SessionListenerFactory;
final class SshClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
import org.opendaylight.protocol.framework.SessionListenerFactory;
class TcpClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.protocol.framework.ReconnectStrategy;
-import java.net.InetSocketAddress;
-
public class NetconfClientConfiguration {
private final NetconfClientProtocol clientProtocol;
*/
package org.opendaylight.controller.netconf.client.conf;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.protocol.framework.ReconnectStrategy;
-import java.net.InetSocketAddress;
-
public class NetconfClientConfigurationBuilder {
public static final int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 5000;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.protocol.framework.ReconnectStrategy;
import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
-import java.net.InetSocketAddress;
-
public final class NetconfReconnectingClientConfiguration extends NetconfClientConfiguration {
private final ReconnectStrategyFactory connectStrategyFactory;
package org.opendaylight.controller.netconf.client.conf;
import java.net.InetSocketAddress;
-
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.protocol.framework.ReconnectStrategy;
import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
<groupId>${project.groupId}</groupId>
<artifactId>netconf-mapping-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netconf-util</artifactId>
org.opendaylight.controller.netconf.api,
org.opendaylight.controller.netconf.api.jmx,
org.opendaylight.controller.netconf.mapping.api,
- org.opendaylight.controller.netconf.util,
- org.opendaylight.controller.netconf.util.mapping,
- org.opendaylight.controller.netconf.util.osgi,
- org.opendaylight.controller.netconf.util.xml,
- org.opendaylight.controller.netconf.util.exception,
- org.opendaylight.controller.netconf.util.handler,
+ org.opendaylight.controller.netconf.util.*,
org.opendaylight.protocol.framework,
org.osgi.framework,
org.osgi.util.tracker,
org.slf4j,
org.w3c.dom,
org.xml.sax,
- org.opendaylight.controller.netconf.util.messages,
io.netty.util.internal,
org.opendaylight.controller.netconf.api.monitoring,
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924,
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas,
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,
org.opendaylight.yangtools.yang.binding,
- org.openexi.*,</Import-Package>
+ org.openexi.*,
+ org.opendaylight.controller.netconf.nettyutil.*</Import-Package>
</instructions>
</configuration>
</plugin>
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.impl.util.DeserializerExceptionHandler;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
import org.opendaylight.protocol.framework.AbstractDispatcher;
-import java.net.InetSocketAddress;
-
public class NetconfServerDispatcher extends AbstractDispatcher<NetconfServerSession, NetconfServerSessionListener> {
private final ServerChannelInitializer initializer;
package org.opendaylight.controller.netconf.impl;
+import com.google.common.base.Preconditions;
+import io.netty.channel.Channel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
-import org.opendaylight.controller.netconf.util.AbstractNetconfSession;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXIToMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToEXIEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSession;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXIToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToEXIEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import io.netty.channel.Channel;
-
public final class NetconfServerSession extends AbstractNetconfSession<NetconfServerSession, NetconfServerSessionListener> implements NetconfManagementSession {
private static final Logger logger = LoggerFactory.getLogger(NetconfServerSession.class);
package org.opendaylight.controller.netconf.impl;
+import com.google.common.base.Optional;
+import io.netty.channel.Channel;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
import java.net.InetSocketAddress;
-
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
-import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSessionNegotiator;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-
-import io.netty.channel.Channel;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
-
public class NetconfServerSessionNegotiator extends
AbstractNetconfSessionNegotiator<NetconfServerSessionPreferences, NetconfServerSession, NetconfServerSessionListener> {
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
+import com.google.common.base.Preconditions;
+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 io.netty.util.concurrent.GlobalEventExecutor;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
-
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
-import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import com.google.common.base.Preconditions;
-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 io.netty.util.concurrent.GlobalEventExecutor;
-
@RunWith(Parameterized.class)
public class ConcurrentClientsTest {
private static final Logger logger = LoggerFactory.getLogger(ConcurrentClientsTest.class);
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;
-
import java.util.Queue;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.handler.ChunkedFramingMechanismEncoder;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.ChunkedFramingMechanismEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfChunkAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEOMAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
</properties>
<dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.logback_settings</artifactId>
<artifactId>netconf-monitoring</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netconf-ssh</artifactId>
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import ch.ethz.ssh2.Connection;
+import io.netty.channel.ChannelFuture;
+import io.netty.util.concurrent.GlobalEventExecutor;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Collection;
import java.util.List;
-
import junit.framework.Assert;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.controller.usermanager.IUserManager;
import org.opendaylight.protocol.framework.NeverReconnectStrategy;
-import ch.ethz.ssh2.Connection;
-import io.netty.channel.ChannelFuture;
-import io.netty.util.concurrent.GlobalEventExecutor;
-
public class NetconfITSecureTest extends AbstractNetconfConfigTest {
private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024);
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2014 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
+ -->
+<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>netconf-subsystem</artifactId>
+ <version>0.2.5-SNAPSHOT</version>
+ </parent>
+ <artifactId>netconf-netty-util</artifactId>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <!-- compile dependencies -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-mapping-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-handler</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>protocol-framework</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>ganymed</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openexi</groupId>
+ <artifactId>nagasena</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openexi</groupId>
+ <artifactId>nagasena-rta</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>ch.ethz.ssh2, com.google.common.base, com.google.common.collect, io.netty.buffer,
+ io.netty.channel, io.netty.channel.socket, io.netty.handler.codec, io.netty.handler.ssl, io.netty.util,
+ io.netty.util.concurrent, javax.xml.transform, javax.xml.transform.dom, javax.xml.transform.sax,
+ javax.xml.transform.stream, org.opendaylight.controller.netconf.api,
+ org.opendaylight.controller.netconf.util.messages, org.opendaylight.controller.netconf.util.xml,
+ org.opendaylight.protocol.framework, org.openexi.proc, org.openexi.proc.common, org.openexi.proc.grammars,
+ org.openexi.sax, org.openexi.schema, org.slf4j, org.w3c.dom, org.xml.sax</Import-Package>
+ <Export-Package>org.opendaylight.controller.netconf.nettyutil,
+ org.opendaylight.controller.netconf.nettyutil.handler,
+ org.opendaylight.controller.netconf.nettyutil.handler.exi,
+ org.opendaylight.controller.netconf.nettyutil.handler.ssh,
+ org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication,
+ org.opendaylight.controller.netconf.nettyutil.handler.ssh.client</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ <phase>package</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util;
+package org.opendaylight.controller.netconf.nettyutil;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
-
import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfHelloMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEOMAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfHelloMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToHelloMessageDecoder;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
public abstract class AbstractChannelInitializer<S extends NetconfSession> {
* 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;
+package org.opendaylight.controller.netconf.nettyutil;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandler;
import java.io.IOException;
-
+import org.opendaylight.controller.netconf.api.NetconfExiSession;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.api.NetconfSessionListener;
import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
-import org.opendaylight.controller.netconf.util.xml.EXIParameters;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.EXIParameters;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.protocol.framework.AbstractProtocolSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelHandler;
-
public abstract class AbstractNetconfSession<S extends NetconfSession, L extends NetconfSessionListener<S>> extends AbstractProtocolSession<NetconfMessage> implements NetconfSession, NetconfExiSession {
private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfSession.class);
private final L sessionListener;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util;
+package org.opendaylight.controller.netconf.nettyutil;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.Promise;
+import java.util.concurrent.TimeUnit;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSessionListener;
import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfChunkAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToHelloMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
-import java.util.concurrent.TimeUnit;
-
public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionPreferences, S extends AbstractNetconfSession<S, L>, L extends NetconfSessionListener<S>>
extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
import org.slf4j.Logger;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import java.util.List;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import com.google.common.base.Preconditions;
import org.openexi.proc.HeaderOptionsOutputType;
* 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.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import java.io.InputStream;
import java.util.List;
* 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.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
* 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.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
* 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.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
* 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.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
* 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.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import java.util.List;
* 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.xml;
+package org.opendaylight.controller.netconf.nettyutil.handler.exi;
import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.openexi.proc.common.AlignmentType;
import org.openexi.proc.common.EXIOptions;
import org.openexi.proc.common.EXIOptionsException;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.messages;
+package org.opendaylight.controller.netconf.nettyutil.handler.exi;
import java.util.List;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import java.io.IOException;
import java.net.SocketAddress;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.SshClient;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter;
-import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocket;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClient;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.Invoker;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClientAdapter;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
/**
* Netty SSH handler class. Acts as interface between Netty and SSH library. All standard Netty message handling
- * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter};
+ * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClientAdapter};
*/
public class SshHandler extends ChannelOutboundHandlerAdapter {
private static final String SOCKET = "socket";
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.authentication;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication;
import ch.ethz.ssh2.Connection;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.authentication;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication;
import ch.ethz.ssh2.Connection;
/**
* Class Providing username/password authentication option to
- * {@link org.opendaylight.controller.netconf.util.handler.ssh.SshHandler}
+ * {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.SshHandler}
*/
public class LoginPassword extends AuthenticationHandler {
private final String username;
* 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.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
import java.io.IOException;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.channel.Channel;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocket;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
import java.io.IOException;
import java.util.HashMap;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocketException;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocketException;
/**
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
/**
* Exception class which provides notification about exceptional situations at the virtual socket layer.
* 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.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
* 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.messages;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import static org.junit.Assert.assertEquals;
-import io.netty.buffer.Unpooled;
+import com.google.common.io.Files;
+import io.netty.buffer.Unpooled;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
-
import org.junit.Test;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
-
-import com.google.common.io.Files;
public class NetconfMessageFactoryTest {
@Test
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-api</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>protocol-framework</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.thirdparty</groupId>
- <artifactId>ganymed</artifactId>
- </dependency>
- <dependency>
- <groupId>org.openexi</groupId>
- <artifactId>nagasena</artifactId>
- </dependency>
- <dependency>
- <groupId>org.openexi</groupId>
- <artifactId>nagasena-rta</artifactId>
- </dependency>
-
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Export-Package>org.opendaylight.controller.netconf.util,
- org.opendaylight.controller.netconf.util.xml,
- org.opendaylight.controller.netconf.util.osgi,
- org.opendaylight.controller.netconf.util.mapping,
- org.opendaylight.controller.netconf.util.messages,
- org.opendaylight.controller.netconf.util.handler,
- org.opendaylight.controller.netconf.util.handler.*,
- org.opendaylight.controller.netconf.util.exception,</Export-Package>
- <Import-Package>com.google.common.base,
- com.google.common.collect,
- ch.ethz.ssh2,
- io.netty.buffer,
- io.netty.channel,
- io.netty.channel.socket,
- io.netty.handler.codec,
- io.netty.handler.ssl,
- io.netty.util,
- io.netty.util.concurrent,
- javax.annotation,
- javax.net.ssl,
- javax.xml.namespace,
- javax.xml.parsers,
- javax.xml.transform,
- javax.xml.transform.dom,
- 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.osgi.framework,
- org.slf4j,
- org.w3c.dom,
- org.xml.sax,
- org.xml.sax.helpers,
- org.opendaylight.controller.config.api,
- org.openexi.*,</Import-Package>
+ <Import-Package>com.google.common.base, com.google.common.collect, io.netty.channel,
+ io.netty.util.concurrent, javax.annotation, javax.xml.namespace, javax.xml.parsers, javax.xml.transform,
+ javax.xml.transform.dom, javax.xml.transform.stream, javax.xml.validation, javax.xml.xpath,
+ org.opendaylight.controller.netconf.api, org.opendaylight.controller.netconf.mapping.api,
+ org.osgi.framework, org.slf4j, org.w3c.dom, org.xml.sax</Import-Package>
+ <Export-Package>org.opendaylight.controller.netconf.util.*</Export-Package>
</instructions>
</configuration>
</plugin>
import com.google.common.base.Preconditions;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
public final class NetconfUtil {
private NetconfUtil() {}
- public static NetconfMessage createMessage(final File f) {
- Preconditions.checkNotNull(f, "File parameter was null");
- try {
- return createMessage(new FileInputStream(f));
- } catch (final FileNotFoundException e) {
- logger.warn("File {} not found.", f, e);
- }
- return null;
- }
-
- public static NetconfMessage createMessage(final InputStream is) {
- Preconditions.checkNotNull(is, "InputStream parameter was null");
- Document doc = null;
- try {
- doc = XmlUtil.readXmlToDocument(is);
- } catch (final IOException e) {
- logger.warn("Error ocurred while parsing stream.", e);
- } catch (final SAXException e) {
- logger.warn("Error ocurred while final parsing stream.", e);
- }
- return (doc == null) ? null : new NetconfMessage(doc);
- }
-
public static Document checkIsMessageOk(Document response) throws NetconfDocumentedException {
XmlElement element = XmlElement.fromDomDocument(response);
Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
<module>netconf-impl</module>
<module>config-netconf-connector</module>
<module>netconf-util</module>
+ <module>netconf-netty-util</module>
<module>config-persister-impl</module>
<module>netconf-mapping-api</module>
<module>netconf-client</module>
<module>opendaylight/commons/parent</module>
<module>opendaylight/commons/logback_settings</module>
- <!-- Karaf Distribution
- <module>feature</module> -->
+ <!-- Karaf Distribution -->
+ <module>features/base</module>
<module>opendaylight/dummy-console</module>
<module>opendaylight/distribution/opendaylight-karaf</module>
</modules>