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>
<properties>
<aopalliance.version>1.0.0</aopalliance.version>
<appauth.version>0.4.2-SNAPSHOT</appauth.version>
+ <aries.util.version>1.1.0</aries.util.version>
<!-- Controller Modules Versions -->
<arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
<asm.version>4.1</asm.version>
<hosttracker.northbound.version>0.4.2-SNAPSHOT</hosttracker.northbound.version>
<hosttracker_new.api.version>0.4.2-SNAPSHOT</hosttracker_new.api.version>
<ietf-inet-types.version>2010.09.24.4-SNAPSHOT</ietf-inet-types.version>
+ <ietf-restconf.version>2013.10.19.1-SNAPSHOT</ietf-restconf.version>
<ietf-topology.version>2013.10.21.2-SNAPSHOT</ietf-topology.version>
<ietf-yang-types.version>2010.09.24.4-SNAPSHOT</ietf-yang-types.version>
<jackson.version>2.3.2</jackson.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>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<artifactId>netconf-monitoring</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>org.opendaylight.controller</groupId>
<artifactId>netconf-ssh</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>
<artifactId>ietf-inet-types</artifactId>
<version>${ietf-inet-types.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-restconf</artifactId>
+ <version>${ietf-restconf.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-topology</artifactId>
<artifactId>ietf-yang-types</artifactId>
<version>${ietf-yang-types.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-yang-types-20130715</artifactId>
+ <version>2013.07.15.1-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>opendaylight-l2-types</artifactId>
}
// register services to OSGi
- Map<String, ServiceInterfaceAnnotation> annotationMapping = configTransactionController.getWritableRegistry().findServiceInterfaces(moduleIdentifier);
+ Map<ServiceInterfaceAnnotation, String /* service ref name */> annotationMapping = configTransactionController.getWritableRegistry().findServiceInterfaces(moduleIdentifier);
BundleContext bc = configTransactionController.getModuleFactoryBundleContext(
entry.getModuleFactory().getImplementationName());
if (osgiRegistration == null) {
* @throws java.lang.IllegalArgumentException if any of service qNames is not found
* @throws java.lang.NullPointerException if parameter is null
*/
- Map<String /* service ref */, ServiceInterfaceAnnotation> findServiceInterfaces(ModuleIdentifier moduleIdentifier);
+ Map<ServiceInterfaceAnnotation, String /* service ref name */> findServiceInterfaces(ModuleIdentifier moduleIdentifier);
}
private final Map<String /* service qName */, ServiceInterfaceAnnotation> serviceQNamesToAnnotations;
// all Service Interface qNames for sanity checking
private final Set<String /* qName */> allQNames;
- Map<ModuleIdentifier, Map<String /* service ref name */, ServiceInterfaceAnnotation >> modulesToServiceRef = new HashMap<>();
+ Map<ModuleIdentifier, Map<ServiceInterfaceAnnotation, String /* service ref name */>> modulesToServiceRef = new HashMap<>();
// actual reference database
}
@Override
- public Map<String /* service ref */, ServiceInterfaceAnnotation> findServiceInterfaces(ModuleIdentifier moduleIdentifier) {
- Map<String, ServiceInterfaceAnnotation> result = modulesToServiceRef.get(moduleIdentifier);
+ public Map<ServiceInterfaceAnnotation, String /* service ref name */> findServiceInterfaces(ModuleIdentifier moduleIdentifier) {
+ Map<ServiceInterfaceAnnotation, String /* service ref name */> result = modulesToServiceRef.get(moduleIdentifier);
if (result == null) {
return Collections.emptyMap();
}
}
// save to refNames
refNames.put(serviceReference, moduleIdentifier);
- Map<String, ServiceInterfaceAnnotation> refNamesToAnnotations = modulesToServiceRef.get(moduleIdentifier);
+ Map<ServiceInterfaceAnnotation, String /* service ref name */> refNamesToAnnotations = modulesToServiceRef.get(moduleIdentifier);
if (refNamesToAnnotations == null){
refNamesToAnnotations = new HashMap<>();
modulesToServiceRef.put(moduleIdentifier, refNamesToAnnotations);
ServiceInterfaceAnnotation annotation = serviceQNamesToAnnotations.get(serviceReference.getServiceInterfaceQName());
checkNotNull(annotation, "Possible error in code, cannot find annotation for " + serviceReference);
- refNamesToAnnotations.put(serviceReference.getRefName(), annotation);
+ refNamesToAnnotations.put(annotation, serviceReference.getRefName());
return result;
}
*/
public OsgiRegistration registerToOsgi(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
BundleContext bundleContext,
- Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+ Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations) {
return new OsgiRegistration(instance, moduleIdentifier, bundleContext, serviceNamesToAnnotations);
}
@GuardedBy("this")
private final Set<ServiceRegistration<?>> serviceRegistrations;
@GuardedBy("this")
- private final Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations;
+ private final Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations;
public OsgiRegistration(AutoCloseable instance, ModuleIdentifier moduleIdentifier,
BundleContext bundleContext,
- Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+ Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations) {
this.instance = instance;
this.moduleIdentifier = moduleIdentifier;
this.serviceNamesToAnnotations = serviceNamesToAnnotations;
}
private static Set<ServiceRegistration<?>> registerToSR(AutoCloseable instance, BundleContext bundleContext,
- Map<String, ServiceInterfaceAnnotation> serviceNamesToAnnotations) {
+ Map<ServiceInterfaceAnnotation, String /* service ref name */> serviceNamesToAnnotations) {
Set<ServiceRegistration<?>> serviceRegistrations = new HashSet<>();
- for (Entry<String, ServiceInterfaceAnnotation> entry : serviceNamesToAnnotations.entrySet()) {
- Class<?> requiredInterface = entry.getValue().osgiRegistrationType();
+ for (Entry<ServiceInterfaceAnnotation, String /* service ref name */> entry : serviceNamesToAnnotations.entrySet()) {
+ Class<?> requiredInterface = entry.getKey().osgiRegistrationType();
checkState(requiredInterface.isInstance(instance), instance.getClass().getName() +
" instance should implement " + requiredInterface.getName());
- Dictionary<String, String> propertiesForOsgi = createProps(entry.getKey());
+ Dictionary<String, String> propertiesForOsgi = createProps(entry.getValue());
ServiceRegistration<?> serviceRegistration = bundleContext
.registerService(requiredInterface.getName(), instance, propertiesForOsgi);
serviceRegistrations.add(serviceRegistration);
serviceRegistrations.clear();
}
- public synchronized void updateRegistrations(Map<String, ServiceInterfaceAnnotation> newAnnotationMapping,
+ public synchronized void updateRegistrations(Map<ServiceInterfaceAnnotation, String /* service ref name */> newAnnotationMapping,
BundleContext bundleContext, AutoCloseable newInstance) {
boolean notEquals = this.instance != newInstance;
notEquals |= newAnnotationMapping.equals(serviceNamesToAnnotations) == false;
package org.opendaylight.controller.config.manager.impl.osgi.mapping;
import javassist.ClassPool;
+
import org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil;
import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
private final RuntimeGeneratedMappingServiceImpl service;
private final AutoCloseable registration;
- public CodecRegistryProvider(ClassLoadingStrategy classLoadingStrategy, BundleContext context) {
- service = new RuntimeGeneratedMappingServiceImpl(classLoadingStrategy);
- service.setPool(CLASS_POOL);
- service.init();
+ public CodecRegistryProvider(final ClassLoadingStrategy classLoadingStrategy, final BundleContext context) {
+ service = new RuntimeGeneratedMappingServiceImpl(CLASS_POOL, classLoadingStrategy);
registration = OsgiRegistrationUtil.registerService(context, service,
SchemaServiceListener.class, BindingIndependentMappingService.class);
}
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
-
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
import org.opendaylight.yangtools.yang.common.QName;
private final Map<String, QName> providedServices;
private Collection<RuntimeBeanEntry> runtimeBeans;
+ private String nullableDummyContainerName;
ModuleMXBeanEntry(ModuleMXBeanEntryInitial initials, Map<String, AttributeIfc> yangToAttributes,
Map<String, QName> providedServices2, Collection<RuntimeBeanEntry> runtimeBeans) {
+ '\'' + '}';
}
+ public String getNullableDummyContainerName() {
+ return nullableDummyContainerName;
+ }
+
+ public void setNullableDummyContainerName(String nullableDummyContainerName) {
+ this.nullableDummyContainerName = nullableDummyContainerName;
+ }
+
+
static final class ModuleMXBeanEntryInitial {
private String localName;
*/
package org.opendaylight.controller.config.yangjmxgenerator;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.Collections2;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.annotation.Nullable;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
import org.opendaylight.yangtools.yang.model.api.ModuleImport;
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UsesNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.Nullable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.lang.String.format;
-import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
-
final class ModuleMXBeanEntryBuilder {
private Module currentModule;
return true;
}
- private void processChoiceCaseNode(Map<String, ModuleMXBeanEntry> result,
+ private <HAS_CHILDREN_AND_QNAME extends DataNodeContainer & SchemaNode> void processChoiceCaseNode(Map<String, ModuleMXBeanEntry> result,
Map<String, QName> uniqueGeneratedClassesNames, String configModulePrefix,
Map<String, IdentitySchemaNode> moduleIdentities,
Map<String, IdentitySchemaNode> unaugmentedModuleIdentities, AugmentationSchema augmentation,
// runtime-data
Collection<RuntimeBeanEntry> runtimeBeans = null;
+ HAS_CHILDREN_AND_QNAME dataNodeContainer = getDataNodeContainer(choiceCaseNode);
+
if (expectedConfigurationAugmentationSchemaPath.equals(augmentation.getTargetPath())) {
logger.debug("Parsing configuration of {}", moduleLocalNameFromXPath);
- yangToAttributes = fillConfiguration(choiceCaseNode, currentModule, typeProviderWrapper, qNamesToSIEs,
+ yangToAttributes = fillConfiguration(dataNodeContainer, currentModule, typeProviderWrapper, qNamesToSIEs,
schemaContext, packageName);
checkUniqueAttributesWithGeneratedClass(uniqueGeneratedClassesNames, when.getQName(), yangToAttributes);
} else if (expectedStateAugmentationSchemaPath.equals(augmentation.getTargetPath())) {
logger.debug("Parsing state of {}", moduleLocalNameFromXPath);
try {
- runtimeBeans = fillRuntimeBeans(choiceCaseNode, currentModule, typeProviderWrapper, packageName,
+ runtimeBeans = fillRuntimeBeans(dataNodeContainer, currentModule, typeProviderWrapper, packageName,
moduleLocalNameFromXPath, javaNamePrefix);
} catch (NameConflictException e) {
throw new NameConflictException(e.getConflictingName(), when.getQName(), when.getQName());
} else {
throw new IllegalArgumentException("Cannot parse augmentation " + augmentation);
}
+ boolean hasDummyContainer = choiceCaseNode.equals(dataNodeContainer) == false;
+
+ String nullableDummyContainerName = hasDummyContainer ? dataNodeContainer.getQName().getLocalName() : null;
if (result.containsKey(moduleLocalNameFromXPath)) {
- // either fill runtimeBeans or yangToAttributes
+ // either fill runtimeBeans or yangToAttributes, merge
ModuleMXBeanEntry moduleMXBeanEntry = result.get(moduleLocalNameFromXPath);
if (yangToAttributes != null && moduleMXBeanEntry.getAttributes() == null) {
moduleMXBeanEntry.setYangToAttributes(yangToAttributes);
} else if (runtimeBeans != null && moduleMXBeanEntry.getRuntimeBeans() == null) {
moduleMXBeanEntry.setRuntimeBeans(runtimeBeans);
}
+ checkState(Objects.equals(nullableDummyContainerName, moduleMXBeanEntry.getNullableDummyContainerName()),
+ "Mismatch in module " + moduleMXBeanEntry.toString() + " - dummy container must be present/missing in" +
+ " both state and configuration");
} else {
ModuleMXBeanEntry.ModuleMXBeanEntryInitial initial = new ModuleMXBeanEntry.ModuleMXBeanEntryInitialBuilder()
.setIdSchemaNode(moduleIdentity).setPackageName(packageName).setJavaNamePrefix(javaNamePrefix)
moduleMXBeanEntry.setYangModuleName(currentModule.getName());
moduleMXBeanEntry.setYangModuleLocalname(moduleLocalNameFromXPath);
+ moduleMXBeanEntry.setNullableDummyContainerName(nullableDummyContainerName);
result.put(moduleLocalNameFromXPath, moduleMXBeanEntry);
}
}
}
private void checkUniqueTOAttr(Map<String, QName> uniqueGeneratedClassNames, QName parentQName, TOAttribute attr) {
- final String upperCaseCammelCase = attr.getUpperCaseCammelCase();
- if (uniqueGeneratedClassNames.containsKey(upperCaseCammelCase)) {
- QName firstDefinedQName = uniqueGeneratedClassNames.get(upperCaseCammelCase);
- throw new NameConflictException(upperCaseCammelCase, firstDefinedQName, parentQName);
+ final String upperCaseCamelCase = attr.getUpperCaseCammelCase();
+ if (uniqueGeneratedClassNames.containsKey(upperCaseCamelCase)) {
+ QName firstDefinedQName = uniqueGeneratedClassNames.get(upperCaseCamelCase);
+ throw new NameConflictException(upperCaseCamelCase, firstDefinedQName, parentQName);
} else {
- uniqueGeneratedClassNames.put(upperCaseCammelCase, parentQName);
+ uniqueGeneratedClassNames.put(upperCaseCamelCase, parentQName);
}
}
- private Collection<RuntimeBeanEntry> fillRuntimeBeans(ChoiceCaseNode choiceCaseNode, Module currentModule,
+ private Collection<RuntimeBeanEntry> fillRuntimeBeans(DataNodeContainer dataNodeContainer, Module currentModule,
TypeProviderWrapper typeProviderWrapper, String packageName, String moduleLocalNameFromXPath,
String javaNamePrefix) {
- return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName, choiceCaseNode, moduleLocalNameFromXPath,
+ return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName, dataNodeContainer, moduleLocalNameFromXPath,
typeProviderWrapper, javaNamePrefix, currentModule).values();
}
- private Map<String, AttributeIfc> fillConfiguration(ChoiceCaseNode choiceCaseNode, Module currentModule,
+ /**
+ * Since each case statement within a module must provide unique child nodes, it is allowed to wrap
+ * the actual configuration with a container node with name equal to case name.
+ *
+ * @param choiceCaseNode state or configuration case statement
+ * @return either choiceCaseNode or its only child container
+ */
+ private <HAS_CHILDREN_AND_QNAME extends DataNodeContainer & SchemaNode> HAS_CHILDREN_AND_QNAME getDataNodeContainer(ChoiceCaseNode choiceCaseNode) {
+ Set<DataSchemaNode> childNodes = choiceCaseNode.getChildNodes();
+ if (childNodes.size() == 1) {
+ DataSchemaNode onlyChild = childNodes.iterator().next();
+ if (onlyChild instanceof ContainerSchemaNode) {
+ ContainerSchemaNode onlyContainer = (ContainerSchemaNode) onlyChild;
+ if (Objects.equals(onlyContainer.getQName().getLocalName(), choiceCaseNode.getQName().getLocalName())) {
+ // the actual configuration is inside dummy container
+ return (HAS_CHILDREN_AND_QNAME) onlyContainer;
+ }
+ }
+ }
+ return (HAS_CHILDREN_AND_QNAME) choiceCaseNode;
+ }
+
+ private Map<String, AttributeIfc> fillConfiguration(DataNodeContainer dataNodeContainer, Module currentModule,
TypeProviderWrapper typeProviderWrapper, Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
SchemaContext schemaContext, String packageName) {
Map<String, AttributeIfc> yangToAttributes = new HashMap<>();
- for (DataSchemaNode attrNode : choiceCaseNode.getChildNodes()) {
+ Set<DataSchemaNode> childNodes = dataNodeContainer.getChildNodes();
+ for (DataSchemaNode attrNode : childNodes) {
AttributeIfc attributeValue = getAttributeValue(attrNode, currentModule, qNamesToSIEs, typeProviderWrapper,
schemaContext, packageName);
yangToAttributes.put(attributeValue.getAttributeYangName(), attributeValue);
String prefix = m.group(1);
ModuleImport moduleImport = findModuleImport(currentModule, prefix);
foundModule = schemaContext.findModuleByName(moduleImport.getModuleName(), moduleImport.getRevision());
- checkState(foundModule != null, format("Module not found in SchemaContext by %s", moduleImport));
+ checkNotNull(foundModule, format("Module not found in SchemaContext by %s", moduleImport));
localSIName = m.group(2);
} else {
foundModule = currentModule; // no prefix => SIE is in currentModule
*/
package org.opendaylight.controller.config.yangjmxgenerator;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UsesNode;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-
/**
* Holds information about runtime bean to be generated. There are two kinds of
* RuntimeBeanEntry instances: if isRoot flag is set to true, this bean
@VisibleForTesting
RuntimeBeanEntry(String packageName,
- DataSchemaNode nodeForReporting, String yangName,
+ DataNodeContainer nodeForReporting, String yangName,
String javaNamePrefix, boolean isRoot,
Optional<String> keyYangName, List<AttributeIfc> attributes,
List<RuntimeBeanEntry> children, Set<Rpc> rpcs) {
* not contain special configuration for it.
*/
public static Map<String, RuntimeBeanEntry> extractClassNameToRuntimeBeanMap(
- String packageName, ChoiceCaseNode container,
+ String packageName, DataNodeContainer container,
String moduleYangName, TypeProviderWrapper typeProviderWrapper,
String javaNamePrefix, Module currentModule) {
}
private static RuntimeBeanEntry createRoot(String packageName,
- DataSchemaNode nodeForReporting, String attributeYangName,
+ DataNodeContainer nodeForReporting, String attributeYangName,
List<AttributeIfc> attributes, String javaNamePrefix,
List<RuntimeBeanEntry> children, Set<Rpc> rpcs) {
return new RuntimeBeanEntry(packageName, nodeForReporting,
*/
package org.opendaylight.controller.config.yangjmxgenerator;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.format;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.junit.Assert;
import org.junit.Before;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.YangModelSearchUtils;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.format;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
public abstract class AbstractYangTest {
protected SchemaContext context;
protected Map<String, Module> namesToModules; // are module names globally
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import com.google.common.base.Optional;
import java.net.URI;
import java.util.Collections;
import java.util.List;
-
import org.junit.Test;
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import com.google.common.base.Optional;
-
public class RuntimeRegistratorTest {
// TODO add more tests
protected RuntimeBeanEntry prepareRootRB(List<RuntimeBeanEntry> children) {
- DataSchemaNode dataSchemaNodeForReporting = mock(DataSchemaNode.class);
- doReturn("DataSchemaNode").when(dataSchemaNodeForReporting).toString();
- return new RuntimeBeanEntry("pa.cka.ge", dataSchemaNodeForReporting,
+ DataNodeContainer nodeContainer = mock(DataNodeContainer.class);
+ doReturn("DataSchemaNode").when(nodeContainer).toString();
+ return new RuntimeBeanEntry("pa.cka.ge", nodeContainer,
"module-name", "ModuleName", true, Optional.<String> absent(),
Collections.<AttributeIfc> emptyList(), children,
Collections.<Rpc> emptySet());
protected RuntimeBeanEntry prepareChildRB(List<RuntimeBeanEntry> children,
String prefix) {
- DataSchemaNode dataSchemaNodeForReporting = mock(DataSchemaNode.class);
- doReturn("DataSchemaNode").when(dataSchemaNodeForReporting).toString();
- return new RuntimeBeanEntry("pa.cka.ge", dataSchemaNodeForReporting,
+ DataNodeContainer nodeContainer = mock(DataNodeContainer.class);
+ doReturn("DataSchemaNode").when(nodeContainer).toString();
+ return new RuntimeBeanEntry("pa.cka.ge", nodeContainer,
prefix + "child-name", capitalize(prefix) + "ChildName", false,
Optional.<String> absent(),
Collections.<AttributeIfc> emptyList(), children,
augment "/config:modules/config:module/config:state" {
case bgp-listener-impl {
when "/config:modules/config:module/config:type = 'bgp-listener-impl'";
- list peers {
- config:inner-state-bean;
- leaf port {
- type inet:port-number;
- default 179;
+ container bgp-listener-impl {
+ list peers {
+ config:inner-state-bean;
+ leaf port {
+ type inet:port-number;
+ default 179;
+ }
+ leaf core-size {
+ type uint32;
+ }
}
- leaf core-size {
- type uint32;
- }
- }
- leaf as-number {
- mandatory true;
- type inet:as-number;
+ leaf as-number {
+ mandatory true;
+ type inet:as-number;
+ }
}
}
}
augment "/config:modules/config:module/config:configuration" {
case threadpool-dynamic {
when "/config:modules/config:module/config:type = 'threadpool-dynamic'";
- leaf core-size {
- type uint32;
- }
+ container threadpool-dynamic {
+ leaf core-size {
+ type uint32;
+ }
- leaf keep-alive {
- type uint32;
- units seconds;
- default 10;
- }
+ leaf keep-alive {
+ type uint32;
+ units seconds;
+ default 10;
+ }
- leaf maximum-size {
- type uint32;
- description "maximum-size description";
- }
+ leaf maximum-size {
+ type uint32;
+ description "maximum-size description";
+ }
- leaf binary {
- type binary;
- }
+ leaf binary {
+ type binary;
+ }
- container threadfactory {
- description "threadfactory description";
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity th2:threadfactory;
+ container threadfactory {
+ description "threadfactory description";
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity th2:threadfactory;
+ }
}
}
- }
- leaf-list users {
- type string;
- }
+ leaf-list users {
+ type string;
+ }
- leaf-list users-numbers {
- type uint32;
- description "numbers of users description";
+ leaf-list users-numbers {
+ type uint32;
+ description "numbers of users description";
+ }
}
}
}
augment "/config:modules/config:module/config:state" {
case threadpool-dynamic {
when "/config:modules/config:module/config:type = 'threadpool-dynamic'";
- // root runtime bean
- leaf created-sessions {
- type uint32;
+ container threadpool-dynamic {
+ // root runtime bean
+ leaf created-sessions {
+ type uint32;
+ }
}
}
}
-
-
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) {
augment "/config:modules/config:module/config:configuration" {
case impl-netconf {
when "/config:modules/config:module/config:type = 'impl-netconf'";
- leaf binaryLeaf {
- type binary;
- default ZGVmYXVsdEJpbg==;
- }
-
- leaf type {
- type string;
- default "default-string";
- }
+ container impl-netconf {
+ leaf binaryLeaf {
+ type binary;
+ default ZGVmYXVsdEJpbg==;
+ }
- leaf extended {
- type tt:extend-once;
- default 1;
- }
+ leaf type {
+ type string;
+ default "default-string";
+ }
- leaf extended-twice {
- type tt:extend-twice;
- default 2;
- }
+ leaf extended {
+ type tt:extend-once;
+ default 1;
+ }
- leaf extended-enum {
- type tt:extend-enum;
- default ONE;
- }
+ leaf extended-twice {
+ type tt:extend-twice;
+ default 2;
+ }
- leaf ip {
- type inet:ip-address;
- default 0:0:0:0:0:0:0:1;
- }
+ leaf extended-enum {
+ type tt:extend-enum;
+ default ONE;
+ }
- leaf union-test-attr {
- type tt:unionTest;
- default 456;
- }
+ leaf ip {
+ type inet:ip-address;
+ default 0:0:0:0:0:0:0:1;
+ }
- leaf sleep-factor {
- type decimal64 {
- fraction-digits 2;
+ leaf union-test-attr {
+ type tt:unionTest;
+ default 456;
}
- default 2.00;
- }
- container dto-c {
- leaf simple-arg {
- type uint32;
+ leaf sleep-factor {
+ type decimal64 {
+ fraction-digits 2;
+ }
+ default 2.00;
}
- container dto-a-inner {
+ container dto-c {
leaf simple-arg {
type uint32;
}
- container dto-a-inner-inner {
+ container dto-a-inner {
leaf simple-arg {
type uint32;
}
+
+ container dto-a-inner-inner {
+ leaf simple-arg {
+ type uint32;
+ }
+ }
}
}
- }
-
- leaf simpleInt {
- type uint32;
- }
-
- leaf simpleBoolean {
- type boolean;
- default false;
- }
-
- leaf simple-long {
- type int64;
- default -45;
- }
-
- leaf simple-long-2 {
- type uint32;
- default 445;
- }
- leaf simple-BigInteger {
- type uint64;
- default 545454;
- }
+ leaf simpleInt {
+ type uint32;
+ }
- leaf simple-byte {
- type int8;
- default -4;
- }
+ leaf simpleBoolean {
+ type boolean;
+ default false;
+ }
- leaf simple-short {
- type uint8;
- default 45;
- }
+ leaf simple-long {
+ type int64;
+ default -45;
+ }
- leaf simple-test {
- type uint16;
- default 99;
- }
+ leaf simple-long-2 {
+ type uint32;
+ default 445;
+ }
- leaf-list simple-list {
- type uint16;
- }
+ leaf simple-BigInteger {
+ type uint64;
+ default 545454;
+ }
- container dto_d {
- leaf simple-int1 {
- type uint32;
+ leaf simple-byte {
+ type int8;
+ default -4;
}
- leaf simple-int2 {
- type uint32;
+ leaf simple-short {
+ type uint8;
+ default 45;
}
- leaf simple-int3 {
+ leaf simple-test {
type uint16;
+ default 99;
}
leaf-list simple-list {
type uint16;
}
- list complex-dto-bInner {
- leaf-list simple-list {
- type uint16;
+ container dto_d {
+ leaf simple-int1 {
+ type uint32;
}
+
+ leaf simple-int2 {
+ type uint32;
+ }
+
leaf simple-int3 {
type uint16;
}
- container deep {
+ leaf-list simple-list {
+ type uint16;
+ }
+
+ list complex-dto-bInner {
+ leaf-list simple-list {
+ type uint16;
+ }
leaf simple-int3 {
type uint16;
- default 0;
+ }
+
+ container deep {
+ leaf simple-int3 {
+ type uint16;
+ default 0;
+ }
}
}
}
- }
- list complex-list {
- list simple-list {
- leaf simple-int3 {
- type uint16;
+ list complex-list {
+ list simple-list {
+ leaf simple-int3 {
+ type uint16;
+ }
}
}
- }
- list peers {
- leaf port {
- type string;
- }
- leaf core-size {
- type uint32;
- }
- leaf simple-int3 {
- type uint16;
- }
- }
+ list peers {
+ leaf port {
+ type string;
+ }
+ leaf core-size {
+ type uint32;
+ }
+ leaf simple-int3 {
+ type uint16;
+ }
+ }
- container testing-dep {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity test:testing;
+ container testing-dep {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity test:testing;
+ }
}
}
- }
- list testing-deps {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity test:testing;
+ list testing-deps {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity test:testing;
+ }
}
}
}
augment "/config:modules/config:module/config:state" {
case impl-netconf {
when "/config:modules/config:module/config:type = 'impl-netconf'";
- // rpc
- rpcx:rpc-context-instance "test-rpc";
-
- // root runtime bean
- leaf created-sessions {
- type uint32;
- }
-
- container asdf {
- leaf simpleInt {
- type uint16;
- }
+ container impl-netconf {
+ // rpc
+ rpcx:rpc-context-instance "test-rpc";
- leaf simpleString {
- type string;
+ // root runtime bean
+ leaf created-sessions {
+ type uint32;
}
- }
+ container asdf {
+ leaf simpleInt {
+ type uint16;
+ }
- list inner-running-data-additional {
- config:inner-state-bean;
+ leaf simpleString {
+ type string;
+ }
+ }
- // rpc
- rpcx:rpc-context-instance "inner-test-rpc";
- key "simpleString";
+ list inner-running-data-additional {
+ config:inner-state-bean;
- leaf simple-int3 {
- type uint16;
- }
+ // rpc
+ rpcx:rpc-context-instance "inner-test-rpc";
- leaf simpleString {
- type string;
- }
+ key "simpleString";
- container deep4 {
- leaf boool {
- type boolean;
+ leaf simple-int3 {
+ type uint16;
}
- }
- }
-
- list inner-running-data {
- config:inner-state-bean;
- key "simple-int3";
-
- leaf simple-int3 {
- type uint16;
+ leaf simpleString {
+ type string;
}
- container deep2 {
- leaf boool {
- type boolean;
+ container deep4 {
+ leaf boool {
+ type boolean;
+ }
}
- }
+ }
- list inner-inner-running-data {
+ list inner-running-data {
config:inner-state-bean;
- rpcx:rpc-context-instance "inner-inner-test-rpc";
- rpcx:rpc-context-instance "complex-output-rpc";
-
key "simple-int3";
leaf simple-int3 {
- type uint16;
- }
+ type uint16;
+ }
- leaf-list list-of-strings {
- type string;
- }
+ container deep2 {
+ leaf boool {
+ type boolean;
+ }
+ }
- list not-state-bean {
- leaf element {
- type string;
+ list inner-inner-running-data {
+ config:inner-state-bean;
+
+ rpcx:rpc-context-instance "inner-inner-test-rpc";
+ rpcx:rpc-context-instance "complex-output-rpc";
+
+ key "simple-int3";
+
+ leaf simple-int3 {
+ type uint16;
}
- list not-state-bean-internal {
- // This should be ignored
- config:inner-state-bean;
+ leaf-list list-of-strings {
+ type string;
+ }
- leaf element2 {
+ list not-state-bean {
+ leaf element {
type string;
}
+
+ list not-state-bean-internal {
+ // This should be ignored
+ config:inner-state-bean;
+
+ leaf element2 {
+ type string;
+ }
+ }
}
- }
- container deep3 {
- leaf boool {
- type boolean;
+ container deep3 {
+ leaf boool {
+ type boolean;
+ }
}
}
}
<version>${karaf.version}</version>
<type>kar</type>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-features</artifactId>
- <version>${config.version}</version>
- <classifier>features</classifier>
- <type>xml</type>
- <scope>runtime</scope>
- </dependency>
<!-- 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>config-features</artifactId>
+ <version>${config.version}</version>
+ <classifier>features</classifier>
+ <type>xml</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>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-inet-types</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-restconf</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-topology</artifactId>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>ietf-yang-types</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-yang-types-20130715</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>
<artifactId>opendaylight-l2-types</artifactId>
reference\:file\:../lib/jersey-server-1.17.jar@2:start
# Netconf startup configuration
-netconf.tcp.address=127.0.0.1
-netconf.tcp.port=8383
-netconf.tcp.client.address=127.0.0.1
-netconf.tcp.client.port=8383
+# Netconf tcp address:port is optional with default value 127.0.0.1:8383
+#netconf.tcp.address=127.0.0.1
+#netconf.tcp.port=8384
+
+#netconf.tcp.client.address=127.0.0.1
+#netconf.tcp.client.port=8384
netconf.ssh.address=0.0.0.0
netconf.ssh.port=1830
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-parent</artifactId>
- <version>1.1-SNAPSHOT</version>
- <relativePath>../..</relativePath>
- </parent>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
- <tag>HEAD</tag>
- </scm>
-
- <artifactId>clustered-datastore-implementation</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- <packaging>bundle</packaging>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- </instructions>
- <manifestLocation>${project.basedir}/META-INF</manifestLocation>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>generate-sources</goal>
- </goals>
- <configuration>
- <codeGenerators>
- <generator>
- <codeGeneratorClass>
- org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
- </codeGeneratorClass>
- <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
- <additionalConfiguration>
- <namespaceToPackage1>
- urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
- </namespaceToPackage1>
- </additionalConfiguration>
- </generator>
- <generator>
- <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
- <outputBaseDir>target/site/models</outputBaseDir>
- </generator>
- </codeGenerators>
- <inspectDependencies>true</inspectDependencies>
- </configuration>
- </execution>
- </executions>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>0.2.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
- <dependencies>
-
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-core-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-api</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-api</artifactId>
- </dependency>
-
- </dependencies>
-</project>
+++ /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
- */
-/**
-* Generated file
-
-* Generated from: yang module name: odl-sal-dom-clustered-store-cfg yang module local name: dom-clustered-store-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Wed Nov 27 17:09:17 CET 2013
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.controller.config.yang.md.sal.dom.cluster.store;
-
-import org.opendaylight.controller.datastore.internal.ClusteredDataStoreManager;
-import org.osgi.framework.BundleContext;
-
-/**
-*
-*/
-public final class ClusteredDataStoreImplModule extends org.opendaylight.controller.config.yang.md.sal.dom.cluster.store.AbstractClusteredDataStoreImplModule
-{
-
- private BundleContext bundleContext;
-
- public ClusteredDataStoreImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public ClusteredDataStoreImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, ClusteredDataStoreImplModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- public void validate(){
- super.validate();
- // Add custom validation for module attributes here.
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- ClusteredDataStoreManager manager = new ClusteredDataStoreManager();
- manager.setContext(bundleContext);
- manager.start();
- return manager;
- }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-}
+++ /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
- */
-/**
-* Generated file
-
-* Generated from: yang module name: odl-sal-dom-clustered-store-cfg yang module local name: dom-clustered-store-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Wed Nov 27 17:09:17 CET 2013
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.controller.config.yang.md.sal.dom.cluster.store;
-
-import org.opendaylight.controller.config.api.DependencyResolver;
-import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
-import org.opendaylight.controller.config.spi.Module;
-import org.osgi.framework.BundleContext;
-
-/**
-*
-*/
-public class ClusteredDataStoreImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.dom.cluster.store.AbstractClusteredDataStoreImplModuleFactory
-{
-
- @Override
- public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
- ClusteredDataStoreImplModule module =
- (ClusteredDataStoreImplModule) super.createModule(instanceName, dependencyResolver, bundleContext);
- module.setBundleContext(bundleContext);
- return module;
- }
-
- @Override
- public Module createModule(String instanceName, DependencyResolver dependencyResolver,
- DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
- ClusteredDataStoreImplModule module =
- (ClusteredDataStoreImplModule) super.createModule(instanceName, dependencyResolver, old, bundleContext);
- module.setBundleContext(bundleContext);
- return module;
- }
-
-}
+++ /dev/null
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-
-package org.opendaylight.controller.datastore;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.sal.core.api.data.DataStore;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-public interface ClusteredDataStore extends DataStore {
-
-
-}
+++ /dev/null
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.datastore.internal;
-
-import com.google.common.base.Preconditions;
-
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.CacheExistException;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.clustering.services.IClusterServices;
-import org.opendaylight.controller.datastore.ClusteredDataStore;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.sal.common.util.Rpcs;
-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.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * The ClusteredDataStoreImpl stores global data to be shared across a controller cluster. It uses Clustering Services.
- */
-public class ClusteredDataStoreImpl implements ClusteredDataStore {
-
-
- public static final String OPERATIONAL_DATA_CACHE = "clustered_data_store.operational_data_cache";
- public static final String CONFIGURATION_DATA_CACHE = "clustered_data_store.configuration_data_cache";
-
- private final ConcurrentMap<InstanceIdentifier, CompositeNode> operationalDataCache;
- private final ConcurrentMap<InstanceIdentifier, CompositeNode> configurationDataCache;
-
- private Logger logger = LoggerFactory.getLogger(ClusteredDataStoreImpl.class);
-
- public ClusteredDataStoreImpl(IClusterGlobalServices clusterGlobalServices) throws CacheConfigException {
- logger.trace("Constructing clustered data store");
- Preconditions.checkNotNull(clusterGlobalServices, "clusterGlobalServices cannot be null");
-
- operationalDataCache = getOrCreateCache(clusterGlobalServices, OPERATIONAL_DATA_CACHE);
-
- Preconditions.checkNotNull(operationalDataCache, "operationalDataCache cannot be null");
-
- configurationDataCache = getOrCreateCache(clusterGlobalServices, CONFIGURATION_DATA_CACHE);
-
- Preconditions.checkNotNull(configurationDataCache, "configurationDataCache cannot be null");
- }
-
- @Override
- public DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
- return new ClusteredDataStoreTransaction(modification);
- }
-
- @Override
- public CompositeNode readOperationalData(InstanceIdentifier path) {
- Preconditions.checkNotNull(path, "path cannot be null");
- return operationalDataCache.get(path);
- }
-
- @Override
- public boolean containsConfigurationPath(InstanceIdentifier path) {
- return configurationDataCache.containsKey(path);
- }
-
- @Override
- public boolean containsOperationalPath(InstanceIdentifier path) {
- return operationalDataCache.containsKey(path);
- }
-
- @Override
- public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
- return configurationDataCache.keySet();
- }
-
- @Override
- public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
- return operationalDataCache.keySet();
- }
-
-
-
- @Override
- public CompositeNode readConfigurationData(InstanceIdentifier path) {
- Preconditions.checkNotNull(path, "path cannot be null");
- return configurationDataCache.get(path);
- }
-
- private RpcResult<Void> finish(final ClusteredDataStoreTransaction transaction) {
- final DataModification<InstanceIdentifier,CompositeNode> modification = transaction.getModification();
-
- this.configurationDataCache.putAll(modification.getUpdatedConfigurationData());
- this.operationalDataCache.putAll(modification.getUpdatedOperationalData());
-
- for (final InstanceIdentifier removal : modification.getRemovedConfigurationData()) {
- this.configurationDataCache.remove(removal);
- }
-
- for (final InstanceIdentifier removal : modification.getRemovedOperationalData()) {
- this.operationalDataCache.remove(removal );
- }
-
- Set<RpcError> _emptySet = Collections.<RpcError>emptySet();
- return Rpcs.<Void>getRpcResult(true, null, _emptySet);
- }
-
- private RpcResult<Void> rollback(final ClusteredDataStoreTransaction transaction) {
- Set<RpcError> _emptySet = Collections.<RpcError>emptySet();
- return Rpcs.<Void>getRpcResult(true, null, _emptySet);
- }
-
-
- private ConcurrentMap getOrCreateCache(IClusterGlobalServices clusterGlobalServices, String name) throws CacheConfigException {
- ConcurrentMap cache = clusterGlobalServices.getCache(name);
-
- if(cache == null) {
- try {
- cache = clusterGlobalServices.createCache(name, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
- } catch (CacheExistException e) {
- cache = clusterGlobalServices.getCache(name);
- }
- }
- return cache;
- }
-
- private class ClusteredDataStoreTransaction implements DataCommitTransaction<InstanceIdentifier, CompositeNode> {
- private final DataModification<InstanceIdentifier,CompositeNode> modification;
-
- public ClusteredDataStoreTransaction(DataModification<InstanceIdentifier,CompositeNode> modification){
- Preconditions.checkNotNull(modification, "modification cannot be null");
-
- this.modification = modification;
- }
-
- @Override
- public DataModification<InstanceIdentifier, CompositeNode> getModification() {
- return this.modification;
- }
-
- @Override
- public RpcResult<Void> finish() throws IllegalStateException {
- return ClusteredDataStoreImpl.this.finish(this);
- }
-
- @Override
- public RpcResult<Void> rollback() throws IllegalStateException {
- return ClusteredDataStoreImpl.this.rollback(this);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.datastore.internal;
-
-import java.util.Hashtable;
-
-import com.google.common.base.Preconditions;
-
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.datastore.ClusteredDataStore;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-public class ClusteredDataStoreManager implements //
- ClusteredDataStore, //
- ServiceTrackerCustomizer<IClusterGlobalServices, IClusterGlobalServices>, //
- AutoCloseable {
-
- private ClusteredDataStore clusteredDataStore = null;
- private IClusterGlobalServices clusterGlobalServices = null;
- private BundleContext context;
-
- private ServiceReference<IClusterGlobalServices> firstClusterGlobalReference;
- private ServiceTracker<IClusterGlobalServices, IClusterGlobalServices> clusterTracker;
-
- @Override
- public DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
- DataModification<InstanceIdentifier, CompositeNode> modification) {
- Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
- return clusteredDataStore.requestCommit(modification);
- }
-
- @Override
- public CompositeNode readOperationalData(InstanceIdentifier path) {
- Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
- return clusteredDataStore.readOperationalData(path);
- }
-
- @Override
- public CompositeNode readConfigurationData(InstanceIdentifier path) {
- Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
- return clusteredDataStore.readConfigurationData(path);
- }
-
- public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
- Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
- return clusteredDataStore.getStoredConfigurationPaths();
- }
-
- public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
- Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
- return clusteredDataStore.getStoredOperationalPaths();
- }
-
- public boolean containsConfigurationPath(InstanceIdentifier path) {
- Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
- return clusteredDataStore.containsConfigurationPath(path);
- }
-
- public boolean containsOperationalPath(InstanceIdentifier path) {
- Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
- return clusteredDataStore.containsOperationalPath(path);
- }
-
- public void setClusterGlobalServices(IClusterGlobalServices clusterGlobalServices) {
- this.clusterGlobalServices = clusterGlobalServices;
- try {
- // Adding creation of the clustered data store in its own method
- // to make the method unit testable
- clusteredDataStore = createClusteredDataStore();
- } catch (CacheConfigException e) {
- throw new IllegalStateException("could not construct clusteredDataStore");
- }
- }
-
- @Override
- public IClusterGlobalServices addingService(ServiceReference<IClusterGlobalServices> reference) {
- if (clusterGlobalServices == null) {
- setClusterGlobalServices(context.getService(reference));
- return clusterGlobalServices;
- }
- return null;
- }
-
- @Override
- public void modifiedService(ServiceReference<IClusterGlobalServices> reference, IClusterGlobalServices service) {
-
- }
-
- @Override
- public void removedService(ServiceReference<IClusterGlobalServices> reference, IClusterGlobalServices service) {
- if (clusterGlobalServices == service) {
- clusterGlobalServices = null;
- clusteredDataStore = null;
- }
- }
-
- public BundleContext getContext() {
- return context;
- }
-
- public void setContext(BundleContext context) {
- this.context = context;
- }
-
-
- /**
- * Function called by the dependency manager when all the required
- * dependencies are satisfied
- *
- */
- public void start() {
- if (context != null) {
- clusterTracker = new ServiceTracker<>(context, IClusterGlobalServices.class, this);
- clusterTracker.open();
-
- context.registerService(ClusteredDataStore.class, this, new Hashtable<String,Object>());
- }
- }
-
- protected ClusteredDataStore createClusteredDataStore() throws CacheConfigException {
- return new ClusteredDataStoreImpl(clusterGlobalServices);
- }
-
- @Override
- public void close() throws Exception {
- clusterTracker.close();
- }
-}
+++ /dev/null
-module odl-sal-dom-clustered-store-cfg {
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:cluster:store";
- prefix "binding-impl";
-
- import config { prefix config; revision-date 2013-04-05; }
- import opendaylight-md-sal-dom {prefix sal;}
-
- description
- "Service definition for MD-SAL Clustered Store.";
-
- revision "2013-10-28" {
- description
- "Initial revision";
- }
-
- identity dom-clustered-store-impl {
- base config:module-type;
- config:provided-service sal:dom-data-store;
- config:java-name-prefix ClusteredDataStoreImpl;
- }
-
- augment "/config:modules/config:module/config:state" {
- case dom-clustered-store-impl {
- when "/config:modules/config:module/config:type = 'dom-clustered-store-impl'";
- }
- }
-
-}
\ No newline at end of file
+++ /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.datastore.internal;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.CacheExistException;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.clustering.services.IClusterServices;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-import java.util.EnumSet;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class ClusteredDataStoreImplTest {
- @Before
- public void setUp(){
-
- }
-
- @Test
- public void constructor_WhenPassedANullClusteringServices_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
- try {
- new ClusteredDataStoreImpl(null);
- } catch(NullPointerException npe){
- assertEquals("clusterGlobalServices cannot be null", npe.getMessage());
- }
- }
-
- @Test
- public void constructor_WhenClusteringServicesReturnsANullOperationalDataCache_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
- try {
- new ClusteredDataStoreImpl(mock(IClusterGlobalServices.class));
- } catch(NullPointerException npe){
- assertEquals("operationalDataCache cannot be null", npe.getMessage());
- }
- }
-
- @Test
- public void constructor_WhenClusteringServicesReturnsANullOConfigurationDataCache_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
- IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
- // Confused about the following line?
- // See this http://stackoverflow.com/questions/10952629/a-strange-generics-edge-case-with-mockito-when-and-generic-type-inference
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(new ConcurrentHashMap<Object, Object>());
-
-
- try {
- new ClusteredDataStoreImpl(mockClusterGlobalServices);
- } catch(NullPointerException npe){
- assertEquals("configurationDataCache cannot be null", npe.getMessage());
- }
- }
-
- @Test
- public void constructor_WhenOperationalDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException {
- IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
-
- new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
- }
-
- @Test
- public void constructor_WhenConfigurationDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException {
- IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
-
- new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
- }
-
-
- @Test
- public void constructor_WhenPassedAValidClusteringServices_ShouldNotThrowAnyExceptions() throws CacheExistException, CacheConfigException {
- IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
- new ClusteredDataStoreImpl(mockClusterGlobalServices);
- }
-
-
- @Test
- public void readOperationalData_WhenPassedANullPath_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
- IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
- ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- try {
- store.readOperationalData(null);
- } catch(NullPointerException npe){
- assertEquals("path cannot be null", npe.getMessage());
- }
- }
-
- @Test
- public void readOperationalData_WhenPassedAKeyThatDoesNotExistInTheCache_ShouldReturnNull() throws CacheExistException, CacheConfigException {
- InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
-
- IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
- ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- assertNull(store.readOperationalData(path));
- }
-
- @Test
- public void readOperationalData_WhenPassedAKeyThatDoesExistInTheCache_ShouldReturnTheValueObject() throws CacheExistException, CacheConfigException {
- InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
-
- IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
- ConcurrentMap<InstanceIdentifier, CompositeNode> mockOperationalDataCache = mock(ConcurrentMap.class);
-
- CompositeNode valueObject = mock(CompositeNode.class);
-
- when(mockOperationalDataCache.get(path)).thenReturn(valueObject);
-
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(new ConcurrentHashMap<Object, Object>());
-
-
- ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- assertEquals(valueObject, store.readOperationalData(path));
- }
-
-
-
- @Test
- public void readConfigurationData_WhenPassedANullPath_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
-
- IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
- ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- try {
- store.readConfigurationData(null);
- } catch(NullPointerException npe){
- assertEquals("path cannot be null", npe.getMessage());
- }
- }
-
-
- @Test
- public void readConfigurationData_WhenPassedAKeyThatDoesNotExistInTheCache_ShouldReturnNull() throws CacheExistException, CacheConfigException {
- InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
-
- IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
- ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- assertNull(store.readConfigurationData(path));
- }
-
- @Test
- public void readConfigurationData_WhenPassedAKeyThatDoesExistInTheCache_ShouldReturnTheValueObject() throws CacheExistException, CacheConfigException {
- InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
-
- IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
- ConcurrentMap<InstanceIdentifier, CompositeNode> mockConfigurationDataCache = mock(ConcurrentMap.class);
-
- CompositeNode valueObject = mock(CompositeNode.class);
-
- when(mockConfigurationDataCache.get(path)).thenReturn(valueObject);
-
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
-
-
- ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- assertEquals(valueObject, store.readConfigurationData(path));
- }
-
-
- @Test
- public void requestCommit_ShouldReturnADataTransaction() throws CacheExistException, CacheConfigException {
- IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
-
- ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- assertNotNull(store.requestCommit(mock(DataModification.class)));
-
-
- }
-
- @Test
- public void finishingADataTransaction_ShouldUpdateTheUnderlyingCache() throws CacheExistException, CacheConfigException {
- IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
- ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
- ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
-
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
-
- ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- DataModification mockModification = mock(DataModification.class);
-
- Map configurationData = mock(Map.class);
- Map operationalData = mock(Map.class);
-
- when(mockModification.getUpdatedConfigurationData()).thenReturn(configurationData);
- when(mockModification.getUpdatedOperationalData()).thenReturn(operationalData);
-
- DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> transaction = store.requestCommit(mockModification);
-
- transaction.finish();
-
- verify(mockConfigurationDataCache).putAll(mockModification.getUpdatedConfigurationData());
- verify(mockOperationalDataCache).putAll(mockModification.getUpdatedOperationalData());
- }
-
-
- @Test
- public void rollingBackADataTransaction_ShouldDoNothing() throws CacheExistException, CacheConfigException {
- IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
- ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
- ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
-
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
-
- ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
-
- DataModification mockModification = mock(DataModification.class);
-
- Map configurationData = mock(Map.class);
- Map operationalData = mock(Map.class);
-
- when(mockModification.getUpdatedConfigurationData()).thenReturn(configurationData);
- when(mockModification.getUpdatedOperationalData()).thenReturn(operationalData);
-
- DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> transaction = store.requestCommit(mockModification);
-
- transaction.rollback();
-
- verify(mockConfigurationDataCache, never()).putAll(mockModification.getUpdatedConfigurationData());
- verify(mockOperationalDataCache, never()).putAll(mockModification.getUpdatedOperationalData());
-
- }
-
-
- private IClusterGlobalServices createClusterGlobalServices() throws CacheExistException, CacheConfigException {
- IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
-
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
- Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
-
- return mockClusterGlobalServices;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.datastore.internal;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.felix.dm.Component;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.clustering.services.CacheConfigException;
-import org.opendaylight.controller.clustering.services.CacheExistException;
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-import static junit.framework.Assert.assertNotNull;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-public class ClusteredDataStoreManagerTest {
-
- private static ClusteredDataStoreManager clusteredDSMgr = null;
- private IClusterGlobalServices icClusterGlbServices = mock(IClusterGlobalServices.class);
-
- @BeforeClass
- public static void construct() {
- clusteredDSMgr = new ClusteredDataStoreManager();
- assertNotNull(clusteredDSMgr);
- }
-
- @Test
- public void construct_OnSetClusterGlobalServices_AssertNoException() {
- doReturn(new ConcurrentHashMap<InstanceIdentifier, CompositeNode>()).when(icClusterGlbServices).getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE);
- doReturn(new ConcurrentHashMap<InstanceIdentifier, CompositeNode>()).when(icClusterGlbServices).getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE);
- clusteredDSMgr.setClusterGlobalServices(icClusterGlbServices);
- }
-
- @Test
- public void construct_init_AssertNoException() throws CacheExistException, CacheConfigException {
- ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
-
- ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
- doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore();
- clusteredDSManager.start();
- }
-
-
- @Test
- public void construct_readOperationalData_AssertNoException() throws CacheExistException, CacheConfigException {
- ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
-
- ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
- doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore();
- Component c = mock(Component.class);
-
- clusteredDSManager.start();
- clusteredDSManager.setClusterGlobalServices(icClusterGlbServices);
- CompositeNode o = mock(CompositeNode.class);
-
- when(clusteredDSImpl.readOperationalData(any(InstanceIdentifier.class))).thenReturn(o);
- assertEquals(o, clusteredDSManager.readOperationalData(any(InstanceIdentifier.class)));
- }
-
- @Test
- public void construct_readConfigurationData_AssertNoException() throws CacheExistException, CacheConfigException {
- ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
-
- ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
- doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore();
- Component c = mock(Component.class);
-
- clusteredDSManager.start();
- clusteredDSManager.setClusterGlobalServices(icClusterGlbServices);
-
- CompositeNode o = mock(CompositeNode.class);
-
- when(clusteredDSImpl.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(o);
- assertEquals(o, clusteredDSManager.readConfigurationData(any(InstanceIdentifier.class)));
- }
-
- @Test
- public void construct_requestCommit_AssertNoException() throws CacheExistException, CacheConfigException {
- ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
-
- ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
- doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore();
- IClusterGlobalServices globalServices = mock(IClusterGlobalServices.class);
- clusteredDSManager.setClusterGlobalServices(globalServices);
- clusteredDSManager.start();
- DataCommitTransaction dataCommitTransaction = mock(DataCommitTransaction.class);
-
- when(clusteredDSImpl.requestCommit(any(DataModification.class))).thenReturn(dataCommitTransaction);
- assertEquals(dataCommitTransaction, clusteredDSManager.requestCommit(any(DataModification.class)));
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
- xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.integrationtest</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- <relativePath>../../../commons/integrationtest</relativePath>
- </parent>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
- </scm>
-
- <artifactId>clustered-datastore.integrationtest</artifactId>
- <version>0.4.0-SNAPSHOT</version>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>xml-apis</groupId>
- <artifactId>xml-apis</artifactId>
- <version>1.4.01</version>
- </dependency>
- </dependencies>
- </dependencyManagement>
-
- <dependencies>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-it</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-api</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-impl</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-broker-impl</artifactId>
- <version>1.0-SNAPSHOT</version>
- <exclusions>
- <exclusion>
- <artifactId>xml-apis</artifactId>
- <groupId>xml-apis</groupId>
- </exclusion>
- <exclusion>
- <artifactId>reflections</artifactId>
- <groupId>org.reflections</groupId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- <version>0.7.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
- <version>0.5.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>antlr4-runtime-osgi-nohead</artifactId>
- <version>4.0</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>protocol_plugins.stub</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal.implementation</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>containermanager</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>containermanager.it.implementation</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.stub</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustered-datastore-implementation</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>xtend-lib-osgi</artifactId>
- <version>2.4.3</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-broker-impl</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-container-native</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-junit4</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-netconf-connector</artifactId>
- <version>${netconf.version}</version>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <artifactId>xml-apis</artifactId>
- <groupId>xml-apis</groupId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>logback-config</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-persister-impl</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-persister-file-xml-adapter</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-impl</artifactId>
- <version>${netconf.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-client</artifactId>
- <version>${netconf.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>concepts</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <version>1.9.5</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-manager</artifactId>
- <version>0.2.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>antlr4-runtime-osgi-nohead</artifactId>
- <version>4.0</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>xtend-lib-osgi</artifactId>
- <version>2.4.3</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-broker-impl</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-container-native</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-junit4</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-netconf-connector</artifactId>
- <version>${netconf.version}</version>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-parser-impl</artifactId>
- <version>${yangtools.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-model-util</artifactId>
- <version>${yangtools.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>logback-config</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-persister-impl</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-impl</artifactId>
- <version>${netconf.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-client</artifactId>
- <version>${netconf.version}</version>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-link-mvn</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.osgi</artifactId>
- <version>3.8.1.v20120830-144521</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- <version>1.7.2</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- <version>1.0.9</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <version>1.0.9</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-service</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-manager</artifactId>
- <version>0.2.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>antlr4-runtime-osgi-nohead</artifactId>
- <version>4.0</version>
- </dependency>
- </dependencies>
- <properties>
- <!-- Sonar jacoco plugin to get integration test coverage info -->
- <sonar.jacoco.reportPath>../implementation/target/jacoco.exec</sonar.jacoco.reportPath>
- <sonar.jacoco.itReportPath>../implementaiton/target/jacoco-it.exec</sonar.jacoco.itReportPath>
- </properties>
- <build>
- <plugins>
- <plugin>
- <groupId>org.jacoco</groupId>
- <artifactId>jacoco-maven-plugin</artifactId>
- <configuration>
- <destFile>../implementation/target/jacoco-it.exec</destFile>
- <includes><include>org.opendaylight.controller.*</include></includes>
- </configuration>
- <executions>
- <execution>
- <id>pre-test</id>
- <goals>
- <goal>prepare-agent</goal>
- </goals>
- </execution>
- <execution>
- <id>post-test</id>
- <configuration>
- <skip>true</skip>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.datastore;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.ops4j.pax.exam.CoreOptions.junitBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.CoreOptions.systemPackages;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.test.sal.binding.it.TestHelper;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.util.Filter;
-import org.ops4j.pax.exam.util.PathUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@RunWith(PaxExam.class)
-//@ExamReactorStrategy(PerClass.class)
-public class ClusteredDataStoreIT {
- private Logger log = LoggerFactory.getLogger(ClusteredDataStoreIT.class);
- // get the OSGI bundle context
- @Inject
- private BundleContext bc;
- @Inject
- @Filter(timeout=60*1000)
- private ClusteredDataStore clusteredDS;
-
- // Configure the OSGi container
- @Configuration
- public Option[] config() {
- return options(
- //
- systemProperty("logback.configurationFile").value(
- "file:" + PathUtils.getBaseDir() + "/src/test/resources/logback.xml"),
- // To start OSGi console for inspection remotely
- systemProperty("osgi.console").value("2401"),
- // Set the systemPackages (used by clustering)
- systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
- systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG"),
- // List framework bundles
- mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.eclipse.osgi.services").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell").versionAsInProject(),
- // List logger bundles
- mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
- mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
- mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(),
- mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(),
- // needed by statisticsmanager
- mavenBundle("org.opendaylight.controller", "containermanager").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "containermanager.it.implementation").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "clustering.services").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "clustering.stub").versionAsInProject(),
-
- // List all the bundles on which the test case depends
- mavenBundle("org.opendaylight.controller", "sal").versionAsInProject(),
- TestHelper.baseModelBundles(),
- TestHelper.configMinumumBundles(),
- TestHelper.bindingIndependentSalBundles(),
- TestHelper.bindingAwareSalBundles(),
- TestHelper.mdSalCoreBundles(),
- mavenBundle("org.opendaylight.controller", "config-api").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "sal.implementation").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "protocol_plugins.stub").versionAsInProject(),
-
- mavenBundle("org.osgi", "org.osgi.core").versionAsInProject(),
- // adding new maven bundles
- mavenBundle("org.mockito", "mockito-all").versionAsInProject(),
-
- // needed by hosttracker
- mavenBundle("org.opendaylight.controller", "clustered-datastore-implementation").versionAsInProject(),
- mavenBundle("org.jboss.spec.javax.transaction", "jboss-transaction-api_1.1_spec").versionAsInProject(),
- mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
- mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
- junitBundles());
- }
-
- private String stateToString(int state) {
- switch (state) {
- case Bundle.ACTIVE:
- return "ACTIVE";
- case Bundle.INSTALLED:
- return "INSTALLED";
- case Bundle.RESOLVED:
- return "RESOLVED";
- case Bundle.UNINSTALLED:
- return "UNINSTALLED";
- default:
- return "Not CONVERTED";
- }
- }
-
- @Test
- public void testBundleContextClusteredDS_NotNull() throws Exception {
- ServiceReference serviceReference = bc.getServiceReference(ClusteredDataStore.class);
- ClusteredDataStore store = ClusteredDataStore.class.cast(bc.getService(serviceReference));
- assertNotNull(store);
- }
-
- @Test
- public void testInjected_ClusteredDS_NotNull() {
- assertNotNull(clusteredDS);
- }
-
- @Test
- public void requestCommit_readConfigurationData_ShouldVerifyDataAndNoException() {
- DataModification dataModification = mock(DataModification.class);
- HashMap map = new HashMap();
- List list = new ArrayList();
- list.add("key");
- InstanceIdentifier key = new InstanceIdentifier(list);
- map.put(key, mock(CompositeNode.class));
- when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
- DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
- dataCommitTrans.finish();
- Object value = clusteredDS.readConfigurationData(key);
- Assert.assertNotNull(value);
- }
-
- @Test(expected = NullPointerException.class)
- public void requestCommit_ShouldThrowException() {
- DataModification dataModification = null;
- DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
- dataCommitTrans.finish();
- }
-
- @Test
- public void requestCommit_readOperationalData_ShouldVerifyDataAndNoException() {
- DataModification dataModification = mock(DataModification.class);
- HashMap map = new HashMap();
- List list = new ArrayList();
- list.add("key");
- InstanceIdentifier key = new InstanceIdentifier(list);
- map.put(key, mock(CompositeNode.class));
- when(dataModification.getUpdatedOperationalData()).thenReturn(map);
- DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
- dataCommitTrans.finish();
- Object value = clusteredDS.readOperationalData(key);
- Assert.assertNotNull(value);
- }
-
- @Test
- public void requestCommit_readConfigurationData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException() {
- DataModification dataModification = mock(DataModification.class);
- HashMap map = new HashMap();
- List list = new ArrayList();
- list.add("key");
- InstanceIdentifier key = new InstanceIdentifier(list);
- map.put(key, "value");
- when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
- DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
- dataCommitTrans.finish();
- list = new ArrayList();
- list.add("key1");
- InstanceIdentifier key1 = new InstanceIdentifier(list);
-
- Object value = clusteredDS.readConfigurationData(key1);
- assertNull(value);
- }
-
- @Test
- public void requestCommit_readOperationalData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException() {
- DataModification dataModification = mock(DataModification.class);
- HashMap map = new HashMap();
- List list = new ArrayList();
- list.add("key");
- InstanceIdentifier key = new InstanceIdentifier(list);
- map.put(key, mock(CompositeNode.class));
- when(dataModification.getUpdatedOperationalData()).thenReturn(map);
- DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
- dataCommitTrans.finish();
- list = new ArrayList();
- list.add("key1");
- InstanceIdentifier key1 = new InstanceIdentifier(list);
-
- Object value = clusteredDS.readOperationalData(key1);
- assertNull(value);
- }
-
- @Test(expected = NullPointerException.class)
- public void requestCommit_readConfigurationData_WithNullPathShouldThrowException() {
- DataModification dataModification = mock(DataModification.class);
- HashMap map = new HashMap();
- List list = new ArrayList();
- list.add("key");
- InstanceIdentifier key = new InstanceIdentifier(list);
- map.put(key, "value");
- when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
- DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
- dataCommitTrans.finish();
- Object value = clusteredDS.readConfigurationData(null);
- }
-
- @Test(expected = NullPointerException.class)
- public void requestCommit_readOperationalData_WithNullPathShouldThrowException() {
- DataModification dataModification = mock(DataModification.class);
- HashMap map = new HashMap();
- List list = new ArrayList();
- list.add("key");
- InstanceIdentifier key = new InstanceIdentifier(list);
- map.put(key, "value");
- when(dataModification.getOriginalOperationalData()).thenReturn(map);
- DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
- dataCommitTrans.finish();
- Object value = clusteredDS.readOperationalData(null);
- }
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<persisted-snapshots>
- <snapshots>
- <snapshot>
- <required-capabilities>
- <capability>
- urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:cluster:store?module=odl-sal-dom-clustered-store-cfg&revision=2013-10-28
- </capability>
- </required-capabilities>
- <configuration>
-
- <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
- <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:cluster:store">
- prefix:dom-clustered-store-impl
- </type>
- <name>cluster-data-store</name>
- </module>
- </modules>
-
- <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-
- </services>
- </data>
-
- </configuration>
- </snapshot>
- </snapshots>
-</persisted-snapshots>
+++ /dev/null
-<configuration scan="true">
-
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
- </pattern>
- </encoder>
- </appender>
-
- <root level="debug">
- <appender-ref ref="STDOUT" />
- </root>
-</configuration>
--- /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.sal.compatibility;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.compatibility.adsal.DataPacketServiceAdapter;
+import org.opendaylight.controller.sal.compatibility.topology.TopologyAdapter;
+import org.opendaylight.controller.sal.compatibility.topology.TopologyProvider;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.opendaylight.controller.sal.core.Node.NodeIDType;
+import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
+import org.opendaylight.controller.sal.discovery.IDiscoveryService;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
+import org.opendaylight.controller.sal.inventory.IPluginInInventoryService;
+import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService;
+import org.opendaylight.controller.sal.packet.IPluginInDataPacketService;
+import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService;
+import org.opendaylight.controller.sal.reader.IPluginInReadService;
+import org.opendaylight.controller.sal.reader.IPluginOutReadService;
+import org.opendaylight.controller.sal.topology.IPluginInTopologyService;
+import org.opendaylight.controller.sal.topology.IPluginOutTopologyService;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.INodeConnectorFactory;
+import org.opendaylight.controller.sal.utils.INodeFactory;
+import org.osgi.framework.BundleContext;
+
+import com.google.common.base.Preconditions;
+
+public class ComponentActivator extends ComponentActivatorAbstractBase {
+ private final INodeConnectorFactory nodeConnectorFactory = new MDSalNodeConnectorFactory();
+ private final DataPacketServiceAdapter dataPacketService = new DataPacketServiceAdapter();
+ private final InventoryAndReadAdapter inventory = new InventoryAndReadAdapter();
+ private final FlowProgrammerAdapter flow = new FlowProgrammerAdapter();
+ private final DataPacketAdapter dataPacket = new DataPacketAdapter();
+ private final TopologyProvider tpProvider = new TopologyProvider();
+ private final INodeFactory nodeFactory = new MDSalNodeFactory();
+ private final TopologyAdapter topology = new TopologyAdapter();
+ private BundleContext context;
+
+ public INodeConnectorFactory getNodeConnectorFactory() {
+ return nodeConnectorFactory;
+ }
+
+ public DataPacketServiceAdapter getDataPacketService() {
+ return dataPacketService;
+ }
+
+ public InventoryAndReadAdapter getInventory() {
+ return inventory;
+ }
+
+ public FlowProgrammerAdapter getFlow() {
+ return flow;
+ }
+
+ public DataPacketAdapter getDataPacket() {
+ return dataPacket;
+ }
+
+ public TopologyProvider getTpProvider() {
+ return tpProvider;
+ }
+
+ public INodeFactory getNodeFactory() {
+ return nodeFactory;
+ }
+
+ public TopologyAdapter getTopology() {
+ return topology;
+ }
+
+ @Override
+ protected void init() {
+ NodeIDType.registerIDType(NodeMapping.MD_SAL_TYPE, String.class);
+ NodeConnectorIDType.registerIDType(NodeMapping.MD_SAL_TYPE, String.class, NodeMapping.MD_SAL_TYPE);
+ }
+
+ @Override
+ public void start(final BundleContext context) {
+ super.start(context);
+ this.context = Preconditions.checkNotNull(context);
+ }
+
+ public ProviderContext setBroker(final BindingAwareBroker broker) {
+ return broker.registerProvider(new SalCompatibilityProvider(this), context);
+ }
+
+ @Override
+ protected Object[] getGlobalImplementations() {
+ return new Object[] {
+ flow,
+ inventory,
+ dataPacket,
+ nodeFactory,
+ nodeConnectorFactory,
+ topology,
+ tpProvider,
+ };
+ }
+
+ @Override
+ protected void configureGlobalInstance(final Component c, final Object imp) {
+ if (imp instanceof DataPacketAdapter) {
+ _configure((DataPacketAdapter)imp, c);
+ } else if (imp instanceof FlowProgrammerAdapter) {
+ _configure((FlowProgrammerAdapter)imp, c);
+ } else if (imp instanceof InventoryAndReadAdapter) {
+ _configure((InventoryAndReadAdapter)imp, c);
+ } else if (imp instanceof ComponentActivator) {
+ _configure((ComponentActivator)imp, c);
+ } else if (imp instanceof MDSalNodeConnectorFactory) {
+ _configure((MDSalNodeConnectorFactory)imp, c);
+ } else if (imp instanceof MDSalNodeFactory) {
+ _configure((MDSalNodeFactory)imp, c);
+ } else if (imp instanceof TopologyAdapter) {
+ _configure((TopologyAdapter)imp, c);
+ } else if (imp instanceof TopologyProvider) {
+ _configure((TopologyProvider)imp, c);
+ } else {
+ throw new IllegalArgumentException(String.format("Unhandled implementation class %s", imp.getClass()));
+ }
+ }
+
+ @Override
+ protected Object[] getImplementations() {
+ return new Object[] {
+ dataPacketService,
+ };
+ }
+
+ @Override
+ protected void configureInstance(final Component c, final Object imp, final String containerName) {
+ if (imp instanceof ComponentActivator) {
+ _instanceConfigure((ComponentActivator)imp, c, containerName);
+ } else if (imp instanceof DataPacketServiceAdapter) {
+ _instanceConfigure((DataPacketServiceAdapter)imp, c, containerName);
+ } else {
+ throw new IllegalArgumentException(String.format("Unhandled implementation class %s", imp.getClass()));
+ }
+ }
+
+ private void _configure(final MDSalNodeFactory imp, final Component it) {
+ it.setInterface(INodeFactory.class.getName(), properties());
+ }
+
+ private void _configure(final MDSalNodeConnectorFactory imp, final Component it) {
+ it.setInterface(INodeConnectorFactory.class.getName(), properties());
+ }
+
+ private void _configure(final ComponentActivator imp, final Component it) {
+ it.add(createServiceDependency()
+ .setService(BindingAwareBroker.class)
+ .setCallbacks("setBroker", "setBroker")
+ .setRequired(true));
+ }
+
+ private void _configure(final DataPacketAdapter imp, final Component it) {
+ it.add(createServiceDependency()
+ .setService(IPluginOutDataPacketService.class)
+ .setCallbacks("setDataPacketPublisher", "setDataPacketPublisher")
+ .setRequired(false));
+ }
+
+ private void _configure(final FlowProgrammerAdapter imp, final Component it) {
+ it.setInterface(IPluginInFlowProgrammerService.class.getName(), properties());
+ it.add(createServiceDependency()
+ .setService(IPluginOutFlowProgrammerService.class)
+ .setCallbacks("setFlowProgrammerPublisher", "setFlowProgrammerPublisher")
+ .setRequired(false));
+ it.add(createServiceDependency()
+ .setService(IClusterGlobalServices.class)
+ .setCallbacks("setClusterGlobalServices", "unsetClusterGlobalServices")
+ .setRequired(false));
+ }
+
+ private void _instanceConfigure(final DataPacketServiceAdapter imp, final Component it, final String containerName) {
+ it.setInterface(IPluginInDataPacketService.class.getName(), properties());
+ }
+
+ private void _instanceConfigure(final ComponentActivator imp, final Component it, final String containerName) {
+ // No-op
+ }
+
+ private void _configure(final InventoryAndReadAdapter imp, final Component it) {
+ it.setInterface(new String[] {
+ IPluginInInventoryService.class.getName(),
+ IPluginInReadService.class.getName(),
+ }, properties());
+
+ it.add(createServiceDependency()
+ .setService(IPluginOutReadService.class)
+ .setCallbacks("setReadPublisher", "unsetReadPublisher")
+ .setRequired(false));
+ it.add(createServiceDependency()
+ .setService(IPluginOutInventoryService.class)
+ .setCallbacks("setInventoryPublisher", "unsetInventoryPublisher")
+ .setRequired(false));
+ it.add(createServiceDependency()
+ .setService(IDiscoveryService.class)
+ .setCallbacks("setDiscoveryPublisher", "setDiscoveryPublisher")
+ .setRequired(false));
+ }
+
+ private void _configure(final TopologyAdapter imp, final Component it) {
+ it.setInterface(IPluginInTopologyService.class.getName(), properties());
+
+ it.add(createServiceDependency()
+ .setService(IPluginOutTopologyService.class)
+ .setCallbacks("setTopologyPublisher", "setTopologyPublisher")
+ .setRequired(false));
+ }
+
+ private void _configure(final TopologyProvider imp, final Component it) {
+ it.add(createServiceDependency()
+ .setService(IPluginOutTopologyService.class)
+ .setCallbacks("setTopologyPublisher", "setTopologyPublisher")
+ .setRequired(false));
+ }
+
+ private Dictionary<String,Object> properties() {
+ final Hashtable<String,Object> props = new Hashtable<String, Object>();
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), NodeMapping.MD_SAL_TYPE);
+ props.put("protocolName", NodeMapping.MD_SAL_TYPE);
+ return props;
+ }
+}
+++ /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.sal.compatibility
-
-import java.util.Arrays
-import java.util.Dictionary
-import java.util.Hashtable
-import org.apache.felix.dm.Component
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext
-import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer
-import org.opendaylight.controller.sal.binding.api.NotificationService
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.compatibility.topology.TopologyAdapter
-import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase
-import org.opendaylight.controller.sal.core.Node
-import org.opendaylight.controller.sal.core.NodeConnector
-import org.opendaylight.controller.sal.discovery.IDiscoveryService
-import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService
-import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService
-import org.opendaylight.controller.sal.inventory.IPluginInInventoryService
-import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService
-import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService
-import org.opendaylight.controller.sal.reader.IPluginInReadService
-import org.opendaylight.controller.sal.reader.IPluginOutReadService
-import org.opendaylight.controller.sal.topology.IPluginInTopologyService
-import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
-import org.opendaylight.controller.sal.utils.GlobalConstants
-import org.opendaylight.controller.sal.utils.INodeConnectorFactory
-import org.opendaylight.controller.sal.utils.INodeFactory
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices
-import org.opendaylight.controller.sal.packet.IPluginInDataPacketService
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService
-import org.osgi.framework.BundleContext
-
-import static org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import org.opendaylight.controller.sal.compatibility.topology.TopologyProvider
-import org.opendaylight.controller.sal.compatibility.adsal.DataPacketServiceAdapter
-import org.opendaylight.controller.sal.binding.api.BindingAwareProvider
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext
-
-class ComponentActivator extends ComponentActivatorAbstractBase {
-
- private BundleContext context;
-
- @Property
- FlowProgrammerAdapter flow = new FlowProgrammerAdapter;
-
- @Property
- InventoryAndReadAdapter inventory = new InventoryAndReadAdapter;
-
- @Property
- DataPacketAdapter dataPacket = new DataPacketAdapter;
-
- @Property
- INodeFactory nodeFactory = new MDSalNodeFactory
-
- @Property
- INodeConnectorFactory nodeConnectorFactory = new MDSalNodeConnectorFactory
-
- @Property
- TopologyAdapter topology = new TopologyAdapter
-
- @Property
- TopologyProvider tpProvider = new TopologyProvider()
-
- @Property
- DataPacketServiceAdapter dataPacketService = new DataPacketServiceAdapter()
-
-
-
- override protected init() {
- Node.NodeIDType.registerIDType(MD_SAL_TYPE, String);
- NodeConnector.NodeConnectorIDType.registerIDType(MD_SAL_TYPE, String, MD_SAL_TYPE);
- }
-
- override start(BundleContext context) {
- super.start(context)
- this.context = context;
- }
-
- def setBroker(BindingAwareBroker broker) {
- broker.registerProvider(new SalCompatibilityProvider(this), context)
- }
-
-
- override protected getGlobalImplementations() {
- return Arrays.asList(this, flow, inventory, dataPacket, nodeFactory, nodeConnectorFactory,topology,tpProvider)
- }
-
- override protected configureGlobalInstance(Component c, Object imp) {
- configure(imp, c);
- }
-
- override protected getImplementations() {
- return Arrays.asList(dataPacketService)
- }
-
- override protected configureInstance(Component c, Object imp, String containerName) {
- instanceConfigure(imp, c, containerName);
- }
-
- private def dispatch configure(MDSalNodeFactory imp, Component it) {
- setInterface(INodeFactory.name, properties);
- }
-
- private def dispatch configure(MDSalNodeConnectorFactory imp, Component it) {
- setInterface(INodeConnectorFactory.name, properties);
- }
-
- private def dispatch configure(ComponentActivator imp, Component it) {
- add(
- createServiceDependency().setService(BindingAwareBroker) //
- .setCallbacks("setBroker", "setBroker") //
- .setRequired(true))
-
-
- }
-
- private def dispatch configure(DataPacketAdapter imp, Component it) {
- add(
- createServiceDependency() //
- .setService(IPluginOutDataPacketService) //
- .setCallbacks("setDataPacketPublisher", "setDataPacketPublisher") //
- .setRequired(false))
- }
-
- private def dispatch configure(FlowProgrammerAdapter imp, Component it) {
- setInterface(IPluginInFlowProgrammerService.name, properties)
- add(
- createServiceDependency() //
- .setService(IPluginOutFlowProgrammerService) //
- .setCallbacks("setFlowProgrammerPublisher", "setFlowProgrammerPublisher") //
- .setRequired(false))
-
- add(
- createServiceDependency() //
- .setService(IClusterGlobalServices) //
- .setCallbacks("setClusterGlobalServices", "unsetClusterGlobalServices") //
- .setRequired(false))
-
- }
-
- private def dispatch instanceConfigure(DataPacketServiceAdapter imp, Component it, String containerName) {
- setInterface(IPluginInDataPacketService.name, properties)
- }
-
- private def dispatch instanceConfigure(ComponentActivator imp, Component it, String containerName) {
- }
-
-
- private def dispatch configure(InventoryAndReadAdapter imp, Component it) {
- setInterface(Arrays.asList(IPluginInInventoryService.name, IPluginInReadService.name), properties)
- add(
- createServiceDependency() //
- .setService(IPluginOutReadService) //
- .setCallbacks("setReadPublisher", "unsetReadPublisher") //
- .setRequired(false))
- add(
- createServiceDependency() //
- .setService(IPluginOutInventoryService) //
- .setCallbacks("setInventoryPublisher", "unsetInventoryPublisher") //
- .setRequired(false))
- add(
- createServiceDependency() //
- .setService(IDiscoveryService) //
- .setCallbacks("setDiscoveryPublisher", "setDiscoveryPublisher") //
- .setRequired(false))
-
-
- }
-
- private def dispatch configure (TopologyAdapter imp, Component it) {
- setInterface(Arrays.asList(IPluginInTopologyService.name), properties)
- add(
- createServiceDependency() //
- .setService(IPluginOutTopologyService) //
- .setCallbacks("setTopologyPublisher", "setTopologyPublisher") //
- .setRequired(false))
- }
-
- private def dispatch configure (TopologyProvider imp, Component it) {
- add(
- createServiceDependency() //
- .setService(IPluginOutTopologyService) //
- .setCallbacks("setTopologyPublisher", "setTopologyPublisher") //
- .setRequired(false))
- }
-
- private def Dictionary<String, Object> properties() {
- val props = new Hashtable<String, Object>();
- props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString, MD_SAL_TYPE)
- props.put("protocolName", MD_SAL_TYPE);
- return props;
- }
-}
-package class SalCompatibilityProvider implements BindingAwareProvider {
-
- private val ComponentActivator activator;
-
- new(ComponentActivator cmpAct) {
- activator = cmpAct;
- }
-
- override getFunctionality() {
- // Noop
- }
-
- override getImplementations() {
- // Noop
- }
-
-
- override onSessionInitialized(ConsumerContext session) {
- // Noop
- }
-
-
- override onSessionInitiated(ProviderContext session) {
- val it = activator
- val subscribe = session.getSALService(NotificationService)
-
- // Registration of Flow Service
- flow.delegate = session.getRpcService(SalFlowService)
- flow.dataBrokerService = session.getSALService(DataBrokerService);
- subscribe.registerNotificationListener(flow);
-
- // Data Packet Service
- subscribe.registerNotificationListener(inventory);
- dataPacketService.delegate = session.getRpcService(PacketProcessingService)
-
- // Inventory Service
- inventory.dataService = session.getSALService(DataBrokerService);
- inventory.flowStatisticsService = session.getRpcService(OpendaylightFlowStatisticsService);
- inventory.flowTableStatisticsService = session.getRpcService(OpendaylightFlowTableStatisticsService);
- inventory.nodeConnectorStatisticsService = session.getRpcService(OpendaylightPortStatisticsService);
- inventory.topologyDiscovery = session.getRpcService(FlowTopologyDiscoveryService);
- inventory.dataProviderService = session.getSALService(DataProviderService)
- topology.dataService = session.getSALService(DataProviderService)
- tpProvider.dataService = session.getSALService(DataProviderService)
-
- inventory.startAdapter();
-
- tpProvider.startAdapter();
-
- subscribe.registerNotificationListener(dataPacket)
- }
-}
--- /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.sal.compatibility;
+
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService;
+import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class DataPacketAdapter implements PacketProcessingListener {
+ private static final Logger LOG = LoggerFactory.getLogger(DataPacketAdapter.class);
+ private IPluginOutDataPacketService dataPacketPublisher;
+
+ @Override
+ public void onPacketReceived(final PacketReceived packet) {
+ try {
+ RawPacket inPacket = toRawPacket(packet);
+ dataPacketPublisher.receiveDataPacket(inPacket);
+ } catch (ConstructionException e) {
+ LOG.warn("Failed to construct raw packet from {}, dropping it", packet, e);
+ }
+ }
+
+ public static RawPacket toRawPacket(final PacketReceived received) throws ConstructionException {
+ final RawPacket ret = new RawPacket(received.getPayload());
+ ret.setIncomingNodeConnector(NodeMapping.toADNodeConnector(received.getIngress()));
+ return ret;
+ }
+}
+++ /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.sal.compatibility
-
-import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived
-import org.opendaylight.controller.sal.packet.RawPacket
-
-class DataPacketAdapter implements PacketProcessingListener {
-
- @Property
- IPluginOutDataPacketService dataPacketPublisher;
-
- override onPacketReceived(PacketReceived packet) {
- val RawPacket inPacket = packet.toRawPacket();
- dataPacketPublisher.receiveDataPacket(inPacket);
- }
-
- public static def RawPacket toRawPacket(PacketReceived received) {
- val ret = new RawPacket(received.payload);
- ret.setIncomingNodeConnector(NodeMapping.toADNodeConnector(received.ingress))
- return ret;
- }
-
-}
--- /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.sal.compatibility;
+
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices.cacheMode;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener {
+ private final static Logger LOG = LoggerFactory.getLogger(FlowProgrammerAdapter.class);
+
+ // Note: clustering services manipulate this
+ private final Map<Flow, UUID> flowToFlowId = new ConcurrentHashMap<Flow, UUID>();
+ private final static String CACHE_NAME = "flowprogrammeradapter.flowtoid";
+
+ // These are injected via Apache DM (see ComponentActivator)
+ private IPluginOutFlowProgrammerService flowProgrammerPublisher;
+ private IClusterGlobalServices clusterGlobalServices;
+ private DataBrokerService dataBrokerService;
+ private SalFlowService delegate;
+
+ public SalFlowService getDelegate() {
+ return this.delegate;
+ }
+
+ public void setDelegate(final SalFlowService delegate) {
+ this.delegate = delegate;
+ }
+
+ public DataBrokerService getDataBrokerService() {
+ return this.dataBrokerService;
+ }
+
+ public void setDataBrokerService(final DataBrokerService dataBrokerService) {
+ this.dataBrokerService = dataBrokerService;
+ }
+
+ public IPluginOutFlowProgrammerService getFlowProgrammerPublisher() {
+ return this.flowProgrammerPublisher;
+ }
+
+ public void setFlowProgrammerPublisher(final IPluginOutFlowProgrammerService flowProgrammerPublisher) {
+ this.flowProgrammerPublisher = flowProgrammerPublisher;
+ }
+
+ public IClusterGlobalServices getClusterGlobalServices() {
+ return this.clusterGlobalServices;
+ }
+
+ public void setClusterGlobalServices(final IClusterGlobalServices clusterGlobalServices) {
+ this.clusterGlobalServices = clusterGlobalServices;
+ }
+
+ @Override
+ public Status addFlow(final Node node, final Flow flow) {
+ return toFutureStatus(internalAddFlowAsync(node, flow, 0));
+ }
+
+ @Override
+ public Status modifyFlow(final Node node, final Flow oldFlow, final Flow newFlow) {
+ return toFutureStatus(internalModifyFlowAsync(node, oldFlow, newFlow, 0));
+ }
+
+ @Override
+ public Status removeFlow(final Node node, final Flow flow) {
+ return toFutureStatus(internalRemoveFlowAsync(node, flow, 0));
+ }
+
+ @Override
+ public Status addFlowAsync(final Node node, final Flow flow, final long rid) {
+ // FIXME is this correct? What if the future fails?
+ this.internalAddFlowAsync(node, flow, rid);
+ return FlowProgrammerAdapter.toStatus(true);
+ }
+
+ @Override
+ public Status modifyFlowAsync(final Node node, final Flow oldFlow, final Flow newFlow, final long rid) {
+ // FIXME is this correct? What if the future fails?
+ this.internalModifyFlowAsync(node, oldFlow, newFlow, rid);
+ return FlowProgrammerAdapter.toStatus(true);
+ }
+
+ @Override
+ public Status removeFlowAsync(final Node node, final Flow flow, final long rid) {
+ // FIXME is this correct? What if the future fails?
+ this.internalRemoveFlowAsync(node, flow, rid);
+ return FlowProgrammerAdapter.toStatus(true);
+ }
+
+ @Override
+ public Status removeAllFlows(final Node node) {
+ // FIXME: unfinished?
+ return new Status(StatusCode.SUCCESS);
+ }
+
+ @Override
+ public Status syncSendBarrierMessage(final Node node) {
+ // FIXME: unfinished?
+ return null;
+ }
+
+ @Override
+ public Status asyncSendBarrierMessage(final Node node) {
+ // FIXME: unfinished?
+ return null;
+ }
+
+ private static Status toStatus(final boolean successful) {
+ return new Status(successful ? StatusCode.SUCCESS : StatusCode.INTERNALERROR);
+ }
+
+ public static Status toStatus(final RpcResult<? extends Object> result) {
+ return toStatus(result.isSuccessful());
+ }
+
+ @Override
+ public void onFlowAdded(final FlowAdded notification) {
+ // FIXME: unfinished?
+ }
+
+ @Override
+ public void onFlowRemoved(final FlowRemoved notification) {
+ if (notification == null) {
+ return;
+ }
+
+ final NodeRef node = notification.getNode();
+ if (node == null) {
+ LOG.debug("Notification {} has not node, ignoring it", notification);
+ return;
+ }
+
+ Node adNode;
+ try {
+ adNode = NodeMapping.toADNode(notification.getNode());
+ } catch (ConstructionException e) {
+ LOG.warn("Failed to construct AD node for {}, ignoring notification", node, e);
+ return;
+ }
+ flowProgrammerPublisher.flowRemoved(adNode, ToSalConversionsUtils.toFlow(notification, adNode));
+ }
+
+ @Override
+ public void onFlowUpdated(final FlowUpdated notification) {
+ // FIXME: unfinished?
+ }
+
+ @Override
+ public void onSwitchFlowRemoved(final SwitchFlowRemoved notification) {
+ // FIXME: unfinished?
+ }
+
+ @Override
+ public void onNodeErrorNotification(final NodeErrorNotification notification) {
+ // FIXME: unfinished?
+ }
+
+ @Override
+ public void onNodeExperimenterErrorNotification(final NodeExperimenterErrorNotification notification) {
+ // FIXME: unfinished?
+ }
+
+ private static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow> flowPath(
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, final NodeKey nodeKey) {
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, nodeKey)
+ .augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(flow.getTableId()))
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow.class, new FlowKey(flow.getId()))
+ .toInstance();
+ }
+
+ private Future<RpcResult<TransactionStatus>> writeFlowAsync(final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, final NodeKey nodeKey) {
+ final DataModificationTransaction modification = this.dataBrokerService.beginTransaction();
+ modification.putConfigurationData(flowPath(flow, nodeKey), flow);
+ return modification.commit();
+ }
+
+ private Future<RpcResult<TransactionStatus>> internalAddFlowAsync(final Node node, final Flow flow, final long rid) {
+ final Map<Flow,UUID> cache = this.getCache();
+ UUID flowId = cache.get(flow);
+ if (flowId != null) {
+ this.removeFlow(node, flow);
+ }
+
+ flowId = UUID.randomUUID();
+ cache.put(flow, flowId);
+ return this.writeFlowAsync(MDFlowMapping.toMDFlow(flow, flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
+ }
+
+ private Future<RpcResult<TransactionStatus>> internalModifyFlowAsync(final Node node, final Flow oldFlow, final Flow newFlow, final long rid) {
+ final Map<Flow,UUID> cache = this.getCache();
+
+ UUID flowId = cache.remove(oldFlow);
+ if (flowId == null) {
+ flowId = UUID.randomUUID();
+ cache.put(oldFlow, flowId);
+ LOG.warn("Could not find flow {} in cache, assigned new ID {}", oldFlow.hashCode(), flowId);
+ }
+
+ cache.put(newFlow, flowId);
+ return this.writeFlowAsync(MDFlowMapping.toMDFlow(newFlow, flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
+ }
+
+ private Future<RpcResult<TransactionStatus>> internalRemoveFlowAsync(final Node node, final Flow adflow, final long rid) {
+ final Map<Flow,UUID> cache = this.getCache();
+
+ final UUID flowId = cache.remove(adflow);
+ if (flowId == null) {
+ LOG.warn("Could not find flow {} in cache, nothing to do", adflow.hashCode());
+ return null;
+ }
+
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow = MDFlowMapping.toMDFlow(adflow, flowId.toString());
+ final DataModificationTransaction modification = this.dataBrokerService.beginTransaction();
+ modification.removeConfigurationData(flowPath(flow, new NodeKey(new NodeId(node.getNodeIDString()))));
+ return modification.commit();
+ }
+
+ private static Status toFutureStatus(final Future<RpcResult<TransactionStatus>> future) {
+ if (future == null) {
+ // FIXME: really?
+ return FlowProgrammerAdapter.toStatus(true);
+ }
+
+ try {
+ final RpcResult<TransactionStatus> result = future.get();
+ return FlowProgrammerAdapter.toStatus(result);
+ } catch (final InterruptedException e) {
+ FlowProgrammerAdapter.LOG.error("Interrupted while processing flow", e);
+ } catch (ExecutionException e) {
+ FlowProgrammerAdapter.LOG.error("Failed to process flow", e);
+ }
+
+ return new Status(StatusCode.INTERNALERROR);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Map<Flow,UUID> getCache() {
+ final IClusterGlobalServices cgs = getClusterGlobalServices();
+ if (cgs == null) {
+ return new ConcurrentHashMap<Flow, UUID>();
+ }
+
+ Map<Flow, UUID> cache = (Map<Flow, UUID>) cgs.getCache(FlowProgrammerAdapter.CACHE_NAME);
+ if (cache != null) {
+ return cache;
+ }
+
+ try {
+ return (Map<Flow, UUID>) cgs.createCache(CACHE_NAME, EnumSet.of(cacheMode.TRANSACTIONAL));
+ } catch (CacheExistException e) {
+ return (Map<Flow, UUID>) cgs.getCache(CACHE_NAME);
+ } catch (CacheConfigException e) {
+ throw new IllegalStateException("Unexpected cache configuration problem", e);
+ }
+ }
+
+}
+++ /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.sal.compatibility
-
-import java.util.Map
-import java.util.UUID
-import java.util.concurrent.ExecutionException
-import java.util.concurrent.ConcurrentHashMap
-import java.util.concurrent.Future
-import java.util.EnumSet
-import org.opendaylight.controller.sal.core.Node
-import org.opendaylight.controller.sal.flowprogrammer.Flow
-import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService
-import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService
-import org.opendaylight.controller.sal.utils.Status
-import org.opendaylight.controller.sal.utils.StatusCode
-import org.opendaylight.controller.clustering.services.CacheExistException
-import org.opendaylight.controller.clustering.services.IClusterGlobalServices
-import org.opendaylight.controller.clustering.services.IClusterServices
-
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.slf4j.LoggerFactory
-
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
-
-
-import static extension org.opendaylight.controller.sal.compatibility.MDFlowMapping.*
-
-import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import static extension org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.*
-
-class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener {
-
- private static val LOG = LoggerFactory.getLogger(FlowProgrammerAdapter);
- private static val CACHE_NAME = "flowprogrammeradapter.flowtoid";
-
- @Property
- private SalFlowService delegate;
-
- @Property
- private DataBrokerService dataBrokerService;
-
- @Property
- private IPluginOutFlowProgrammerService flowProgrammerPublisher;
-
- @Property
- private IClusterGlobalServices clusterGlobalServices;
-
-
- @Property
- private Map<Flow, UUID> flowToFlowId = new ConcurrentHashMap<Flow, UUID>();
-
-
- override addFlow(Node node, Flow flow) {
- return toFutureStatus(internalAddFlowAsync(node,flow,0));
- }
-
- override modifyFlow(Node node, Flow oldFlow, Flow newFlow) {
- return toFutureStatus(internalModifyFlowAsync(node, oldFlow,newFlow,0));
- }
-
- override removeFlow(Node node, Flow flow) {
- return toFutureStatus(internalRemoveFlowAsync(node, flow,0));
- }
-
- override addFlowAsync(Node node, Flow flow, long rid) {
- internalAddFlowAsync(node, flow, rid);
- return toStatus(true);
- }
-
- override modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) {
- internalModifyFlowAsync(node, oldFlow, newFlow, rid);
- return toStatus(true);
- }
-
- override removeFlowAsync(Node node, Flow flow, long rid) {
- internalRemoveFlowAsync(node, flow, rid);
- return toStatus(true);
- }
-
- override removeAllFlows(Node node) {
- // I know this looks like a copout... but its exactly what the legacy OFplugin did
- return new Status(StatusCode.SUCCESS);
- }
-
- override syncSendBarrierMessage(Node node) {
-
- // FIXME: Update YANG model
- return null;
- }
-
- override asyncSendBarrierMessage(Node node) {
-
- // FIXME: Update YANG model
- return null;
- }
-
- private static def toStatus(boolean successful) {
- if (successful) {
- return new Status(StatusCode.SUCCESS);
- } else {
- return new Status(StatusCode.INTERNALERROR);
- }
- }
-
- public static def toStatus(RpcResult<?> result) {
- return toStatus(result.isSuccessful());
- }
-
- private static dispatch def Status processException(InterruptedException e) {
- LOG.error("Interruption occured during processing flow",e);
- return new Status(StatusCode.INTERNALERROR);
- }
-
- private static dispatch def Status processException(ExecutionException e) {
- LOG.error("Execution exception occured during processing flow",e.cause);
- return new Status(StatusCode.INTERNALERROR);
- }
-
- private static dispatch def Status processException(Exception e) {
- throw new RuntimeException(e);
- }
-
- override onFlowAdded(FlowAdded notification) {
- // NOOP : Not supported by AD SAL
- }
-
- override onFlowRemoved(FlowRemoved notification) {
- if(notification != null && notification.node != null) {
- val adNode = notification.node.toADNode
- if(adNode != null) {
- flowProgrammerPublisher.flowRemoved(adNode,notification.toFlow(adNode));
- }
- }
- }
-
- override onFlowUpdated(FlowUpdated notification) {
- // NOOP : Not supported by AD SAL
- }
-
- override onSwitchFlowRemoved(SwitchFlowRemoved notification) {
- // NOOP : Not supported by AD SAL
- }
-
- override onNodeErrorNotification(NodeErrorNotification notification) {
- // NOOP : Not supported by AD SAL
- }
-
- override onNodeExperimenterErrorNotification(
- NodeExperimenterErrorNotification notification) {
- // NOOP : Not supported by AD SAL
- }
-
- private def Future<RpcResult<TransactionStatus>> writeFlowAsync(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow flow, NodeKey nodeKey){
- val modification = this._dataBrokerService.beginTransaction();
- val flowPath = InstanceIdentifier.builder(Nodes)
- .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, nodeKey)
- .augmentation(FlowCapableNode)
- .child(Table, new TableKey(flow.getTableId()))
- .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id))
- .build;
- modification.putConfigurationData(flowPath, flow);
- return modification.commit();
- }
-
- private def Future<RpcResult<TransactionStatus>> internalAddFlowAsync(Node node, Flow flow, long rid){
- var flowId = getCache().get(flow);
- if(flowId != null) {
- removeFlow(node, flow);
- return internalAddFlowAsync(node, flow, rid);
- }
-
- flowId = UUID.randomUUID();
- getCache().put(flow, flowId);
-
- return writeFlowAsync(flow.toMDFlow(flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
- }
-
- private def Future<RpcResult<TransactionStatus>> internalModifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) {
- var flowId = getCache().remove(oldFlow);
- if(flowId == null){
- LOG.error("oldFlow not found in cache : " + oldFlow.hashCode);
- flowId = UUID.randomUUID();
- getCache().put(oldFlow, flowId);
- }
-
- getCache().put(newFlow, flowId);
- return writeFlowAsync(newFlow.toMDFlow(flowId.toString()), new NodeKey(new NodeId(node.getNodeIDString())));
- }
-
-
- private def Future<RpcResult<TransactionStatus>> internalRemoveFlowAsync(Node node, Flow adflow, long rid){
- val flowId = getCache().remove(adflow);
- if(flowId == null){
- //throw new IllegalArgumentException("adflow not found in cache : " + adflow.hashCode);
- LOG.error("adflow not found in cache : " + adflow.hashCode);
- return null;
- }
- val flow = adflow.toMDFlow(flowId.toString());
- val modification = this._dataBrokerService.beginTransaction();
- val flowPath = InstanceIdentifier.builder(Nodes)
- .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, new NodeKey(new NodeId(node.getNodeIDString())))
- .augmentation(FlowCapableNode)
- .child(Table, new TableKey(flow.getTableId()))
- .child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, new FlowKey(flow.id))
- .build;
- modification.removeConfigurationData(flowPath);
- return modification.commit();
- }
-
- private def toFutureStatus(Future<RpcResult<TransactionStatus>> future){
- if(future == null){
- return toStatus(true);
- }
-
- try {
- val result = future.get();
- return toStatus(result);
- } catch (InterruptedException e) {
- return processException(e);
- } catch (ExecutionException e) {
- return processException(e);
- } catch (Exception e){
- processException(e);
- }
- return toStatus(false);
- }
-
- private def Map<Flow, UUID> getCache(){
- if(clusterGlobalServices == null){
- return new ConcurrentHashMap<Flow, UUID>();
- }
-
- var cache = clusterGlobalServices.getCache(CACHE_NAME);
-
- if(cache == null) {
- try {
- cache = clusterGlobalServices.createCache(CACHE_NAME, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
- } catch (CacheExistException e) {
- cache = clusterGlobalServices.getCache(CACHE_NAME);
- }
- }
- return cache as Map<Flow, UUID>;
-
- }
-
-}
import java.util.ArrayList
import java.util.Collections
import java.util.List
+import java.util.Map
import java.util.Set
-import java.util.ArrayList;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ConcurrentHashMap
+import java.util.concurrent.CopyOnWriteArrayList
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
import org.opendaylight.controller.sal.binding.api.data.DataProviderService
import org.opendaylight.controller.sal.core.Edge
import static extension org.opendaylight.controller.sal.common.util.Arguments.*
import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import java.util.concurrent.ConcurrentHashMap
-import java.util.Map
-import java.util.HashMap
class InventoryAndReadAdapter implements IPluginInReadService,
IPluginInInventoryService,
*/
package org.opendaylight.controller.sal.compatibility;
+import java.math.BigInteger;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
return new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, aDNodeId);
}
- public static NodeId toNodeId(final InstanceIdentifier<? extends Object> node) {
- Preconditions.<InstanceIdentifier<? extends Object>>checkNotNull(node);
- List<PathArgument> path = node.getPath();
- Preconditions.<List<PathArgument>>checkNotNull(path);
- int size = path.size();
- Preconditions.checkArgument(size >= 2);
- final PathArgument arg = path.get(1);
- final IdentifiableItem item = Arguments.<IdentifiableItem>checkInstanceOf(arg, IdentifiableItem.class);
- Identifier<?> key = item.getKey();
- final NodeKey nodeKey = Arguments.<NodeKey>checkInstanceOf(key, NodeKey.class);
- return nodeKey.getId();
+ public static NodeId toNodeId(final InstanceIdentifier<?> id) {
+ final NodeKey key = id.firstKeyOf(Node.class, NodeKey.class);
+ Preconditions.checkArgument(key != null, "No node identifier found in %s", id);
+ return key.getId();
}
public static String toADNodeId(final NodeId nodeId) {
- Preconditions.<NodeId>checkNotNull(nodeId);
return nodeId.getValue();
}
public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorRef source) throws ConstructionException {
- Preconditions.<NodeConnectorRef>checkNotNull(source);
- final InstanceIdentifier<?> path = Preconditions.<InstanceIdentifier<? extends Object>>checkNotNull(source.getValue());
- Preconditions.checkArgument(path.getPath().size() >= 3);
- final PathArgument arg = path.getPath().get(2);
- final IdentifiableItem item = Arguments.<IdentifiableItem>checkInstanceOf(arg,IdentifiableItem.class);
- final NodeConnectorKey connectorKey = Arguments.<NodeConnectorKey>checkInstanceOf(item.getKey(), NodeConnectorKey.class);
- return NodeMapping.toADNodeConnector(connectorKey.getId(), NodeMapping.toNodeId(path));
+ final InstanceIdentifier<?> id = Preconditions.checkNotNull(source.getValue());
+ final NodeConnectorKey key = id.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
+ return NodeMapping.toADNodeConnector(key.getId(), NodeMapping.toNodeId(id));
}
public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorId ncid, final NodeId nid) throws ConstructionException {
public static NodeConnectorRef toNodeConnectorRef(final org.opendaylight.controller.sal.core.NodeConnector nodeConnector) {
final NodeRef node = NodeMapping.toNodeRef(nodeConnector.getNode());
+ @SuppressWarnings("unchecked")
final InstanceIdentifier<Node> nodePath = ((InstanceIdentifier<Node>) node.getValue());
NodeConnectorId nodeConnectorId = null;
public static MacAddress toADMacAddress(final NodeId id) {
final String nodeId = id.getValue().replaceAll("openflow:", "");
- long lNodeId = Long.parseLong(nodeId);
- lNodeId = Long.valueOf(lNodeId).longValue();
+ BigInteger nodeIdRaw = new BigInteger(nodeId);
+ long lNodeId = nodeIdRaw.longValue();
byte[] bytesFromDpid = ToSalConversionsUtils.bytesFromDpid(lNodeId);
return new MacAddress(bytesFromDpid);
}
--- /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.sal.compatibility;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.NotificationService;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.compatibility.adsal.DataPacketServiceAdapter;
+import org.opendaylight.controller.sal.compatibility.topology.TopologyAdapter;
+import org.opendaylight.controller.sal.compatibility.topology.TopologyProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+import com.google.common.base.Preconditions;
+
+class SalCompatibilityProvider implements BindingAwareProvider {
+ private final ComponentActivator activator;
+
+ public SalCompatibilityProvider(final ComponentActivator cmpAct) {
+ this.activator = Preconditions.checkNotNull(cmpAct);
+ }
+
+ @Override
+ public Collection<? extends ProviderFunctionality> getFunctionality() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Collection<? extends RpcService> getImplementations() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void onSessionInitialized(final ConsumerContext session) {
+ // No-op
+ }
+
+ @Override
+ public void onSessionInitiated(final ProviderContext session) {
+ final NotificationService subscribe = session.getSALService(NotificationService.class);
+
+ final FlowProgrammerAdapter flow = activator.getFlow();
+ flow.setDelegate(session.getRpcService(SalFlowService.class));
+ flow.setDataBrokerService(session.getSALService(DataBrokerService.class));
+ // FIXME: remember registration for clean shutdown
+ subscribe.registerNotificationListener(flow);
+
+ final InventoryAndReadAdapter inv = activator.getInventory();
+ inv.setDataService(session.getSALService(DataBrokerService.class));
+ inv.setFlowStatisticsService(session.getRpcService(OpendaylightFlowStatisticsService.class));
+ inv.setFlowTableStatisticsService(session.getRpcService(OpendaylightFlowTableStatisticsService.class));
+ inv.setNodeConnectorStatisticsService(session.getRpcService(OpendaylightPortStatisticsService.class));
+ inv.setTopologyDiscovery(session.getRpcService(FlowTopologyDiscoveryService.class));
+ inv.setDataProviderService(session.getSALService(DataProviderService.class));
+ // FIXME: remember registration for clean shutdown
+ subscribe.registerNotificationListener(inv);
+
+ final DataPacketServiceAdapter dps = activator.getDataPacketService();
+ dps.setDelegate(session.getRpcService(PacketProcessingService.class));
+
+ final TopologyAdapter topo = activator.getTopology();
+ topo.setDataService(session.getSALService(DataProviderService.class));
+
+ final TopologyProvider tpp = activator.getTpProvider();
+ tpp.setDataService(session.getSALService(DataProviderService.class));
+
+ inv.startAdapter();
+ tpp.startAdapter();
+
+ subscribe.registerNotificationListener(activator.getDataPacket());
+ }
+}
--- /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.sal.compatibility.topology;
+
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.topology.IPluginInTopologyService;
+import org.opendaylight.controller.sal.topology.IPluginOutTopologyService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+public class TopologyAdapter implements IPluginInTopologyService {
+ private final InstanceIdentifier<Topology> topology = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId("flow:1"))).toInstance();
+
+ // FIXME: seems to be unused
+ private IPluginOutTopologyService topologyPublisher;
+ private DataProviderService dataService;
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = Preconditions.checkNotNull(dataService);
+ }
+
+ @Override
+ public void sollicitRefresh() {
+ final TypeSafeDataReader reader = TypeSafeDataReader.forReader(dataService);
+ final Topology t = reader.readOperationalData(topology);
+ topologyPublisher.edgeUpdate(TopologyMapping.toADEdgeUpdates(t, reader));
+ }
+}
+++ /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.sal.compatibility.topology
-
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.topology.IPluginInTopologyService
-import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-
-import static extension org.opendaylight.controller.sal.compatibility.topology.TopologyMapping.*
-
-class TopologyAdapter implements IPluginInTopologyService {
-
- @Property
- DataProviderService dataService;
-
- @Property
- IPluginOutTopologyService topologyPublisher;
-
- override sollicitRefresh() {
- val path = InstanceIdentifier.builder(NetworkTopology).child(Topology,new TopologyKey(new TopologyId("flow:1"))).toInstance;
- val reader = TypeSafeDataReader.forReader(dataService)
- val topology = reader.readOperationalData(path)
- topologyPublisher.edgeUpdate(topology.toADEdgeUpdates(reader))
- }
-
-}
--- /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.sal.compatibility.topology;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
+import org.opendaylight.controller.sal.compatibility.NodeMapping;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Edge;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.UpdateType;
+import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+
+public final class TopologyMapping {
+ private static final Logger LOG = LoggerFactory.getLogger(TopologyMapping.class);
+
+ private TopologyMapping() {
+ throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
+ }
+
+ public static List<TopoEdgeUpdate> toADEdgeUpdates(final Topology topology,final TypeSafeDataReader reader) {
+ final List<TopoEdgeUpdate> result = new CopyOnWriteArrayList<>();
+ return FluentIterable.from(topology.getLink()).transform(
+ new Function<Link, TopoEdgeUpdate>() {
+ @Override
+ public TopoEdgeUpdate apply(final Link input) {
+ try {
+ return toTopoEdgeUpdate(toAdEdge(input, topology), reader);
+ } catch (ConstructionException e) {
+ throw new IllegalArgumentException(String.format("Failed to construct edge update for {}", input), e);
+ }
+ }}
+ ).copyInto(result);
+ }
+
+ public static Edge toAdEdge(final Link link, final Topology topology) throws ConstructionException {
+ final NodeConnector adSrc = toADNodeConnector(link.getSource().getSourceTp(), link.getSource().getSourceNode());
+ final NodeConnector adDst = toADNodeConnector(link.getDestination().getDestTp(), link.getDestination().getDestNode());
+ return new Edge(adSrc, adDst);
+ }
+
+ public static TopoEdgeUpdate toTopoEdgeUpdate(final Edge e, final TypeSafeDataReader reader) {
+ return toTopoEdgeUpdate(e, UpdateType.ADDED, reader);
+ }
+
+ public static TopoEdgeUpdate toTopoEdgeUpdate(final Edge e,final UpdateType type,final TypeSafeDataReader reader) {
+ return new TopoEdgeUpdate(e, toAdEdgeProperties(e, reader), type);
+ }
+
+ public static Set<Property> toAdEdgeProperties(final Edge e,final TypeSafeDataReader reader) {
+ final NodeConnectorRef ncref = NodeMapping.toNodeConnectorRef(e.getTailNodeConnector());
+ if(ncref == null) {
+ LOG.debug("Edge {} ncref {}",e,ncref);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector> ncInstanceId =
+ (InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector>) ncref.getValue();
+ if(ncInstanceId == null) {
+ LOG.debug("Edge {} ncref {}",e,ncref);
+ return null;
+ }
+
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc = reader.readOperationalData(ncInstanceId);
+ if(nc == null) {
+ return null;
+ }
+ return NodeMapping.toADNodeConnectorProperties(nc);
+ }
+
+ public static String toADNodeId(final NodeId nodeId) {
+ return nodeId.getValue();
+ }
+
+ public static NodeConnector toADNodeConnector(final TpId source, final NodeId nodeId) throws ConstructionException {
+ checkNotNull(source);
+ return new NodeConnector(NodeMapping.MD_SAL_TYPE, toADNodeConnectorId(source), toADNode(nodeId));
+ }
+
+ public static String toADNodeConnectorId(final TpId nodeConnectorId) {
+ return nodeConnectorId.getValue();
+ }
+
+ public static Node toADNode(final NodeId nodeId) throws ConstructionException {
+ checkNotNull(nodeId);
+ return new Node(NodeMapping.MD_SAL_TYPE, toADNodeId(nodeId));
+ }
+}
+++ /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.sal.compatibility.topology
-
-import com.google.common.collect.FluentIterable
-import java.util.Collections
-import java.util.List
-import java.util.concurrent.CopyOnWriteArrayList
-import org.opendaylight.controller.sal.core.ConstructionException
-import org.opendaylight.controller.sal.core.Edge
-import org.opendaylight.controller.sal.core.Node
-import org.opendaylight.controller.sal.core.NodeConnector
-import org.opendaylight.controller.sal.core.UpdateType
-import org.opendaylight.controller.sal.topology.TopoEdgeUpdate
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link
-
-import static com.google.common.base.Preconditions.*
-import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
-import org.slf4j.LoggerFactory
-
-class TopologyMapping {
- private static val LOG = LoggerFactory.getLogger(TopologyMapping);
- private new() {
- throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
- }
-
- public static def toADEdgeUpdates(Topology topology,TypeSafeDataReader reader) {
- val List<TopoEdgeUpdate> result = new CopyOnWriteArrayList<TopoEdgeUpdate>()
- return FluentIterable.from(topology.link).transform[toAdEdge(topology).toTopoEdgeUpdate(reader)].copyInto(result)
- }
-
- public static def toAdEdge(Link link,Topology topology) {
- val adSrc = link.source.sourceTp.toADNodeConnector(link.source.sourceNode)
- val adDst = link.destination.destTp.toADNodeConnector(link.destination.destNode)
- return new Edge(adSrc,adDst);
- }
-
- public static def toTopoEdgeUpdate(Edge e,TypeSafeDataReader reader) {
- return toTopoEdgeUpdate(e,UpdateType.ADDED,reader)
- }
-
- public static def toTopoEdgeUpdate(Edge e,UpdateType type,TypeSafeDataReader reader) {
- return new TopoEdgeUpdate(e,e.toAdEdgeProperties(reader),type)
- }
-
- public static def toAdEdgeProperties(Edge e,TypeSafeDataReader reader) {
- val ncref = e.tailNodeConnector.toNodeConnectorRef
- if(ncref == null) {
- LOG.debug("Edge {} ncref {}",e,ncref)
- return null;
- }
- val ncInstanceId = (ncref.value as InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector>)
- if(ncInstanceId == null) {
- LOG.debug("Edge {} ncref {}",e,ncref)
- return null;
- }
- val nc = reader.readOperationalData(ncInstanceId)
- if(nc == null) {
- return null;
- }
- return nc.toADNodeConnectorProperties
- }
-
- public static def toADNodeId(NodeId nodeId) {
- checkNotNull(nodeId);
- return nodeId.value
- }
- public static def toADNodeConnector(TpId source,NodeId nodeId) throws ConstructionException {
- checkNotNull(source);
- return new NodeConnector(MD_SAL_TYPE,source.toADNodeConnectorId,nodeId.toADNode)
- }
-
- public static def toADNodeConnectorId(TpId nodeConnectorId) {
- return nodeConnectorId.value
- }
-
- public static def toADNode(NodeId nodeId) {
- checkNotNull(nodeId);
- return new Node(MD_SAL_TYPE,nodeId.toADNodeId);
- }
-}
--- /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.sal.compatibility.topology;
+
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.topology.IPluginOutTopologyService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class TopologyProvider implements AutoCloseable{
+ private static final Logger LOG = LoggerFactory.getLogger(TopologyProvider.class);
+ private static final InstanceIdentifier<Link> PATH = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class ,new TopologyKey(new TopologyId("flow:1")))
+ .child(Link.class)
+ .toInstance();
+ private TopologyCommitHandler commitHandler;
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private IPluginOutTopologyService topologyPublisher;
+ private DataProviderService dataService;
+
+ public void startAdapter() {
+ if(dataService == null){
+ LOG.error("dataService not set");
+ return;
+ }
+ commitHandler = new TopologyCommitHandler(dataService,topologyPublisher);
+ listenerRegistration = dataService.registerDataChangeListener(PATH, commitHandler);
+ LOG.info("TopologyProvider started");
+ }
+
+ @Override
+ public void close() {
+ if (listenerRegistration != null) {
+ listenerRegistration.close();
+ }
+ }
+
+ void setTopologyPublisher(final IPluginOutTopologyService topologyPublisher) {
+ this.topologyPublisher = topologyPublisher;
+ if (commitHandler != null) {
+ commitHandler.setTopologyPublisher(topologyPublisher);
+ }
+ }
+
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = Preconditions.checkNotNull(dataService);
+ }
+}
+++ /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.sal.compatibility.topology
-
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.controller.sal.topology.IPluginOutTopologyService
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link
-import org.slf4j.LoggerFactory
-import org.opendaylight.yangtools.concepts.ListenerRegistration
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener
-
-class TopologyProvider implements AutoCloseable{
- static val LOG = LoggerFactory.getLogger(TopologyProvider);
- TopologyCommitHandler commitHandler
-
- @Property
- IPluginOutTopologyService topologyPublisher;
-
- @Property
- DataProviderService dataService;
-
- ListenerRegistration<DataChangeListener> listenerRegistration
-
-
- def void start() {
-
- }
- def void startAdapter() {
- if(dataService == null){
- LOG.error("dataService not set");
- return;
- }
- commitHandler = new TopologyCommitHandler(dataService,topologyPublisher);
- val InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder(NetworkTopology)
- .child(Topology,new TopologyKey(new TopologyId("flow:1")))
- .child(Link)
- .toInstance();
- listenerRegistration = dataService.registerDataChangeListener(path,commitHandler);
- LOG.info("TopologyProvider started")
- }
-
- override close() throws Exception {
- listenerRegistration.close
- }
-
- def setTopologyPublisher(IPluginOutTopologyService topologyPublisher) {
- _topologyPublisher = topologyPublisher;
- if(commitHandler != null){
- commitHandler.setTopologyPublisher(topologyPublisher);
- }
- }
-
-}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.compatibility.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.sal.compatibility.NodeMapping;
+import org.opendaylight.controller.sal.core.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+/**
+ * test of {@link NodeMapping} utility class
+ */
+public class NodeMappingTest {
+
+ /**
+ * Test method for
+ * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#toADMacAddress(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId)}
+ * .
+ */
+ @Test
+ public void testToADMacAddress() {
+ NodeId[] nodeIds = new NodeId[] {
+ // 0x0000|0000 0000002a (answer to the ultimate question of life, universe and everything)
+ new NodeId("42"),
+ // 0x7fff|ffff ffffffff (max long -> 2**63 - 1)
+ new NodeId("9223372036854775807"),
+ // 0x7fff|7fff ffffffff
+ new NodeId("9223231299366420479"),
+ // 0x8fff|7fff ffffffff (more than biggest positive long)
+ new NodeId("10376152803973267455"),
+ // 0xca13|764a e9ace65a (BUG-770)
+ new NodeId("14561112084339025498")
+ };
+
+ byte[][] expectedMacs = new byte[][] {
+ {0, 0, 0, 0, 0, 0x2a},
+ {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff},
+ {(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff},
+ {(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff},
+ {(byte) 0x76, (byte) 0x4a, (byte) 0xe9, (byte) 0xac, (byte) 0xe6, (byte) 0x5a}
+ };
+
+ Assert.assertEquals(expectedMacs.length, nodeIds.length);
+
+ for (int i = 0; i < expectedMacs.length; i++) {
+ NodeId nodeId = nodeIds[i];
+ MacAddress mac = NodeMapping.toADMacAddress(nodeId);
+ Assert.assertArrayEquals(expectedMacs[i], mac.getMacAddress());
+ }
+ }
+
+}
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
+import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
import java.util.List;
import org.junit.Test;
-import org.opendaylight.controller.sal.action.*;
+import org.opendaylight.controller.sal.action.Action;
+import org.opendaylight.controller.sal.action.Flood;
+import org.opendaylight.controller.sal.action.FloodAll;
+import org.opendaylight.controller.sal.action.HwPath;
+import org.opendaylight.controller.sal.action.Loopback;
+import org.opendaylight.controller.sal.action.PopVlan;
+import org.opendaylight.controller.sal.action.PushVlan;
+import org.opendaylight.controller.sal.action.SetDlDst;
+import org.opendaylight.controller.sal.action.SetDlSrc;
+import org.opendaylight.controller.sal.action.SetDlType;
+import org.opendaylight.controller.sal.action.SetNextHop;
+import org.opendaylight.controller.sal.action.SetNwDst;
+import org.opendaylight.controller.sal.action.SetNwSrc;
+import org.opendaylight.controller.sal.action.SetNwTos;
+import org.opendaylight.controller.sal.action.SetTpDst;
+import org.opendaylight.controller.sal.action.SetTpSrc;
+import org.opendaylight.controller.sal.action.SetVlanCfi;
+import org.opendaylight.controller.sal.action.SetVlanId;
+import org.opendaylight.controller.sal.action.SetVlanPcp;
+import org.opendaylight.controller.sal.action.SwPath;
import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
import org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanAction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.FloodAllActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.HwPathActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.LoopbackActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlTypeActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNextHopActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwTosActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanCfiActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SwPathActionCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
if (layer4Match instanceof SctpMatch) {
assertEquals("Sctp source port is incorrect.", 0xffff, (int) ((SctpMatch) layer4Match)
.getSctpSourcePort().getValue());
- assertEquals("Sctp dest port is incorrect.", (int) 0xfffe, (int) ((SctpMatch) layer4Match)
+ assertEquals("Sctp dest port is incorrect.", 0xfffe, (int) ((SctpMatch) layer4Match)
.getSctpDestinationPort().getValue());
sctpFound = true;
}
assertEquals("Wrong protocol", TCP, match.getIpMatch().getIpProtocol().byteValue());
layer4Match = match.getLayer4Match();
if (layer4Match instanceof TcpMatch) {
- assertEquals("Tcp source port is incorrect.", (int) 0xabcd, (int) ((TcpMatch) layer4Match)
+ assertEquals("Tcp source port is incorrect.", 0xabcd, (int) ((TcpMatch) layer4Match)
.getTcpSourcePort().getValue());
- assertEquals("Tcp dest port is incorrect.", (int) 0xdcba, (int) ((TcpMatch) layer4Match)
+ assertEquals("Tcp dest port is incorrect.", 0xdcba, (int) ((TcpMatch) layer4Match)
.getTcpDestinationPort().getValue());
sctpFound = true;
}
assertEquals("Wrong protocol", UDP, match.getIpMatch().getIpProtocol().byteValue());
layer4Match = match.getLayer4Match();
if (layer4Match instanceof UdpMatch) {
- assertEquals("Udp source port is incorrect.", (int) 0xcdef, (int) ((UdpMatch) layer4Match)
+ assertEquals("Udp source port is incorrect.", 0xcdef, (int) ((UdpMatch) layer4Match)
.getUdpSourcePort().getValue());
- assertEquals("Udp dest port is incorrect.", (int) 0xfedc, (int) ((UdpMatch) layer4Match)
+ assertEquals("Udp dest port is incorrect.", 0xfedc, (int) ((UdpMatch) layer4Match)
.getUdpDestinationPort().getValue());
sctpFound = true;
}
assertEquals("Wrong value of vlad ID in PushVlanAction.", (Integer) 4095,
((PushVlanActionCase) innerAction).getPushVlanAction().getVlanId().getValue());
} else if (innerAction instanceof SetDlDstActionCase) {
- assertEquals("Wrong MAC destination address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
+ assertEquals("Wrong MAC destination address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
((SetDlDstActionCase) innerAction).getSetDlDstAction().getAddress().getValue());
} else if (innerAction instanceof SetDlSrcActionCase) {
- assertEquals("Wrong MAC source address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
+ assertEquals("Wrong MAC source address in SetDlDstAction.", "ff:ee:dd:cc:bb:aa",
((SetDlSrcActionCase) innerAction).getSetDlSrcAction().getAddress().getValue());
} else if (innerAction instanceof SetDlTypeActionCase) {
- assertEquals("Wrong data link type in SetDlTypeAction.", (long) 513,
+ assertEquals("Wrong data link type in SetDlTypeAction.", 513,
(long) ((SetDlTypeActionCase) innerAction).getSetDlTypeAction().getDlType().getValue());
} else if (innerAction instanceof SetNextHopActionCase) {
Address address = ((SetNextHopActionCase) innerAction).getSetNextHopAction().getAddress();
<!-- Clustering -->
<module>remoterpc-routingtable/implementation</module>
<module>sal-remoterpc-connector/implementation</module>
- <!--module>clustered-data-store/implementation</module>
- -->
<!-- Documentation -->
<module>sal-rest-docgen</module>
<modules>
<module>sal-binding-it</module>
<module>sal-binding-dom-it</module>
- <!--module>clustered-data-store/integrationtest</module -->
- <!--module>zeromq-routingtable/integrationtest</module -->
- <!--module>sal-remoterpc-connector/integrationtest</module -->
- <!--module>test/sal-rest-connector-it</modulei -->
</modules>
</profile>
</profiles>
import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
public final class RuntimeMappingModule extends
org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractRuntimeMappingModule {
+ private static final Logger LOG = LoggerFactory.getLogger(RuntimeMappingModule.class);
+
private BundleContext bundleContext;
public RuntimeMappingModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
}
@Override
- public void close() throws Exception {
+ public void close() {
if(delegate != null) {
delegate = null;
- bundleContext.ungetService(reference);
+
+ try {
+ bundleContext.ungetService(reference);
+ } catch (IllegalStateException e) {
+ // Indicates the BundleContext is no longer valid which can happen normally on shutdown.
+ LOG.debug( "Error unregistering service", e );
+ }
+
bundleContext= null;
reference = null;
}
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
}
private static class BackwardsCompatibleConfigurationDataChangeInvoker implements BindingDataChangeListener, Delegator<DataChangeListener> {
-
-
- @SuppressWarnings("rawtypes")
private final org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<?,?> delegate;
public BackwardsCompatibleConfigurationDataChangeInvoker(final DataChangeListener listener) {
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.binding.codegen;
+
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+public final class RuntimeCodeSpecification {
+ public final static String DIRECT_PROXY_SUFFIX = "DirectProxy";
+ public final static String INVOKER_SUFFIX = "ListenerInvoker";
+ public final static String ROUTER_SUFFIX = "Router";
+
+ public final static String DELEGATE_FIELD = "_delegate";
+ public final static String ROUTING_TABLE_FIELD_PREFIX = "_routes_";
+
+ private RuntimeCodeSpecification() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ /**
+ * Returns a name for generated interface
+ */
+ private static String getGeneratedName(final Class<? extends Object> cls, final String suffix) {
+ return cls.getName() + "$$Broker$" + suffix;
+ }
+
+ public static String getInvokerName(final Class<? extends NotificationListener> listener) {
+ return getGeneratedName(listener, RuntimeCodeSpecification.INVOKER_SUFFIX);
+ }
+
+ /**
+ * Returns a name for DirectProxy implementation
+ */
+ public static String getDirectProxyName(final Class<? extends RpcService> base) {
+ return getGeneratedName(base, RuntimeCodeSpecification.DIRECT_PROXY_SUFFIX);
+ }
+
+ /**
+ * Returns a name for Router implementation
+ */
+ public static String getRouterName(final Class<? extends RpcService> base) {
+ return getGeneratedName(base, RuntimeCodeSpecification.ROUTER_SUFFIX);
+ }
+
+ /**
+ * Returns a field name for specified routing context
+ */
+ public static String getRoutingTableField(final Class<? extends BaseIdentity> routingContext) {
+ return "_routes_" + routingContext.getSimpleName();
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.codegen
-
-import org.opendaylight.yangtools.yang.binding.RpcService
-import org.opendaylight.yangtools.yang.binding.BaseIdentity
-import org.opendaylight.yangtools.yang.binding.NotificationListener
-
-/**
- *
- *
- */
-class RuntimeCodeSpecification {
-
- //public static val PACKAGE_PREFIX = "_gen.";
-
- public static val DIRECT_PROXY_SUFFIX = "DirectProxy";
- public static val ROUTER_SUFFIX = "Router";
- public static val INVOKER_SUFFIX = "ListenerInvoker";
-
- public static val DELEGATE_FIELD = "_delegate"
- public static val ROUTING_TABLE_FIELD_PREFIX = "_routes_"
-
- public static def getInvokerName(Class<? extends NotificationListener> listener) {
- getGeneratedName(listener, INVOKER_SUFFIX);
- }
-
- /**
- * Returns a name for DirectProxy implementation
- *
- *
- */
- public static def getDirectProxyName(Class<? extends RpcService> base) {
- getGeneratedName(base, DIRECT_PROXY_SUFFIX);
- }
-
- /**
- * Returns a name for Router implementation
- *
- */
- public static def getRouterName(Class<? extends RpcService> base) {
- getGeneratedName(base, ROUTER_SUFFIX);
- }
-
- /**
- * Returns a name for generated interface
- *
- */
- public static def getGeneratedName(Class<?> cls, String suffix) {
- '''«cls.name»$$Broker$«suffix»'''.toString()
- }
-
- /**
- * Returns a field name for specified routing context
- *
- */
- public static def getRoutingTableField(Class<? extends BaseIdentity> routingContext) {
- return '''_routes_«routingContext.simpleName»'''.toString;
- }
-}
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-
-
package org.opendaylight.controller.sal.binding.codegen;
import java.lang.reflect.Method;
+
import org.opendaylight.yangtools.yang.binding.Notification;
-@SuppressWarnings("all")
-public class YangtoolsMappingHelper {
- public static boolean isNotificationCallback(final Method it) {
- return it.getName().startsWith("on") && (it.getParameterTypes().length == 1) &&
- Notification.class.isAssignableFrom(it.getParameterTypes()[0]);
- }
+public final class YangtoolsMappingHelper {
+ private YangtoolsMappingHelper() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+ public static boolean isNotificationCallback(final Method it) {
+ return it.getName().startsWith("on") && (it.getParameterTypes().length == 1) &&
+ Notification.class.isAssignableFrom(it.getParameterTypes()[0]);
+ }
}
\ No newline at end of file
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;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
import org.slf4j.Logger;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.util.concurrent.Futures;
}
}
checkState(targetMethod != null, "Rpc method not found");
- Optional<Class<?>> outputClass = BindingReflections.resolveRpcOutputClass(targetMethod);
- Optional<Class<? extends DataContainer>> inputClass = BindingReflections
- .resolveRpcInputClass(targetMethod);
-
- RpcInvocationStrategy strategy = null;
- if (outputClass.isPresent()) {
- if (inputClass.isPresent()) {
- strategy = new DefaultInvocationStrategy(rpc, targetMethod, outputClass.get(), inputClass
- .get());
- } else {
- strategy = new NoInputInvocationStrategy(rpc, targetMethod, outputClass.get());
- }
- } else if (inputClass.isPresent()) {
- strategy = new NoOutputInvocationStrategy(rpc, targetMethod, inputClass.get());
- } else {
- strategy = new NoInputNoOutputInvocationStrategy(rpc, targetMethod);
- }
- return strategy;
+ return new RpcInvocationStrategy(rpc,targetMethod, mappingService, biRpcRegistry);
}
});
}
}
- private abstract class RpcInvocationStrategy {
-
- protected final Method targetMethod;
- protected final QName rpc;
-
- public RpcInvocationStrategy(final QName rpc, final Method targetMethod) {
- this.targetMethod = targetMethod;
- this.rpc = rpc;
- }
-
- public abstract Future<RpcResult<?>> forwardToDomBroker(DataObject input);
-
- public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
- throws Exception;
-
- public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput)
- throws Exception {
- return uncheckedInvoke(rpcService, domInput);
- }
- }
-
- private class DefaultInvocationStrategy extends RpcInvocationStrategy {
-
- @SuppressWarnings("rawtypes")
- private final WeakReference<Class> inputClass;
-
- @SuppressWarnings("rawtypes")
- private final WeakReference<Class> outputClass;
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public DefaultInvocationStrategy(final QName rpc, final Method targetMethod, final Class<?> outputClass,
- final Class<? extends DataContainer> inputClass) {
- super(rpc, targetMethod);
- this.outputClass = new WeakReference(outputClass);
- this.inputClass = new WeakReference(inputClass);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
- throws Exception {
- DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
- Future<RpcResult<?>> futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
- if (futureResult == null) {
- return Rpcs.getRpcResult(false);
- }
- RpcResult<?> bindingResult = futureResult.get();
- final Object resultObj = bindingResult.getResult();
- if (resultObj instanceof DataObject) {
- final CompositeNode output = mappingService.toDataDom((DataObject) resultObj);
- return Rpcs.getRpcResult(true, output, Collections.<RpcError> emptySet());
- }
- return Rpcs.getRpcResult(true);
- }
-
- @Override
- public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
- if (biRpcRegistry == null) {
- return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
- }
-
- CompositeNode xml = mappingService.toDataDom(input);
- CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-
- return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml),
- new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
- @Override
- public RpcResult<?> apply(final RpcResult<CompositeNode> input) {
- Object baResultValue = null;
- if (input.getResult() != null) {
- baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(),
- input.getResult());
- }
- return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors());
- }
- });
- }
- }
-
- private class NoInputInvocationStrategy extends RpcInvocationStrategy {
-
- @SuppressWarnings("rawtypes")
- private final WeakReference<Class> outputClass;
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public NoInputInvocationStrategy(final QName rpc, final Method targetMethod, final Class<?> outputClass) {
- super(rpc, targetMethod);
- this.outputClass = new WeakReference(outputClass);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
- throws Exception {
- Future<RpcResult<?>> futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService);
- if (futureResult == null) {
- return Rpcs.getRpcResult(false);
- }
- RpcResult<?> bindingResult = futureResult.get();
- final Object resultObj = bindingResult.getResult();
- if (resultObj instanceof DataObject) {
- final CompositeNode output = mappingService.toDataDom((DataObject) resultObj);
- return Rpcs.getRpcResult(true, output, Collections.<RpcError> emptySet());
- }
- return Rpcs.getRpcResult(true);
- }
-
- @Override
- public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
- if (biRpcRegistry != null) {
- CompositeNode xml = mappingService.toDataDom(input);
- CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
- return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml),
- new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
- @Override
- public RpcResult<?> apply(final RpcResult<CompositeNode> input) {
- Object baResultValue = null;
- if (input.getResult() != null) {
- baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(),
- input.getResult());
- }
- return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors());
- }
- });
- } else {
- return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
- }
- }
- }
-
- private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
-
- public NoInputNoOutputInvocationStrategy(final QName rpc, final Method targetMethod) {
- super(rpc, targetMethod);
- }
-
- @Override
- public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
- throws Exception {
- @SuppressWarnings("unchecked")
- Future<RpcResult<Void>> result = (Future<RpcResult<Void>>) targetMethod.invoke(rpcService);
- RpcResult<Void> bindingResult = result.get();
- return Rpcs.getRpcResult(bindingResult.isSuccessful(), bindingResult.getErrors());
- }
-
- @Override
- public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
- return Futures.immediateFuture(null);
- }
- }
-
- private class NoOutputInvocationStrategy extends RpcInvocationStrategy {
-
- @SuppressWarnings("rawtypes")
- private final WeakReference<Class> inputClass;
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public NoOutputInvocationStrategy(final QName rpc, final Method targetMethod,
- final Class<? extends DataContainer> inputClass) {
- super(rpc, targetMethod);
- this.inputClass = new WeakReference(inputClass);
- }
-
- @Override
- public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput)
- throws Exception {
- DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
- Future<RpcResult<?>> result = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
- if (result == null) {
- return Rpcs.getRpcResult(false);
- }
- RpcResult<?> bindingResult = result.get();
- return Rpcs.getRpcResult(true);
- }
-
- @Override
- public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
- if (biRpcRegistry == null) {
- return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
- }
-
- CompositeNode xml = mappingService.toDataDom(input);
- CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-
- return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml),
- new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
- @Override
- public RpcResult<?> apply(final RpcResult<CompositeNode> input) {
- return Rpcs.<Void> getRpcResult(input.isSuccessful(), null, input.getErrors());
- }
- });
- }
- }
-
public boolean isRpcForwarding() {
return rpcForwarding;
}
--- /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.binding.impl.connect.dom;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+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.Node;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/*
+ * RPC's can have both input, output, one or the other, or neither.
+ *
+ * This class handles the permutations and provides two means of invocation:
+ * 1. forwardToDomBroker
+ * 2.
+ *
+ * Weak References to the input and output classes are used to allow these classes to
+ * be from another OSGi bundle/class loader which may come and go.
+ *
+ */
+public class RpcInvocationStrategy {
+
+ private final BindingIndependentMappingService mappingService;
+ private final RpcProvisionRegistry biRpcRegistry;
+ protected final Method targetMethod;
+ protected final QName rpc;
+
+ @SuppressWarnings("rawtypes")
+ private final WeakReference<Class> inputClass;
+
+ @SuppressWarnings("rawtypes")
+ private final WeakReference<Class> outputClass;
+
+ @SuppressWarnings({ "rawtypes" })
+ public RpcInvocationStrategy(final QName rpc,
+ final Method targetMethod,
+ final BindingIndependentMappingService mappingService,
+ final RpcProvisionRegistry biRpcRegistry ) {
+
+ this.targetMethod = targetMethod;
+ this.rpc = rpc;
+
+ Optional<Class<?>> outputClassOption = BindingReflections.resolveRpcOutputClass(targetMethod);
+ Optional<Class<? extends DataContainer>> inputClassOption = BindingReflections.resolveRpcInputClass(targetMethod);
+
+ if ( outputClassOption != null && outputClassOption.isPresent() ) {
+ this.outputClass = new WeakReference(outputClassOption.get() ) ;
+ } else {
+ this.outputClass = null ;
+ }
+ if ( inputClassOption != null && inputClassOption.isPresent() ) {
+ this.inputClass = new WeakReference(inputClassOption.get() ) ;
+ } else {
+ this.inputClass = null ;
+ }
+
+ this.mappingService = mappingService;
+ this.biRpcRegistry = biRpcRegistry;
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
+
+ if(biRpcRegistry == null) {
+ return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
+ }
+
+ CompositeNode inputXml = null;
+ if( input != null ) {
+ CompositeNode xml = mappingService.toDataDom(input);
+ inputXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
+ } else {
+ inputXml = ImmutableCompositeNode.create( rpc, Collections.<Node<?>>emptyList() );
+ }
+
+ Function<RpcResult<CompositeNode>, RpcResult<?>> transformationFunction =
+ new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
+ @Override
+ public RpcResult<?> apply(RpcResult<CompositeNode> result) {
+
+ Object output = null;
+
+ if( getOutputClass() != null ) {
+ if (result.getResult() != null) {
+ output = mappingService.dataObjectFromDataDom(getOutputClass().get(),
+ result.getResult());
+ }
+ }
+
+ return Rpcs.getRpcResult(result.isSuccessful(), output, result.getErrors());
+ }
+ };
+
+ return Futures.transform(biRpcRegistry.invokeRpc(rpc, inputXml), transformationFunction);
+ }
+
+ @SuppressWarnings("unchecked")
+ private RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+
+ Future<RpcResult<?>> futureResult = null;
+
+ if( inputClass != null ){
+ DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
+ futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
+
+ } else {
+ futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService);
+ }
+
+ if (futureResult == null) {
+ return Rpcs.getRpcResult(false);
+ }
+
+ RpcResult<?> bindingResult = futureResult.get();
+
+ Collection<RpcError> errors = bindingResult.getErrors();
+ if( errors == null ) {
+ errors = Collections.<RpcError>emptySet();
+ }
+
+ final Object resultObj = bindingResult.getResult();
+ CompositeNode output = null;
+ if (resultObj instanceof DataObject) {
+ output = mappingService.toDataDom((DataObject)resultObj);
+ }
+ return Rpcs.getRpcResult( bindingResult.isSuccessful(), output, errors);
+ }
+
+ public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+ return uncheckedInvoke(rpcService, domInput);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public WeakReference<Class> getOutputClass() {
+ return outputClass;
+ }
+}
--- /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.binding.impl.connect.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+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.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class RpcInvocationStrategyTest {
+
+ @Mock
+ private BindingIndependentMappingService mockMappingService;
+ @Mock
+ private RpcProvisionRegistry mockbiRpcRegistry;
+
+ private RpcInvocationStrategy rpcInvocationStrategy;
+ private ListenableFuture<RpcResult<DataObject>> futureDataObj;
+ private ListenableFuture<RpcResult<CompositeNode>> futureCompNode;
+ private final RpcError rpcError = mock(RpcError.class);
+ private final Collection<RpcError> errors = new ArrayList<RpcError>();
+
+ private final CompositeNode inputInvokeOn = mock(CompositeNode.class);
+ private final CompositeNode outputInvokeOn = mock(CompositeNode.class);
+
+ private final DataObject toDataDomInput = mock(DataObject.class);
+ private final CompositeNode toDataDomReturn = mock(CompositeNode.class);
+ private final CompositeNode invokeRpcResult = mock(CompositeNode.class);
+
+ private final DataObject inputForward = mock(DataObject.class);
+ private final DataObject outputForward = mock(DataObject.class);
+
+ private QName mockQName;
+ private URI urn;
+
+ private final MockRpcService mockRpcService = new MockRpcService();
+
+ public class MockRpcService implements RpcService {
+
+ public Future<?> rpcnameWithInputNoOutput(DataObject input) {
+ return futureDataObj;
+ }
+
+ public Future<RpcResult<DataObject>> rpcnameWithInputWithOutput(DataObject input) {
+ return futureDataObj;
+ }
+
+ public Future<RpcResult<DataObject>> rpcnameNoInputWithOutput() {
+ return futureDataObj;
+ }
+
+ public Future<?> rpcnameNoInputNoOutput() {
+ return futureDataObj;
+ }
+ }
+
+ public RpcInvocationStrategyTest() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Before
+ public void testInit() throws Exception {
+ urn = new URI(new String("urn:a:valid:urn"));
+ }
+
+ private void setupForForwardToDom(boolean hasOutput, boolean hasInput, int expectedErrorSize) {
+
+ if (expectedErrorSize > 0)
+ errors.add(rpcError);
+ RpcResult<CompositeNode> result = Rpcs.getRpcResult(true, invokeRpcResult, errors);
+ futureCompNode = Futures.immediateFuture(result);
+ if( hasInput )
+ {
+ when(mockMappingService.toDataDom(inputForward)).thenReturn(toDataDomReturn);
+ }
+ when(mockbiRpcRegistry.invokeRpc(eq(mockQName), any(CompositeNode.class))).thenReturn(
+ futureCompNode);
+ if (hasOutput) {
+ when(
+ mockMappingService.dataObjectFromDataDom(eq(rpcInvocationStrategy
+ .getOutputClass().get()), any(CompositeNode.class))).thenReturn(
+ outputForward);
+ }
+
+ }
+
+ private void validateForwardToDomBroker(ListenableFuture<RpcResult<?>> forwardToDomBroker,
+ boolean expectedSuccess, DataObject expectedResult, int expectedErrorSize)
+ throws InterruptedException, ExecutionException {
+ assertNotNull(forwardToDomBroker);
+ assertEquals(expectedSuccess, forwardToDomBroker.get().isSuccessful());
+ assertEquals(expectedResult, forwardToDomBroker.get().getResult());
+ assertEquals(expectedErrorSize, forwardToDomBroker.get().getErrors().size());
+ }
+
+ private void setupTestMethod(String rpcName, String testMethodName, boolean hasInput)
+ throws NoSuchMethodException {
+ mockQName = new QName(urn, new Date(0L), new String("prefix"), new String(rpcName));
+ java.lang.reflect.Method rpcMethod = hasInput ? MockRpcService.class.getMethod(rpcName,
+ DataObject.class) : MockRpcService.class.getMethod(rpcName);
+ rpcInvocationStrategy = new RpcInvocationStrategy(mockQName, rpcMethod, mockMappingService,
+ mockbiRpcRegistry);
+ }
+
+ /*
+ * forwardToDomBroker tests
+ */
+ @Test
+ public void testForwardToDomBroker_WithInputNoOutput() throws Exception {
+ setupTestMethod("rpcnameWithInputNoOutput", "testForwardToDomBroker_WithInputNoOutput",
+ true);
+ setupForForwardToDom(false, true, 0);
+ ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+ .forwardToDomBroker(inputForward);
+
+ validateForwardToDomBroker(forwardToDomBroker, true, null, 0);
+ }
+
+ @Test
+ public void testForwardToDomBroker_WithInputNoOutput_error() throws Exception {
+ setupTestMethod("rpcnameWithInputNoOutput",
+ "testForwardToDomBroker_WithInputNoOutput_error", true);
+ setupForForwardToDom(false, true, 1);
+ ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+ .forwardToDomBroker(inputForward);
+
+ validateForwardToDomBroker(forwardToDomBroker, true, null, 1);
+ }
+
+ @Test
+ public void testForwardToDomBroker_WithInputWithOutput() throws Exception {
+ setupTestMethod("rpcnameWithInputWithOutput", "testForwardToDomBroker_WithInputWithOutput",
+ true);
+ setupForForwardToDom(true, true, 0);
+ ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+ .forwardToDomBroker(inputForward);
+ validateForwardToDomBroker(forwardToDomBroker, true, outputForward, 0);
+ }
+
+ @Test
+ public void testForwardToDomBroker_NoInputWithOutput() throws Exception {
+ setupTestMethod("rpcnameNoInputWithOutput", "testForwardToDomBroker_NoInputWithOutput",
+ false);
+ setupForForwardToDom(true, false, 0);
+ ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+ .forwardToDomBroker(null);
+ validateForwardToDomBroker(forwardToDomBroker, true, outputForward, 0);
+ }
+
+ @Test
+ public void testForwardToDomBroker_NoInputNoOutput() throws Exception {
+ setupTestMethod("rpcnameNoInputNoOutput", "testForwardToDomBroker_NoInputNoOutput", false);
+ setupForForwardToDom(false, false, 0);
+ ListenableFuture<RpcResult<?>> forwardToDomBroker = rpcInvocationStrategy
+ .forwardToDomBroker(null);
+ validateForwardToDomBroker(forwardToDomBroker, true, null, 0);
+ }
+
+ /*
+ * invokeOn Tests
+ */
+ private void setupRpcResultsWithOutput(int expectedErrorSize) {
+ if (expectedErrorSize > 0)
+ errors.add(rpcError);
+ RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+ futureCompNode = Futures.immediateFuture(resultCompNode);
+ RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, toDataDomInput, errors);
+ futureDataObj = Futures.immediateFuture(resultDataObj);
+
+ when(mockMappingService.toDataDom(toDataDomInput)).thenReturn(outputInvokeOn);
+ }
+
+ private void setupRpcResultsNoOutput(int expectedErrorSize) {
+ if (expectedErrorSize > 0)
+ errors.add(rpcError);
+ RpcResult<CompositeNode> resultCompNode = Rpcs.getRpcResult(true, inputInvokeOn, errors);
+ futureCompNode = Futures.immediateFuture(resultCompNode);
+ RpcResult<DataObject> resultDataObj = Rpcs.getRpcResult(true, null, errors);
+ futureDataObj = Futures.immediateFuture(resultDataObj);
+ }
+
+ private void validateReturnedImmediateFuture(
+ ListenableFuture<RpcResult<CompositeNode>> immediateFuture, boolean expectedSuccess,
+ CompositeNode expectedReturn, int expectedErrorSize) throws InterruptedException,
+ ExecutionException {
+ assertNotNull(immediateFuture);
+ assertEquals(expectedSuccess, immediateFuture.get().isSuccessful());
+ assertEquals(expectedReturn, immediateFuture.get().getResult());
+ assertEquals(expectedErrorSize, immediateFuture.get().getErrors().size());
+ }
+
+ @Test
+ public void testInvokeOn_NoInputNoOutput() throws Exception {
+ setupTestMethod("rpcnameNoInputNoOutput", "testInvokeOn_NoInputNoOutput", false);
+ setupRpcResultsNoOutput(0);
+ ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+ .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+ validateReturnedImmediateFuture(immediateFuture, true, null, 0);
+ }
+
+ @Test
+ public void testInvokeOn_NoInputNoOutput_errors() throws Exception {
+ setupTestMethod("rpcnameNoInputNoOutput", "testInvokeOn_NoInputNoOutput", false);
+ setupRpcResultsNoOutput(1);
+ ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+ .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+ validateReturnedImmediateFuture(immediateFuture, true, null, 1);
+ }
+
+ @Test
+ public void testInvokeOn_WithInputNoOutput() throws Exception {
+ setupTestMethod("rpcnameWithInputNoOutput", "testInvokeOn_WithInputNoOutput", true);
+ setupRpcResultsNoOutput(0);
+ ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+ .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+ validateReturnedImmediateFuture(immediateFuture, true, null, 0);
+ }
+
+ @Test
+ public void testInvokeOn_WithInputWithOutput() throws Exception {
+ setupTestMethod("rpcnameWithInputWithOutput", "testInvokeOn_WithInputWithOutput", true);
+ setupRpcResultsWithOutput(0);
+ ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+ .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+ validateReturnedImmediateFuture(immediateFuture, true, outputInvokeOn, 0);
+ }
+
+ @Test
+ public void testInvokeOn_NoInputWithOutput() throws Exception {
+ setupTestMethod("rpcnameNoInputWithOutput", "testInvokeOn_NoInputWithOutput", false);
+ setupRpcResultsWithOutput(0);
+ ListenableFuture<RpcResult<CompositeNode>> immediateFuture = Futures
+ .immediateFuture(rpcInvocationStrategy.invokeOn(mockRpcService, inputInvokeOn));
+ validateReturnedImmediateFuture(immediateFuture, true, outputInvokeOn, 0);
+ }
+}
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-public class MultipleAugmentationPuts extends AbstractDataServiceTest implements DataChangeListener {
+public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implements DataChangeListener {
private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
private static final String NODE_ID = "openflow:1";
*
* @throws Exception
*/
- @Test
+ @Test( timeout = 15000)
public void testAugmentSerialization() throws Exception {
baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
*/
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
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>sal-binding-spi</artifactId>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
- </scm>
-
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-api</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-core-api</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>concepts-lang</artifactId>
- <version>0.5-SNAPSHOT</version>
- </dependency>
- </dependencies>
-</project>
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-import org.opendaylight.controller.concepts.lang.Transformer;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-public interface DataDomToJavaTransformer<P extends DataObject> extends Transformer<CompositeNode, P> {
-
- /**
- * Returns a QName of valid input composite node.
- *
- * @return
- */
- QName getQName();
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-import org.opendaylight.controller.concepts.lang.InputClassBasedTransformer;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-public interface JavaToDataDomTransformer<I extends DataObject> extends
- InputClassBasedTransformer<DataObject, I, CompositeNode> {
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-/**
- * Translator between Binding-Independent format and generated Binding Data Objects
- *
- *
- *
- *
- * @param <T> Result Type
- */
-public interface Mapper<T extends DataObject> {
-
- QName getQName();
- Class<T> getDataObjectClass();
- T objectFromDom(CompositeNode object);
-
- /**
- *
- * @param obj
- * @return
- * @throws IllegalArgumentException
- */
- CompositeNode domFromObject(DataObject obj) throws IllegalArgumentException;
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-public interface MappingProvider {
-
- <T extends DataObject> Mapper<T> mapperForClass(Class<T> type);
- Mapper<DataObject> mapperForQName(QName name);
-
- /**
- * Returns {@link RpcMapper} associated to class
- *
- * @param type Class for which RpcMapper should provide mapping
- * @return
- */
- <T extends RpcService> RpcMapper<T> rpcMapperForClass(Class<T> type);
-
- /**
- * Returns {@link RpcMapper} associated to the {@link RpcService} proxy.
- *
- * @param proxy
- * @return
- */
- RpcMapper<? extends RpcService> rpcMapperForProxy(RpcService proxy);
-
- /**
- *
- *
- * @param rpc
- * @param inputNode
- * @return
- */
- RpcMapper<? extends RpcService> rpcMapperForData(QName rpc,
- CompositeNode inputNode);
-
- <T extends MappingExtension> MappingExtensionFactory<T> getExtensionFactory(Class<T> cls);
-
- public interface MappingExtension {
-
- }
-
- public interface MappingExtensionFactory<T> {
- T forClass(Class<?> obj);
- }
-
-
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.binding.spi;
-
-import java.util.Set;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-public interface RpcMapper<T extends RpcService> {
-
- Set<QName> getRpcQNames();
-
- /**
- * Returns a class object representing subinterface
- * to whom, this mapper is assigned.
- *
- * @return
- */
- Class<T> getServiceClass();
-
- /**
- * Returns a Binding Mapper for Rpc Input Data
- * @return
- */
- Mapper<?> getInputMapper();
- /**
- * Returns a Binding Mapper for Rpc Output Data
- *
- * @return
- */
- Mapper<?> getOutputMapper();
-
- /**
- * Returns a consumer proxy, which is responsible
- * for invoking the rpc functionality of {@link BindingAwareBroker} implementation.
- *
- * @return Proxy of {@link RpcService} assigned to this mapper.
- */
- T getConsumerProxy(RpcProxyInvocationHandler handler);
-
- /**
- * Invokes the method of RpcService representing the supplied rpc.
- *
- * @param rpc QName of Rpc
- * @param impl Implementation of RpcService on which the method should be invoked
- * @param baInput Input Data to RPC method
- * @return Result of RPC invocation.
- */
- RpcResult<? extends DataObject> invokeRpcImplementation(QName rpc,
- RpcService impl, DataObject baInput);
-
- public interface RpcProxyInvocationHandler {
-
- Future<RpcResult<? extends DataObject>> invokeRpc(RpcService proxy, QName rpc, DataObject input);
- }
-}
}
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
ImmutableMap.Builder<QName, Object> keys = ImmutableMap.builder();
for (QName key : keyDefinition) {
}
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
}
}
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
}
}
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
}
}
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
}
}
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());
}
}
// Write Augmentation data resolution
- if (legacyData.getChildren().size() == 1) {
+ if (legacyData.getValue().size() == 1) {
final DataNormalizationOperation<?> potentialOp;
try {
- final QName childType = legacyData.getChildren().get(0).getNodeType();
+ final QName childType = legacyData.getValue().get(0).getNodeType();
potentialOp = currentOp.getChild(childType);
} catch (DataNormalizationException e) {
throw new IllegalArgumentException(String.format("Failed to get child operation for %s", legacyData), e);
*/
package org.opendaylight.controller.sal.common.util;
-public class Arguments {
+public final class Arguments {
private Arguments() {
throw new UnsupportedOperationException("Utility class");
}
-
+
/**
* Checks if value is instance of provided class
- *
- *
+ *
+ *
* @param value Value to check
* @param type Type to check
* @return Reference which was checked
@SuppressWarnings("unchecked")
public static <T> T checkInstanceOf(Object value, Class<T> type) {
if(!type.isInstance(value))
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException(String.format("Value %s is not of type %s", value, type));
return (T) value;
}
}
+++ /dev/null
-<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">\r
- <modelVersion>4.0.0</modelVersion>\r
- <parent>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-parent</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </parent>\r
- <artifactId>sal-data-api</artifactId>\r
- <scm>\r
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
- </scm>\r
-\r
-</project>\r
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-api</artifactId>
</instructions>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
<!-- TODO - unite yang-maven-plugin configuration in md-sal-->
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-/**
-*
-*/
public final class SchemaServiceImplSingletonModule extends
- org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImplSingletonModule {
+org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImplSingletonModule {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SchemaServiceImplSingletonModule.class);
BundleContext bundleContext;
- public SchemaServiceImplSingletonModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ public SchemaServiceImplSingletonModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
super(identifier, dependencyResolver);
}
- public SchemaServiceImplSingletonModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
- SchemaServiceImplSingletonModule oldModule, java.lang.AutoCloseable oldInstance) {
+ public SchemaServiceImplSingletonModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ final SchemaServiceImplSingletonModule oldModule, final java.lang.AutoCloseable oldInstance) {
super(identifier, dependencyResolver, oldModule, oldInstance);
}
@Override
- public boolean canReuseInstance(AbstractSchemaServiceImplSingletonModule oldModule) {
+ public boolean canReuseInstance(final AbstractSchemaServiceImplSingletonModule oldModule) {
return true;
}
return bundleContext;
}
- public void setBundleContext(BundleContext bundleContext) {
+ public void setBundleContext(final BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
return new GlobalSchemaServiceProxy(getBundleContext(), ref);
}
- GlobalBundleScanningSchemaServiceImpl newInstance = new GlobalBundleScanningSchemaServiceImpl();
- newInstance.setContext(getBundleContext());
+ GlobalBundleScanningSchemaServiceImpl newInstance = new GlobalBundleScanningSchemaServiceImpl(getBundleContext());
newInstance.start();
return newInstance;
}
private ServiceReference<SchemaService> reference;
private SchemaService delegate;
- public GlobalSchemaServiceProxy(BundleContext bundleContext, ServiceReference<SchemaService> ref) {
+ public GlobalSchemaServiceProxy(final BundleContext bundleContext, final ServiceReference<SchemaService> ref) {
this.bundleContext = bundleContext;
this.reference = ref;
this.delegate = bundleContext.getService(reference);
public void close() throws Exception {
if (delegate != null) {
delegate = null;
- bundleContext.ungetService(reference);
+
+ try {
+ bundleContext.ungetService(reference);
+ } catch (IllegalStateException e) {
+ // Indicates the service was already unregistered which can happen normally
+ // on shutdown.
+ LOG.debug( "Error unregistering service", e );
+ }
+
reference = null;
bundleContext = null;
}
}
- public void addModule(Module arg0) {
+ @Override
+ public void addModule(final Module arg0) {
delegate.addModule(arg0);
}
+ @Override
public SchemaContext getGlobalContext() {
return delegate.getGlobalContext();
}
+ @Override
public SchemaContext getSessionContext() {
return delegate.getSessionContext();
}
- public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener arg0) {
+ @Override
+ public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(final SchemaServiceListener arg0) {
return delegate.registerSchemaServiceListener(arg0);
}
- public void removeModule(Module arg0) {
+ @Override
+ public void removeModule(final Module arg0) {
delegate.removeModule(arg0);
}
package org.opendaylight.controller.md.sal.dom.broker.impl.compat;
import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
import org.opendaylight.controller.md.sal.common.api.data.DataReader;
import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
import org.opendaylight.controller.sal.common.DataStoreIdentifier;
import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.core.api.data.DataProviderService;
import org.opendaylight.controller.sal.core.api.data.DataValidator;
import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
-import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
public class BackwardsCompatibleDataBroker implements DataProviderService, SchemaContextListener {
- DOMDataBroker backingBroker;
- DataNormalizer normalizer;
- private final ListenerRegistry<DataChangeListener> fakeRegistry = ListenerRegistry.create();
-
+ private final DOMDataBroker backingBroker;
+ private DataNormalizer normalizer;
public BackwardsCompatibleDataBroker(final DOMDataBroker newBiDataImpl) {
backingBroker = newBiDataImpl;
@Override
public CompositeNode readConfigurationData(final InstanceIdentifier legacyPath) {
- BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
+ final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
try {
return tx.readConfigurationData(legacyPath);
} finally {
@Override
public CompositeNode readOperationalData(final InstanceIdentifier legacyPath) {
- BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
+ final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
try {
return tx.readOperationalData(legacyPath);
} finally {
}
@Override
- public ListenerRegistration<DataChangeListener> registerDataChangeListener(final InstanceIdentifier path,
+ public ListenerRegistration<DataChangeListener> registerDataChangeListener(final InstanceIdentifier legacyPath,
final DataChangeListener listener) {
- return fakeRegistry .register(listener);
+ final InstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
+
+ final TranslatingListenerInvoker translatingCfgListener =
+ TranslatingListenerInvoker.createConfig(listener, normalizer);
+ translatingCfgListener.register(backingBroker, normalizedPath);
+
+ final TranslatingListenerInvoker translatingOpListener =
+ TranslatingListenerInvoker.createOperational(listener, normalizer);
+ translatingOpListener.register(backingBroker, normalizedPath);
+
+ return new DelegateListenerRegistration(translatingCfgListener, translatingOpListener, listener);
}
@Override
return null;
}
- // Obsolote functionality
+ // Obsolete functionality
@Override
public void addValidator(final DataStoreIdentifier store, final DataValidator validator) {
throw new UnsupportedOperationException("Data Reader contract is not supported.");
}
- private final class TranslatingListenerInvoker implements DOMDataChangeListener, Delegator<DataChangeListener> {
-
+ private static class DelegateListenerRegistration implements ListenerRegistration<DataChangeListener> {
+ private final TranslatingListenerInvoker translatingCfgListener;
+ private final TranslatingListenerInvoker translatingOpListener;
+ private final DataChangeListener listener;
- private DataChangeListener delegate;
+ public DelegateListenerRegistration(final TranslatingListenerInvoker translatingCfgListener, final TranslatingListenerInvoker translatingOpListener, final DataChangeListener listener) {
+ this.translatingCfgListener = translatingCfgListener;
+ this.translatingOpListener = translatingOpListener;
+ this.listener = listener;
+ }
@Override
- public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
-
- DataChangeEvent<InstanceIdentifier, CompositeNode> legacyChange = null;
- delegate.onDataChanged(legacyChange);
+ public void close() {
+ translatingCfgListener.close();
+ translatingOpListener.close();
}
@Override
- public DataChangeListener getDelegate() {
-
- return delegate;
+ public DataChangeListener getInstance() {
+ return listener;
}
-
-
}
-
}
--- /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.broker.impl.compat;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.collect.Maps;
+
+public abstract class TranslatingDataChangeEvent implements
+DataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
+
+ private TranslatingDataChangeEvent() {
+ }
+
+ public static DataChangeEvent<InstanceIdentifier, CompositeNode> createOperational(
+ final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
+ return new OperationalChangeEvent(change, normalizer);
+ }
+
+ public static DataChangeEvent<InstanceIdentifier, CompositeNode> createConfiguration(
+ final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
+ return new ConfigurationChangeEvent(change, normalizer);
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedConfigurationData() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedOperationalData() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public CompositeNode getOriginalConfigurationSubtree() {
+ return null;
+ }
+
+ @Override
+ public CompositeNode getOriginalOperationalSubtree() {
+ return null;
+ }
+
+ @Override
+ public CompositeNode getUpdatedConfigurationSubtree() {
+ return null;
+ }
+
+ @Override
+ public CompositeNode getUpdatedOperationalSubtree() {
+ return null;
+ }
+
+ private final static class OperationalChangeEvent extends TranslatingDataChangeEvent {
+
+ private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> delegate;
+ private final DataNormalizer normalizer;
+ private Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedCache;
+
+ public OperationalChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change,
+ final DataNormalizer normalizer) {
+ this.delegate = change;
+ this.normalizer = normalizer;
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedOperationalData() {
+ return transformToLegacy(normalizer, delegate.getCreatedData());
+ }
+
+
+ @Override
+ public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedOperationalData() {
+ return delegate.getRemovedPaths();
+ }
+
+ @Override
+ public CompositeNode getOriginalOperationalSubtree() {
+ // first argument is unused
+ return normalizer.toLegacy(null, delegate.getOriginalSubtree());
+ }
+
+ @Override
+ public CompositeNode getUpdatedOperationalSubtree() {
+ // first argument is unused
+ return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalOperationalData() {
+ return transformToLegacy(normalizer, delegate.getOriginalData());
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
+ if(updatedCache == null) {
+ final Map<InstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
+ final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
+ final HashMap<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
+ updatedComposite.putAll(created);
+ updatedComposite.putAll(updated);
+ updatedCache = Collections.unmodifiableMap(updatedComposite);
+ }
+ return updatedCache;
+ }
+
+ @Override
+ public String toString() {
+ return "OperationalChangeEvent [delegate=" + delegate + "]";
+ }
+
+ }
+
+ private static Map<InstanceIdentifier, CompositeNode> transformToLegacy(final DataNormalizer normalizer, final Map<InstanceIdentifier, ? extends NormalizedNode<?, ?>> nodes) {
+ final Map<InstanceIdentifier, CompositeNode> legacy = Maps.newHashMap();
+
+ for (final Map.Entry<InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : nodes.entrySet()) {
+ try {
+ legacy.put(normalizer.toLegacy(entry.getKey()), normalizer.toLegacy(entry.getKey(), entry.getValue()));
+ } catch (final DataNormalizationException e) {
+ throw new IllegalStateException("Unable to transform data change event to legacy format", e);
+ }
+ }
+ return legacy;
+ }
+
+ private final static class ConfigurationChangeEvent extends TranslatingDataChangeEvent {
+
+ private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> delegate;
+ private final DataNormalizer normalizer;
+ private Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedCache;
+
+ public ConfigurationChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change,
+ final DataNormalizer normalizer) {
+ this.delegate = change;
+ this.normalizer = normalizer;
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
+ return transformToLegacy(normalizer, delegate.getCreatedData());
+ }
+
+
+ @Override
+ public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedConfigurationData() {
+ return delegate.getRemovedPaths();
+ }
+
+ @Override
+ public CompositeNode getOriginalConfigurationSubtree() {
+ // first argument is unused
+ return normalizer.toLegacy(null, delegate.getOriginalSubtree());
+ }
+
+ @Override
+ public CompositeNode getUpdatedConfigurationSubtree() {
+ // first argument is unused
+ return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
+ return transformToLegacy(normalizer, delegate.getOriginalData());
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
+ if(updatedCache == null) {
+ final Map<InstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
+ final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
+ final HashMap<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
+ updatedComposite.putAll(created);
+ updatedComposite.putAll(updated);
+ updatedCache = Collections.unmodifiableMap(updatedComposite);
+ }
+ return updatedCache;
+ }
+
+ @Override
+ public String toString() {
+ return "ConfigurationChangeEvent [delegate=" + delegate + "]";
+ }
+ }
+}
--- /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.broker.impl.compat;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+abstract class TranslatingListenerInvoker implements AutoCloseable, DOMDataChangeListener, Delegator<DataChangeListener> {
+
+ private final DataChangeListener delegate;
+ private final DataNormalizer normalizer;
+ protected ListenerRegistration<DOMDataChangeListener> reg;
+
+ protected TranslatingListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+ this.delegate = listener;
+ this.normalizer = normalizer;
+ }
+
+ static TranslatingListenerInvoker createConfig(final DataChangeListener listener, final DataNormalizer normalizer) {
+ return new TranslatingConfigListenerInvoker(listener, normalizer);
+ }
+
+ static TranslatingListenerInvoker createOperational(final DataChangeListener listener, final DataNormalizer normalizer) {
+ return new TranslatingOperationalListenerInvoker(listener, normalizer);
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+ delegate.onDataChanged(getLegacyEvent(normalizer, normalizedChange));
+ }
+
+ abstract DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer,
+ final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange);
+
+ @Override
+ public DataChangeListener getDelegate() {
+ return delegate;
+ }
+
+ abstract void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath);
+
+ @Override
+ public void close() {
+ if (reg != null) {
+ reg.close();
+ }
+ }
+
+ static final class TranslatingConfigListenerInvoker extends TranslatingListenerInvoker {
+
+ public TranslatingConfigListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+ super(listener, normalizer);
+ }
+
+ DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+ return TranslatingDataChangeEvent.createConfiguration(normalizedChange, normalizer);
+ }
+
+ @Override
+ void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath) {
+ reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, normalizedPath, this,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ }
+ }
+
+ static final class TranslatingOperationalListenerInvoker extends TranslatingListenerInvoker {
+
+ public TranslatingOperationalListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+ super(listener, normalizer);
+ }
+
+ DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+ return TranslatingDataChangeEvent.createOperational(normalizedChange, normalizer);
+ }
+
+ @Override
+ void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath) {
+ reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, normalizedPath, this,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ }
+ }
+
+}
+++ /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 org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-
-public class DataPreconditionFailedException extends Exception {
-
- /**
- *
- */
- private static final long serialVersionUID = 596430355175413427L;
- private final InstanceIdentifier path;
-
- public DataPreconditionFailedException(final InstanceIdentifier path) {
- this.path = path;
- }
-
- public DataPreconditionFailedException(final InstanceIdentifier path,final String message) {
- super(message);
- this.path = path;
- }
-
-
- public DataPreconditionFailedException(final InstanceIdentifier path,final Throwable cause) {
- super(cause);
- this.path = path;
- }
-
- public DataPreconditionFailedException(final InstanceIdentifier path,final String message, final Throwable cause) {
- super(message, cause);
- this.path = path;
- }
-
- public DataPreconditionFailedException(final InstanceIdentifier path,final String message, final Throwable cause, final boolean enableSuppression,
- final boolean writableStackTrace) {
- super(message, cause, enableSuppression, writableStackTrace);
- this.path = path;
- }
-
- public InstanceIdentifier getPath() {
- return path;
- }
-
-}
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
-import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.increase;
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.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.InMemoryDataTreeFactory;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
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;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-import com.google.common.primitives.UnsignedLong;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, SchemaContextListener {
-
private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class);
- private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
-
+ private final DataTree dataTree = InMemoryDataTreeFactory.getInstance().create();
+ private final ListenerTree listenerTree = ListenerTree.create();
+ private final AtomicLong txCounter = new AtomicLong(0);
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;
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);
}
@Override
public DOMStoreWriteTransaction newWriteOnlyTransaction() {
- return new SnapshotBackedWriteTransaction(nextIdentifier(), snapshot.get(), this, operationTree);
+ return new SnapshotBackedWriteTransaction(nextIdentifier(), dataTree.takeSnapshot(), this);
}
@Override
public synchronized void onGlobalContextUpdated(final SchemaContext ctx) {
- operationTree = SchemaAwareApplyOperationRoot.from(ctx);
- schemaContext = ctx;
+ dataTree.setSchemaContext(ctx);
}
@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,
- final ResolveDataChangeEventsTask listenerResolver) {
- LOG.debug("Updating Store snaphot version: {} with version:{}", currentSnapshot.getMetadataTree()
- .getSubtreeVersion(), 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.");
-
- for (ChangeListenerNotifyTask task : listenerResolver.call()) {
- LOG.trace("Scheduling invocation of listeners: {}", task);
- executor.submit(task);
- }
- }
- }
-
private static abstract class AbstractDOMStoreTransaction implements DOMStoreTransaction {
private final Object identifier;
}
}
- private static class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements
- DOMStoreReadTransaction {
- private DataAndMetadataSnapshot stableSnapshot;
+ private static final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements
+ DOMStoreReadTransaction {
+ private DataTreeSnapshot stableSnapshot;
- public SnapshotBackedReadTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot) {
+ public SnapshotBackedReadTransaction(final Object identifier, final DataTreeSnapshot 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 static class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements
- DOMStoreWriteTransaction {
- private MutableDataTree mutableTree;
+ DOMStoreWriteTransaction {
+ private DataTreeModification mutableTree;
private InMemoryDOMDataStore store;
private boolean ready = false;
- public SnapshotBackedWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot,
- final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
+ public SnapshotBackedWriteTransaction(final Object identifier, final DataTreeSnapshot snapshot,
+ final InMemoryDOMDataStore store) {
super(identifier);
- mutableTree = MutableDataTree.from(snapshot, applyOper);
+ mutableTree = snapshot.newModification();
this.store = store;
- LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree()
- .getSubtreeVersion());
+ LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot);
}
@Override
return store.submit(this);
}
- protected MutableDataTree getMutatedView() {
+ protected DataTreeModification getMutatedView() {
return mutableTree;
}
}
private static class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction implements
- DOMStoreReadWriteTransaction {
+ DOMStoreReadWriteTransaction {
- protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataAndMetadataSnapshot snapshot,
- final InMemoryDOMDataStore store, final ModificationApplyOperation applyOper) {
- super(identifier, snapshot, store, applyOper);
+ protected SnapshotBackedReadWriteTransaction(final Object identifier, final DataTreeSnapshot snapshot,
+ final InMemoryDOMDataStore store) {
+ super(identifier, snapshot, store);
}
@Override
public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final InstanceIdentifier path) {
LOG.trace("Tx: {} Read: {}", getIdentifier(), path);
try {
- return Futures.immediateFuture(getMutatedView().read(path));
+ return Futures.immediateFuture(getMutatedView().readNode(path));
} catch (Exception e) {
LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e);
throw e;
private class ThreePhaseCommitImpl implements DOMStoreThreePhaseCommitCohort {
private final SnapshotBackedWriteTransaction transaction;
- private final NodeModification modification;
+ private final DataTreeModification modification;
- private DataAndMetadataSnapshot storeSnapshot;
- private Optional<StoreMetadataNode> proposedSubtree;
private ResolveDataChangeEventsTask listenerResolver;
+ private DataTreeCandidate candidate;
public ThreePhaseCommitImpl(final SnapshotBackedWriteTransaction writeTransaction) {
this.transaction = writeTransaction;
- this.modification = transaction.getMutatedView().getRootModification();
+ this.modification = transaction.getMutatedView();
}
@Override
public ListenableFuture<Boolean> canCommit() {
- final DataAndMetadataSnapshot snapshotCapture = snapshot.get();
- final ModificationApplyOperation snapshotOperation = operationTree;
-
return executor.submit(new Callable<Boolean>() {
-
@Override
- public Boolean call() throws Exception {
- Boolean applicable = false;
+ public Boolean call() {
try {
- snapshotOperation.checkApplicable(PUBLIC_ROOT_PATH, modification,
- Optional.of(snapshotCapture.getMetadataTree()));
- applicable = true;
+ dataTree.validate(modification);
+ LOG.debug("Store Transaction: {} can be committed", transaction.getIdentifier());
+ return true;
} catch (DataPreconditionFailedException e) {
LOG.warn("Store Tx: {} Data Precondition failed for {}.",transaction.getIdentifier(),e.getPath(),e);
- applicable = false;
+ return false;
}
- LOG.debug("Store Transaction: {} : canCommit : {}", transaction.getIdentifier(), applicable);
- return applicable;
}
});
}
@Override
public ListenableFuture<Void> preCommit() {
- storeSnapshot = snapshot.get();
- if (modification.getModificationType() == ModificationType.UNMODIFIED) {
- return Futures.immediateFuture(null);
- }
return executor.submit(new Callable<Void>() {
-
@Override
- public Void call() throws Exception {
- StoreMetadataNode metadataTree = storeSnapshot.getMetadataTree();
-
- proposedSubtree = operationTree.apply(modification, Optional.of(metadataTree),
- increase(metadataTree.getSubtreeVersion()));
-
- listenerResolver = ResolveDataChangeEventsTask.create() //
- .setRootPath(PUBLIC_ROOT_PATH) //
- .setBeforeRoot(Optional.of(metadataTree)) //
- .setAfterRoot(proposedSubtree) //
- .setModificationRoot(modification) //
- .setListenerRoot(listenerTree);
-
+ public Void call() {
+ candidate = dataTree.prepare(modification);
+ listenerResolver = ResolveDataChangeEventsTask.create(candidate, listenerTree);
return null;
}
});
@Override
public ListenableFuture<Void> abort() {
- storeSnapshot = null;
- proposedSubtree = null;
- return Futures.<Void> immediateFuture(null);
+ candidate = null;
+ return Futures.immediateFuture(null);
}
@Override
public ListenableFuture<Void> commit() {
- if (modification.getModificationType() == ModificationType.UNMODIFIED) {
- return Futures.immediateFuture(null);
+ checkState(candidate != null, "Proposed subtree must be computed");
+
+ /*
+ * The commit has to occur atomically with regard to listener
+ * registrations.
+ */
+ synchronized (this) {
+ dataTree.commit(candidate);
+
+ for (ChangeListenerNotifyTask task : listenerResolver.call()) {
+ LOG.trace("Scheduling invocation of listeners: {}", task);
+ executor.submit(task);
+ }
}
- checkState(proposedSubtree != null, "Proposed subtree must be computed");
- checkState(storeSnapshot != null, "Proposed subtree must be computed");
- // return ImmediateFuture<>;
- InMemoryDOMDataStore.this.commit(storeSnapshot, proposedSubtree.get(), listenerResolver);
- return Futures.<Void> immediateFuture(null);
- }
-
- }
-
- private static final class AlwaysFailOperation implements ModificationApplyOperation {
-
- @Override
- public Optional<StoreMetadataNode> apply(final NodeModification modification,
- final Optional<StoreMetadataNode> storeMeta, final UnsignedLong subtreeVersion) {
- throw new IllegalStateException("Schema Context is not available.");
+ return Futures.immediateFuture(null);
}
-
- @Override
- public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> storeMetadata) {
- throw new IllegalStateException("Schema Context is not available.");
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
- throw new IllegalStateException("Schema Context is not available.");
- }
-
- @Override
- public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
- throw new IllegalStateException("Schema Context is not available.");
- }
-
}
}
+++ /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 static com.google.common.base.Preconditions.checkState;
-
-import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-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.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-/*
- * FIXME: the thread safety of concurrent write/delete/read/seal operations
- * needs to be evaluated.
- */
-class MutableDataTree {
- 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 MutableDataTree(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation strategyTree) {
- this.snapshot = snapshot;
- this.strategyTree = strategyTree;
- this.rootModification = NodeModification.createUnmodified(snapshot.getMetadataTree());
- }
-
- public void write(final InstanceIdentifier path, final NormalizedNode<?, ?> value) {
- checkSealed();
- resolveModificationFor(path).write(value);
- }
-
- public void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
- checkSealed();
- mergeImpl(resolveModificationFor(path),data);
- }
-
- private void mergeImpl(final OperationWithModification op,final NormalizedNode<?,?> data) {
-
- if(data instanceof NormalizedNodeContainer<?,?,?>) {
- @SuppressWarnings({ "rawtypes", "unchecked" })
- NormalizedNodeContainer<?,?,NormalizedNode<PathArgument, ?>> dataContainer = (NormalizedNodeContainer) data;
- for(NormalizedNode<PathArgument, ?> child : dataContainer.getValue()) {
- PathArgument childId = child.getIdentifier();
- mergeImpl(op.forChild(childId), child);
- }
- }
- op.merge(data);
- }
-
- public void delete(final InstanceIdentifier path) {
- checkSealed();
- resolveModificationFor(path).delete();
- }
-
- public Optional<NormalizedNode<?, ?>> read(final InstanceIdentifier path) {
- Entry<InstanceIdentifier, NodeModification> modification = TreeNodeUtils.findClosestsOrFirstMatch(rootModification, path, NodeModification.IS_TERMINAL_PREDICATE);
-
- Optional<StoreMetadataNode> result = resolveSnapshot(modification);
- if (result.isPresent()) {
- NormalizedNode<?, ?> data = result.get().getData();
- return NormalizedNodeUtils.findNode(modification.getKey(), data, path);
- }
- return Optional.absent();
- }
-
- private Optional<StoreMetadataNode> resolveSnapshot(
- final Entry<InstanceIdentifier, NodeModification> keyModification) {
- InstanceIdentifier path = keyModification.getKey();
- NodeModification modification = keyModification.getValue();
- return resolveSnapshot(path, modification);
- }
-
- private Optional<StoreMetadataNode> resolveSnapshot(final InstanceIdentifier path,
- final NodeModification modification) {
- try {
- Optional<Optional<StoreMetadataNode>> potentialSnapshot = modification.getSnapshotCache();
- if(potentialSnapshot.isPresent()) {
- return potentialSnapshot.get();
- }
- return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
- StoreUtils.increase(snapshot.getMetadataTree().getSubtreeVersion()));
- } catch (Exception e) {
- LOG.error("Could not create snapshot for {}:{}", path,modification,e);
- throw e;
- }
- }
-
- private ModificationApplyOperation resolveModificationStrategy(final InstanceIdentifier path) {
- LOG.trace("Resolving modification apply strategy for {}", path);
- return TreeNodeUtils.findNodeChecked(strategyTree, path);
- }
-
- private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
- NodeModification modification = rootModification;
- // We ensure strategy is present.
- ModificationApplyOperation operation = resolveModificationStrategy(path);
- for (PathArgument pathArg : path.getPath()) {
- modification = modification.modifyChild(pathArg);
- }
- return OperationWithModification.from(operation, modification);
- }
-
- public static MutableDataTree from(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation resolver) {
- return new MutableDataTree(snapshot, resolver);
- }
-
- public void seal() {
- final boolean success = sealed.compareAndSet(false, true);
- Preconditions.checkState(success, "Attempted to seal an already-sealed Data Tree.");
- rootModification.seal();
- }
-
- private void checkSealed() {
- checkState(!sealed.get(), "Data Tree is sealed. No further modifications allowed.");
- }
-
- protected NodeModification getRootModification() {
- return rootModification;
- }
-
- @Override
- public String toString() {
- return "MutableDataTree [modification=" + rootModification + "]";
- }
-}
package org.opendaylight.controller.md.sal.dom.store.impl;
import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
-import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.append;
+import static org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils.append;
import java.util.Collection;
import java.util.Collections;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.SimpleEventFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Node;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
* </ul>
*
*/
-public class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListenerNotifyTask>> {
+final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListenerNotifyTask>> {
private static final Logger LOG = LoggerFactory.getLogger(ResolveDataChangeEventsTask.class);
private static final DOMImmutableDataChangeEvent NO_CHANGE = builder(DataChangeScope.BASE).build();
- private InstanceIdentifier rootPath;
- private ListenerTree listenerRoot;
- private NodeModification modificationRoot;
- private Optional<StoreMetadataNode> beforeRoot;
- private Optional<StoreMetadataNode> afterRoot;
private final Multimap<ListenerTree.Node, DOMImmutableDataChangeEvent> events = HashMultimap.create();
+ private final DataTreeCandidate candidate;
+ private final ListenerTree listenerRoot;
- protected InstanceIdentifier getRootPath() {
- return rootPath;
- }
-
- protected ResolveDataChangeEventsTask setRootPath(final InstanceIdentifier rootPath) {
- this.rootPath = rootPath;
- return this;
- }
-
- protected ListenerTree getListenerRoot() {
- return listenerRoot;
- }
-
- protected ResolveDataChangeEventsTask setListenerRoot(final ListenerTree listenerRoot) {
- this.listenerRoot = listenerRoot;
- return this;
- }
-
- protected NodeModification getModificationRoot() {
- return modificationRoot;
- }
-
- protected ResolveDataChangeEventsTask setModificationRoot(final NodeModification modificationRoot) {
- this.modificationRoot = modificationRoot;
- return this;
- }
-
- protected Optional<StoreMetadataNode> getBeforeRoot() {
- return beforeRoot;
- }
-
- protected ResolveDataChangeEventsTask setBeforeRoot(final Optional<StoreMetadataNode> beforeRoot) {
- this.beforeRoot = beforeRoot;
- return this;
- }
-
- protected Optional<StoreMetadataNode> getAfterRoot() {
- return afterRoot;
- }
-
- protected ResolveDataChangeEventsTask setAfterRoot(final Optional<StoreMetadataNode> afterRoot) {
- this.afterRoot = afterRoot;
- return this;
+ public ResolveDataChangeEventsTask(DataTreeCandidate candidate, ListenerTree listenerTree) {
+ this.candidate = Preconditions.checkNotNull(candidate);
+ this.listenerRoot = Preconditions.checkNotNull(listenerTree);
}
/**
*/
@Override
public Iterable<ChangeListenerNotifyTask> call() {
- LOG.trace("Resolving events for {}", modificationRoot);
-
try (final Walker w = listenerRoot.getWalker()) {
- resolveAnyChangeEvent(rootPath, Collections.singleton(w.getRootNode()), modificationRoot, beforeRoot,
- afterRoot);
+ resolveAnyChangeEvent(candidate.getRootPath(), Collections.singleton(w.getRootNode()), candidate.getRootNode());
return createNotificationTasks();
}
}
* @return Data Change Event of this node and all it's children
*/
private DOMImmutableDataChangeEvent resolveAnyChangeEvent(final InstanceIdentifier path,
- final Collection<ListenerTree.Node> listeners, final NodeModification modification,
- final Optional<StoreMetadataNode> before, final Optional<StoreMetadataNode> after) {
- // No listeners are present in listener registration subtree
- // no before and after state is present
- if (!before.isPresent() && !after.isPresent()) {
+ final Collection<ListenerTree.Node> listeners, final DataTreeCandidateNode node) {
+
+ if (node.getModificationType() != ModificationType.UNMODIFIED &&
+ !node.getDataAfter().isPresent() && !node.getDataBefore().isPresent()) {
+ LOG.debug("Modification at {} has type {}, but no before- and after-data. Assuming unchanged.",
+ path, node.getModificationType());
return NO_CHANGE;
}
- switch (modification.getModificationType()) {
+
+ // no before and after state is present
+
+ switch (node.getModificationType()) {
case SUBTREE_MODIFIED:
- return resolveSubtreeChangeEvent(path, listeners, modification, before.get(), after.get());
+ return resolveSubtreeChangeEvent(path, listeners, node);
case MERGE:
case WRITE:
- if (before.isPresent()) {
- return resolveReplacedEvent(path, listeners, before.get().getData(), after.get().getData());
+ Preconditions.checkArgument(node.getDataAfter().isPresent(),
+ "Modification at {} has type {} but no after-data", path, node.getModificationType());
+ if (node.getDataBefore().isPresent()) {
+ return resolveReplacedEvent(path, listeners, node.getDataBefore().get(), node.getDataAfter().get());
} else {
- return resolveCreateEvent(path, listeners, after.get());
+ return resolveCreateEvent(path, listeners, node.getDataAfter().get());
}
case DELETE:
- return resolveDeleteEvent(path, listeners, before.get());
- default:
+ Preconditions.checkArgument(node.getDataBefore().isPresent(),
+ "Modification at {} has type {} but no before-data", path, node.getModificationType());
+ return resolveDeleteEvent(path, listeners, node.getDataBefore().get());
+ case UNMODIFIED:
return NO_CHANGE;
}
+ throw new IllegalStateException(String.format("Unhandled node state %s at %s", node.getModificationType(), path));
}
private DOMImmutableDataChangeEvent resolveReplacedEvent(final InstanceIdentifier path,
private DOMImmutableDataChangeEvent resolveNodeContainerReplaced(final InstanceIdentifier path,
final Collection<Node> listeners,
final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont,
- final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
+ final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
final Set<PathArgument> alreadyProcessed = new HashSet<>();
final List<DOMImmutableDataChangeEvent> childChanges = new LinkedList<>();
* @return
*/
private DOMImmutableDataChangeEvent resolveCreateEvent(final InstanceIdentifier path,
- final Collection<ListenerTree.Node> listeners, final StoreMetadataNode afterState) {
+ final Collection<ListenerTree.Node> listeners, final NormalizedNode<?, ?> afterState) {
@SuppressWarnings({ "unchecked", "rawtypes" })
- final NormalizedNode<PathArgument, ?> node = (NormalizedNode) afterState.getData();
+ final NormalizedNode<PathArgument, ?> node = (NormalizedNode) afterState;
return resolveSameEventRecursivelly(path, listeners, node, DOMImmutableDataChangeEvent.getCreateEventFactory());
}
private DOMImmutableDataChangeEvent resolveDeleteEvent(final InstanceIdentifier path,
- final Collection<ListenerTree.Node> listeners, final StoreMetadataNode beforeState) {
+ final Collection<ListenerTree.Node> listeners, final NormalizedNode<?, ?> beforeState) {
@SuppressWarnings({ "unchecked", "rawtypes" })
- final NormalizedNode<PathArgument, ?> node = (NormalizedNode) beforeState.getData();
+ final NormalizedNode<PathArgument, ?> node = (NormalizedNode) beforeState;
return resolveSameEventRecursivelly(path, listeners, node, DOMImmutableDataChangeEvent.getRemoveEventFactory());
}
final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
DOMImmutableDataChangeEvent propagateEvent = event;
// We have listeners for this node or it's children, so we will try
- // to do additional processing
+ // to do additional processing
if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
LOG.trace("Resolving subtree recursive event for {}, type {}", path, eventFactory);
}
private DOMImmutableDataChangeEvent resolveSubtreeChangeEvent(final InstanceIdentifier path,
- final Collection<ListenerTree.Node> listeners, final NodeModification modification,
- final StoreMetadataNode before, final StoreMetadataNode after) {
+ final Collection<ListenerTree.Node> listeners, final DataTreeCandidateNode modification) {
- Builder one = builder(DataChangeScope.ONE).setBefore(before.getData()).setAfter(after.getData());
+ Preconditions.checkArgument(modification.getDataBefore().isPresent(), "Subtree change with before-data not present at path %s", path);
+ Preconditions.checkArgument(modification.getDataAfter().isPresent(), "Subtree change with after-data not present at path %s", path);
- Builder subtree = builder(DataChangeScope.SUBTREE).setBefore(before.getData()).setAfter(after.getData());
+ Builder one = builder(DataChangeScope.ONE).
+ setBefore(modification.getDataBefore().get()).
+ setAfter(modification.getDataAfter().get());
+ Builder subtree = builder(DataChangeScope.SUBTREE).
+ setBefore(modification.getDataBefore().get()).
+ setAfter(modification.getDataAfter().get());
- for (NodeModification childMod : modification.getModifications()) {
+ for (DataTreeCandidateNode childMod : modification.getChildNodes()) {
PathArgument childId = childMod.getIdentifier();
InstanceIdentifier childPath = append(path, childId);
Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
- Optional<StoreMetadataNode> childBefore = before.getChild(childId);
- Optional<StoreMetadataNode> childAfter = after.getChild(childId);
-
switch (childMod.getModificationType()) {
case WRITE:
case MERGE:
case DELETE:
- one.merge(resolveAnyChangeEvent(childPath, childListeners, childMod, childBefore, childAfter));
+ one.merge(resolveAnyChangeEvent(childPath, childListeners, childMod));
break;
case SUBTREE_MODIFIED:
- subtree.merge(resolveSubtreeChangeEvent(childPath, childListeners, childMod, childBefore.get(),
- childAfter.get()));
+ subtree.merge(resolveSubtreeChangeEvent(childPath, childListeners, childMod));
break;
case UNMODIFIED:
// no-op
}
}
- public static ResolveDataChangeEventsTask create() {
- return new ResolveDataChangeEventsTask();
+ public static ResolveDataChangeEventsTask create(DataTreeCandidate candidate, ListenerTree listenerTree) {
+ return new ResolveDataChangeEventsTask(candidate, listenerTree);
}
}
+++ /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 static com.google.common.base.Preconditions.checkArgument;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
-import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.primitives.UnsignedLong;
-
-public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
-
- public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
- if (schemaNode instanceof ContainerSchemaNode) {
- return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
- } else if (schemaNode instanceof ListSchemaNode) {
- return fromListSchemaNode((ListSchemaNode) schemaNode);
- } else if (schemaNode instanceof ChoiceNode) {
- return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
- } else if (schemaNode instanceof LeafListSchemaNode) {
- return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
- } else if (schemaNode instanceof LeafSchemaNode) {
- return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
- }
- throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
- }
-
- private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
- List<QName> keyDefinition = schemaNode.getKeyDefinition();
- if (keyDefinition == null || keyDefinition.isEmpty()) {
- return new UnkeyedListModificationStrategy(schemaNode);
- }
- if (schemaNode.isUserOrdered()) {
- return new OrderedMapModificationStrategy(schemaNode);
- }
-
- return new UnorderedMapModificationStrategy(schemaNode);
- }
-
- private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
- if(schemaNode.isUserOrdered()) {
- return new OrderedLeafSetModificationStrategy(schemaNode);
- } else {
- return new UnorderedLeafSetModificationStrategy(schemaNode);
- }
- }
-
-
- public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
- final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
- AugmentationSchema augSchema = null;
- allAugments: for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
- boolean containsAll = true;
- for (DataSchemaNode child : potential.getChildNodes()) {
- if (identifier.getPossibleChildNames().contains(child.getQName())) {
- augSchema = potential;
- break allAugments;
- }
- }
- }
- if (augSchema != null) {
- return new AugmentationModificationStrategy(augSchema, resolvedTree);
- }
- return null;
- }
-
- protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
- Optional<ModificationApplyOperation> potential = getChild(child);
- checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
- return potential.get();
- }
-
- @Override
- public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
- if (modification.getModificationType() == ModificationType.WRITE) {
- verifyWritenStructure(modification.getWritenValue());
- }
- }
-
- protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
-
- @Override
- public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
- switch (modification.getModificationType()) {
- case DELETE:
- checkDeleteApplicable(modification, current);
- case SUBTREE_MODIFIED:
- checkSubtreeModificationApplicable(path,modification, current);
- return;
- case WRITE:
- checkWriteApplicable(path,modification, current);
- return;
- case MERGE:
- checkMergeApplicable(path,modification,current);
- return;
- case UNMODIFIED:
- return;
- default:
- throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported.");
- }
-
- }
-
- protected void checkMergeApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
- Optional<StoreMetadataNode> original = modification.getOriginal();
- if (original.isPresent() && current.isPresent()) {
- /*
- * We need to do conflict detection only and only if the value of leaf changed
- * before two transactions. If value of leaf is unchanged between two transactions
- * it should not cause transaction to fail, since result of this merge
- * leads to same data.
- */
- if(!original.get().getData().equals(current.get().getData())) {
-
- checkNotConflicting(path,original.get(), current.get());
- }
- }
- }
-
- protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
- Optional<StoreMetadataNode> original = modification.getOriginal();
- if (original.isPresent() && current.isPresent()) {
- checkNotConflicting(path,original.get(), current.get());
- } else if(original.isPresent()) {
- throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
- }
- }
-
- protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException {
- checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction.");
- checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction");
- }
-
- protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification,
- final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
-
- private void checkDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
- }
-
- @Override
- public final Optional<StoreMetadataNode> apply(final NodeModification modification,
- final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-
- switch (modification.getModificationType()) {
- case DELETE:
- return modification.storeSnapshot(Optional.<StoreMetadataNode> absent());
- case SUBTREE_MODIFIED:
- Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
- modification);
- return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
- subtreeVersion)));
- case MERGE:
- if(currentMeta.isPresent()) {
- return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
- } // Fallback to write is intentional - if node is not preexisting merge is same as write
- case WRITE:
- return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
- case UNMODIFIED:
- return currentMeta;
- default:
- throw new IllegalArgumentException("Provided modification type is not supported.");
- }
- }
-
- protected abstract StoreMetadataNode applyMerge(NodeModification modification,
- StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
-
- protected abstract StoreMetadataNode applyWrite(NodeModification modification,
- Optional<StoreMetadataNode> currentMeta, UnsignedLong subtreeVersion);
-
- protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
- StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
-
- public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends
- SchemaAwareApplyOperation {
-
- private final T schema;
- private final Class<? extends NormalizedNode<?, ?>> nodeClass;
-
- protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
- super();
- this.schema = schema;
- this.nodeClass = nodeClass;
- }
-
- @Override
- protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
- checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
- throw new UnsupportedOperationException("Node " + schema.getPath()
- + "is leaf type node. Child nodes not allowed");
- }
-
- @Override
- protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
- final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
- throw new UnsupportedOperationException("Node " + schema.getPath()
- + "is leaf type node. Subtree change is not allowed.");
- }
-
- @Override
- protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
- final UnsignedLong subtreeVersion) {
- return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
- }
-
- @Override
- protected StoreMetadataNode applyWrite(final NodeModification modification,
- final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
- UnsignedLong nodeVersion = subtreeVersion;
- return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
- .setData(modification.getWritenValue()).build();
- }
-
- @Override
- protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
- final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
- throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
- }
-
- }
-
- public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
- super(schema, (Class) LeafSetEntryNode.class);
- }
- }
-
- public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected LeafModificationStrategy(final LeafSchemaNode schema) {
- super(schema, (Class) LeafNode.class);
- }
- }
-
- public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
-
- private final Class<? extends NormalizedNode<?, ?>> nodeClass;
-
- protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
- this.nodeClass = nodeClass;
- }
-
- @Override
- public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
- if (modification.getModificationType() == ModificationType.WRITE) {
-
- }
- for (NodeModification childModification : modification.getModifications()) {
- resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
- }
- }
-
- @Override
- protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
- final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
- // FIXME: Implement proper write check for replacement of node container
- // prerequisite is to have transaction chain available for clients
- // otherwise this will break chained writes to same node.
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
- checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
- checkArgument(writenValue instanceof NormalizedNodeContainer);
- NormalizedNodeContainer writenCont = (NormalizedNodeContainer) writenValue;
- for (Object child : writenCont.getValue()) {
- checkArgument(child instanceof NormalizedNode);
- NormalizedNode childNode = (NormalizedNode) child;
- }
- }
-
- @Override
- protected StoreMetadataNode applyWrite(final NodeModification modification,
- final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
-
- NormalizedNode<?, ?> newValue = modification.getWritenValue();
-
- final UnsignedLong nodeVersion;
- if (currentMeta.isPresent()) {
- nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
- } else {
- nodeVersion = subtreeVersion;
- }
-
- final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
- if (!modification.hasAdditionalModifications()) {
- return newValueMeta;
- }
-
- @SuppressWarnings("rawtypes")
- NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
- StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) //
- .setNodeVersion(nodeVersion) //
- .setSubtreeVersion(subtreeVersion);
-
- return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion);
- }
-
- @Override
- protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
- final UnsignedLong subtreeVersion) {
- // For Node Containers - merge is same as subtree change - we only replace children.
- return applySubtreeChange(modification, currentMeta, subtreeVersion);
- }
-
- @Override
- public StoreMetadataNode applySubtreeChange(final NodeModification modification,
- final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
- // Bump subtree version to its new target
- final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
-
- @SuppressWarnings("rawtypes")
- NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
- StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder, currentMeta)
- .setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion())
- .setSubtreeVersion(updatedSubtreeVersion);
-
- return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion);
- }
-
- private StoreMetadataNode mutateChildren(final Iterable<NodeModification> modifications, final StoreMetadataNode meta,
- final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) {
-
- for (NodeModification mod : modifications) {
- final PathArgument id = mod.getIdentifier();
- final Optional<StoreMetadataNode> cm = meta.getChild(id);
-
- Optional<StoreMetadataNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
- if (result.isPresent()) {
- builder.add(result.get());
- } else {
- builder.remove(id);
- }
- }
-
- return builder.build();
- }
-
- @Override
- protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
- final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
- checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction.");
- checkChildPreconditions(path,modification,current);
-
- }
-
- private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
- StoreMetadataNode currentMeta = current.get();
- for (NodeModification childMod : modification.getModifications()) {
- PathArgument childId = childMod.getIdentifier();
- Optional<StoreMetadataNode> childMeta = currentMeta.getChild(childId);
- InstanceIdentifier childPath = StoreUtils.append(path, childId);
- resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta);
- }
- }
-
- @Override
- protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
- final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
- if(current.isPresent()) {
- checkChildPreconditions(path,modification,current);
- }
- }
-
- @SuppressWarnings("rawtypes")
- protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
- }
-
- public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
- NormalizedNodeContainerModificationStrategy {
-
- private final T schema;
- private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
- .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
-
- @Override
- public ModificationApplyOperation apply(final PathArgument identifier) {
- if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
- return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
- }
-
- DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
- if (child == null) {
- return null;
- }
- return from(child);
- }
- }));
-
- protected DataNodeContainerModificationStrategy(final T schema,
- final Class<? extends NormalizedNode<?, ?>> nodeClass) {
- super(nodeClass);
- this.schema = schema;
- }
-
- protected T getSchema() {
- return schema;
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- try {
- return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
- } catch (ExecutionException e) {
- return Optional.absent();
- }
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + " [" + schema + "]";
- }
-
- }
-
- public static class ContainerModificationStrategy extends
- DataNodeContainerModificationStrategy<ContainerSchemaNode> {
-
- public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
- super(schemaNode, ContainerNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof ContainerNode);
- return ImmutableContainerNodeBuilder.create((ContainerNode) original);
- }
- }
-
- public static class UnkeyedListItemModificationStrategy extends
- DataNodeContainerModificationStrategy<ListSchemaNode> {
-
- public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
- super(schemaNode, UnkeyedListEntryNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof UnkeyedListEntryNode);
- return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
- }
- }
-
- public static class AugmentationModificationStrategy extends
- DataNodeContainerModificationStrategy<AugmentationSchema> {
-
- protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
- super(createAugmentProxy(schema,resolved), AugmentationNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof AugmentationNode);
- return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
- }
- }
-
- public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final ChoiceNode schema;
- private final Map<PathArgument, ModificationApplyOperation> childNodes;
-
- public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
- super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
- this.schema = schemaNode;
- ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
-
- for (ChoiceCaseNode caze : schemaNode.getCases()) {
- for (DataSchemaNode cazeChild : caze.getChildNodes()) {
- SchemaAwareApplyOperation childNode = from(cazeChild);
- child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
- }
- }
- childNodes = child.build();
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
- return Optional.fromNullable(childNodes.get(child));
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
- return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
- }
- }
-
- public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
-
- protected ListEntryModificationStrategy(final ListSchemaNode schema) {
- super(schema, MapEntryNode.class);
- }
-
- @Override
- @SuppressWarnings("rawtypes")
- protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof MapEntryNode);
- return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
- }
- }
-
- public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
- super((Class) LeafSetNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof LeafSetNode<?>);
- return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeWithValue) {
- return entryStrategy;
- }
- return Optional.absent();
- }
- }
-
- public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
- super((Class) LeafSetNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof OrderedLeafSetNode<?>);
- return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeWithValue) {
- return entryStrategy;
- }
- return Optional.absent();
- }
- }
-
- public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
- entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
- }
-
- @Override
- protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta,
- final UnsignedLong subtreeVersion) {
- return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
- }
-
- @Override
- protected StoreMetadataNode applySubtreeChange(final NodeModification modification,
- final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
- throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
- }
-
- @Override
- protected StoreMetadataNode applyWrite(final NodeModification modification,
- final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
- return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
- if (child instanceof NodeIdentifier) {
- return entryStrategy;
- }
- return Optional.absent();
- }
-
- @Override
- protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
-
- }
-
- @Override
- protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
- final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
- throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
- }
-
- }
-
- public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
- super(MapNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof MapNode);
- return ImmutableMapNodeBuilder.create((MapNode) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeIdentifierWithPredicates) {
- return entryStrategy;
- }
- return Optional.absent();
- }
-
- @Override
- public String toString() {
- return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
- }
- }
-
- public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
-
- private final Optional<ModificationApplyOperation> entryStrategy;
-
- protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
- super(OrderedMapNode.class);
- entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
- checkArgument(original instanceof OrderedMapNode);
- return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
- }
-
- @Override
- public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
- if (identifier instanceof NodeIdentifierWithPredicates) {
- return entryStrategy;
- }
- return Optional.absent();
- }
-
- @Override
- public String toString() {
- return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
- }
- }
-
- public void verifyIdentifier(final PathArgument identifier) {
-
- }
-
- public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
- Set<DataSchemaNode> realChildSchemas = new HashSet<>();
- for(DataSchemaNode augChild : schema.getChildNodes()) {
- realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
- }
- return new AugmentationSchemaProxy(schema, realChildSchemas);
- }
-
- public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException {
- if(!condition) {
- throw new DataPreconditionFailedException(path, message);
- }
- return condition;
- }
-
-}
--- /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.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+public class DataPreconditionFailedException extends Exception {
+ private static final long serialVersionUID = 1L;
+ private final InstanceIdentifier path;
+
+ public DataPreconditionFailedException(final InstanceIdentifier path, final String message) {
+ super(message);
+ this.path = Preconditions.checkNotNull(path);
+ }
+
+ public DataPreconditionFailedException(final InstanceIdentifier path, final String message, final Throwable cause) {
+ super(message, cause);
+ this.path = Preconditions.checkNotNull(path);
+ }
+
+ public InstanceIdentifier getPath() {
+ return path;
+ }
+}
--- /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.tree;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Interface representing a data tree which can be modified in an MVCC fashion.
+ */
+public interface DataTree {
+ /**
+ * Take a read-only point-in-time snapshot of the tree.
+ *
+ * @return Data tree snapshot.
+ */
+ DataTreeSnapshot takeSnapshot();
+
+ /**
+ * Make the data tree use a new schema context. The context will be used
+ * only by subsequent operations.
+ *
+ * @param newSchemaContext new SchemaContext
+ * @throws IllegalArgumentException if the new context is incompatible
+ */
+ void setSchemaContext(SchemaContext newSchemaContext);
+
+ /**
+ * Validate whether a particular modification can be applied to the data tree.
+ */
+ void validate(DataTreeModification modification) throws DataPreconditionFailedException;
+
+ /**
+ * Prepare a modification for commit.
+ *
+ * @param modification
+ * @return candidate data tree
+ */
+ DataTreeCandidate prepare(DataTreeModification modification);
+
+ /**
+ * Commit a data tree candidate.
+ *
+ * @param candidate data tree candidate
+ */
+ void commit(DataTreeCandidate candidate);
+}
--- /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.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public interface DataTreeCandidate {
+ DataTreeCandidateNode getRootNode();
+ InstanceIdentifier getRootPath();
+}
--- /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.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+public interface DataTreeCandidateNode {
+ PathArgument getIdentifier();
+ Iterable<DataTreeCandidateNode> getChildNodes();
+
+ ModificationType getModificationType();
+ Optional<NormalizedNode<?, ?>> getDataAfter();
+ Optional<NormalizedNode<?, ?>> getDataBefore();
+}
--- /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.tree;
+
+/**
+ * Factory interface for creating data trees.
+ */
+public interface DataTreeFactory {
+ /**
+ * Create a new data tree.
+ *
+ * @return A data tree instance.
+ */
+ DataTree create();
+}
--- /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.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Class encapsulation of set of modifications to a base tree. This tree is backed
+ * by a read-only snapshot and tracks modifications on top of that. The modification
+ * has the ability to rebase itself to a new snapshot.
+ */
+public interface DataTreeModification extends DataTreeSnapshot {
+ void delete(InstanceIdentifier path);
+ void merge(InstanceIdentifier path, NormalizedNode<?, ?> data);
+ void write(InstanceIdentifier path, NormalizedNode<?, ?> data);
+ void seal();
+}
--- /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.tree;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+/**
+ * Read-only snapshot of a {@link DataTree}. The snapshot is stable and isolated,
+ * e.g. data tree changes occurring after the snapshot has been taken are not
+ * visible through the snapshot.
+ */
+public interface DataTreeSnapshot {
+ /**
+ * Read a particular node from the snapshot.
+ *
+ * @param path Path of the node
+ * @return Optional result encapsulating the presence and value of the node
+ */
+ Optional<NormalizedNode<?, ?>> readNode(InstanceIdentifier path);
+
+ /**
+ * Create a new data tree modification based on this snapshot, using the
+ * specified data application strategy.
+ *
+ * @param strategy data modification strategy
+ * @return A new data tree modification
+ */
+ DataTreeModification newModification();
+}
+++ /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.tree;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.concepts.Immutable;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.primitives.UnsignedLong;
-
-public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>, StoreTreeNode<StoreMetadataNode> {
-
- private final UnsignedLong nodeVersion;
- private final UnsignedLong subtreeVersion;
- private final NormalizedNode<?, ?> data;
-
- private final Map<PathArgument, StoreMetadataNode> children;
-
- /**
- *
- * @param data
- * @param nodeVersion
- * @param subtreeVersion
- * @param children Map of children, must not be modified externally
- */
- protected StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
- final UnsignedLong subtreeVersion, final Map<PathArgument, StoreMetadataNode> children) {
- this.nodeVersion = nodeVersion;
- this.subtreeVersion = subtreeVersion;
- this.data = data;
- this.children = Preconditions.checkNotNull(children);
- }
-
- public static StoreMetadataNode createEmpty(final NormalizedNode<?, ?> data) {
- return new StoreMetadataNode(data, UnsignedLong.ZERO, UnsignedLong.ZERO,
- Collections.<PathArgument, StoreMetadataNode>emptyMap());
- }
-
- public StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
- final UnsignedLong subtreeVersion) {
- this(data, nodeVersion, subtreeVersion, Collections.<PathArgument, StoreMetadataNode>emptyMap());
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static Builder builder(StoreMetadataNode node) {
- return new Builder(node);
- }
-
- public UnsignedLong getNodeVersion() {
- return this.nodeVersion;
- }
-
- @Override
- public PathArgument getIdentifier() {
- return data.getIdentifier();
- }
-
- public UnsignedLong getSubtreeVersion() {
- return subtreeVersion;
- }
-
- public NormalizedNode<?, ?> getData() {
- return this.data;
- }
-
- @Override
- public Optional<StoreMetadataNode> getChild(final PathArgument key) {
- return Optional.fromNullable(children.get(key));
- }
-
- @Override
- public String toString() {
- return "StoreMetadataNode [identifier=" + getIdentifier() + ", nodeVersion=" + nodeVersion + "]";
- }
-
- public static Optional<UnsignedLong> getVersion(final Optional<StoreMetadataNode> currentMetadata) {
- if (currentMetadata.isPresent()) {
- return Optional.of(currentMetadata.get().getNodeVersion());
- }
- return Optional.absent();
- }
-
- public static Optional<StoreMetadataNode> getChild(final Optional<StoreMetadataNode> parent,
- final PathArgument child) {
- if (parent.isPresent()) {
- return parent.get().getChild(child);
- }
- return Optional.absent();
- }
-
- public static final StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node,
- final UnsignedLong nodeVersion, final UnsignedLong subtreeVersion) {
- Builder builder = builder() //
- .setNodeVersion(nodeVersion) //
- .setSubtreeVersion(subtreeVersion) //
- .setData(node);
- if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
-
- @SuppressWarnings("unchecked")
- NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> nodeContainer = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) node;
- for (NormalizedNode<?, ?> subNode : nodeContainer.getValue()) {
- builder.add(createRecursively(subNode, nodeVersion, subtreeVersion));
- }
- }
- return builder.build();
- }
-
- public static class Builder {
-
- private UnsignedLong nodeVersion;
- private UnsignedLong subtreeVersion;
- private NormalizedNode<?, ?> data;
- private Map<PathArgument, StoreMetadataNode> children;
- private boolean dirty = false;
-
- private Builder() {
- children = new HashMap<>();
- }
-
- public Builder(StoreMetadataNode node) {
- children = new HashMap<>(node.children);
- }
-
- public UnsignedLong getVersion() {
- return nodeVersion;
-
- }
-
- public Builder setNodeVersion(final UnsignedLong version) {
- this.nodeVersion = version;
- return this;
- }
-
- public Builder setSubtreeVersion(final UnsignedLong version) {
- this.subtreeVersion = version;
- return this;
- }
-
- public Builder setData(final NormalizedNode<?, ?> data) {
- this.data = data;
- return this;
- }
-
- public Builder add(final StoreMetadataNode node) {
- if (dirty) {
- children = new HashMap<>(children);
- dirty = false;
- }
- children.put(node.getIdentifier(), node);
- return this;
- }
-
- public Builder remove(final PathArgument id) {
- if (dirty) {
- children = new HashMap<>(children);
- dirty = false;
- }
- children.remove(id);
- return this;
- }
-
- public StoreMetadataNode build() {
- checkState(data != null, "Data node should not be null.");
- checkState(subtreeVersion.compareTo(nodeVersion) >= 0,
- "Subtree version must be equals or greater than node version.");
- dirty = true;
- return new StoreMetadataNode(data, nodeVersion, subtreeVersion, children);
- }
- }
-
- public static StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node, final UnsignedLong version) {
- return createRecursively(node, version, version);
- }
-}
+++ /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.tree;
-
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-
-import com.google.common.base.Preconditions;
-import com.google.common.primitives.UnsignedLong;
-
-/**
- *
- * Helper builder
- *
- *
- */
-@SuppressWarnings("rawtypes")
-public class StoreNodeCompositeBuilder {
-
- private final StoreMetadataNode.Builder metadata;
-
- private final NormalizedNodeContainerBuilder data;
-
- private StoreNodeCompositeBuilder(final NormalizedNodeContainerBuilder nodeBuilder) {
- this.metadata = StoreMetadataNode.builder();
- this.data = Preconditions.checkNotNull(nodeBuilder);
- }
-
- public StoreNodeCompositeBuilder(NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) {
- this.metadata = StoreMetadataNode.builder(currentMeta);
- this.data = Preconditions.checkNotNull(nodeBuilder);
- }
-
- @SuppressWarnings("unchecked")
- public StoreNodeCompositeBuilder add(final StoreMetadataNode node) {
- metadata.add(node);
- data.addChild(node.getData());
- return this;
- }
-
- @SuppressWarnings("unchecked")
- public StoreNodeCompositeBuilder remove(PathArgument id) {
- metadata.remove(id);
- data.removeChild(id);
- return this;
- }
-
- public StoreMetadataNode build() {
- return metadata.setData(data.build()).build();
- }
-
- public static StoreNodeCompositeBuilder from(final NormalizedNodeContainerBuilder nodeBuilder) {
- return new StoreNodeCompositeBuilder(nodeBuilder);
- }
-
- public static StoreNodeCompositeBuilder from(final NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) {
- return new StoreNodeCompositeBuilder(nodeBuilder, currentMeta);
- }
-
- @SuppressWarnings("unchecked")
- public StoreNodeCompositeBuilder setIdentifier(final PathArgument identifier) {
- data.withNodeIdentifier(identifier);
- return this;
- }
-
- public StoreNodeCompositeBuilder setNodeVersion(final UnsignedLong nodeVersion) {
- metadata.setNodeVersion(nodeVersion);
- return this;
- }
-
- public StoreNodeCompositeBuilder setSubtreeVersion(final UnsignedLong updatedSubtreeVersion) {
- metadata.setSubtreeVersion(updatedSubtreeVersion);
- return this;
- }
-}
* 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;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree;
import java.util.Set;
--- /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.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+abstract class AbstractDataTreeCandidate implements DataTreeCandidate {
+ private final InstanceIdentifier rootPath;
+
+ protected AbstractDataTreeCandidate(final InstanceIdentifier rootPath) {
+ this.rootPath = Preconditions.checkNotNull(rootPath);
+ }
+
+ @Override
+ public final InstanceIdentifier getRootPath() {
+ return rootPath;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+
+import com.google.common.base.Optional;
+
+/**
+ * An implementation of apply operation which fails to do anything,
+ * consistently. An instance of this class is used by the data tree
+ * if it does not have a SchemaContext attached and hence cannot
+ * perform anything meaningful.
+ */
+final class AlwaysFailOperation implements ModificationApplyOperation {
+ @Override
+ public Optional<TreeNode> apply(final ModifiedNode modification,
+ final Optional<TreeNode> storeMeta, final Version subtreeVersion) {
+ throw new IllegalStateException("Schema Context is not available.");
+ }
+
+ @Override
+ public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> storeMetadata) {
+ throw new IllegalStateException("Schema Context is not available.");
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+ throw new IllegalStateException("Schema Context is not available.");
+ }
+
+ @Override
+ public void verifyStructure(final ModifiedNode modification) {
+ throw new IllegalStateException("Schema Context is not available.");
+ }
+}
\ No newline at end of file
--- /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.tree.data;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+
+/**
+ * Base strategy for applying changes to a ContainerNode, irrespective of its
+ * actual type.
+ *
+ * @param <T> Type of the container node
+ */
+abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends NormalizedNodeContainerModificationStrategy {
+
+ private final T schema;
+ private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
+ .build(CacheLoader.from(new Function<PathArgument, ModificationApplyOperation>() {
+
+ @Override
+ public ModificationApplyOperation apply(final PathArgument identifier) {
+ if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
+ return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier);
+ }
+
+ DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType());
+ if (child == null) {
+ return null;
+ }
+ return from(child);
+ }
+ }));
+
+ protected DataNodeContainerModificationStrategy(final T schema,
+ final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+ super(nodeClass);
+ this.schema = schema;
+ }
+
+ protected T getSchema() {
+ return schema;
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+ try {
+ return Optional.<ModificationApplyOperation> fromNullable(childCache.get(identifier));
+ } catch (ExecutionException e) {
+ return Optional.absent();
+ }
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " [" + schema + "]";
+ }
+
+ public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy<AugmentationSchema> {
+
+ protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
+ super(createAugmentProxy(schema,resolved), AugmentationNode.class);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof AugmentationNode);
+ return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
+ }
+
+
+ private static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
+ Set<DataSchemaNode> realChildSchemas = new HashSet<>();
+ for(DataSchemaNode augChild : schema.getChildNodes()) {
+ realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
+ }
+ return new AugmentationSchemaProxy(schema, realChildSchemas);
+ }
+ }
+
+ public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
+
+ public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
+ super(schemaNode, ContainerNode.class);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof ContainerNode);
+ return ImmutableContainerNodeBuilder.create((ContainerNode) original);
+ }
+ }
+
+ public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
+
+ protected ListEntryModificationStrategy(final ListSchemaNode schema) {
+ super(schema, MapEntryNode.class);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof MapEntryNode);
+ return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
+ }
+ }
+
+ public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
+
+ public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
+ super(schemaNode, UnkeyedListEntryNode.class);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof UnkeyedListEntryNode);
+ return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
+ }
+ }
+}
\ No newline at end of file
--- /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.tree.data;
+
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * Read-only snapshot of the data tree.
+ */
+final class InMemoryDataTree implements DataTree {
+ private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTree.class);
+ private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
+
+ private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
+ private ModificationApplyOperation applyOper = new AlwaysFailOperation();
+ private SchemaContext currentSchemaContext;
+ private TreeNode rootNode;
+
+ public InMemoryDataTree(final TreeNode rootNode, final SchemaContext schemaContext) {
+ this.rootNode = Preconditions.checkNotNull(rootNode);
+
+ if (schemaContext != null) {
+ // Also sets applyOper
+ setSchemaContext(schemaContext);
+ }
+ }
+
+ @Override
+ 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.
+ */
+
+ // Instantiate new apply operation, this still may fail
+ final ModificationApplyOperation newApplyOper = SchemaAwareApplyOperation.from(newSchemaContext);
+
+ // Ready to change the context now, make sure no operations are running
+ rwLock.writeLock().lock();
+ try {
+ this.applyOper = newApplyOper;
+ this.currentSchemaContext = newSchemaContext;
+ } finally {
+ rwLock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public InMemoryDataTreeSnapshot takeSnapshot() {
+ rwLock.readLock().lock();
+ try {
+ return new InMemoryDataTreeSnapshot(currentSchemaContext, rootNode, applyOper);
+ } finally {
+ rwLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public void validate(final DataTreeModification modification) throws DataPreconditionFailedException {
+ Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
+
+ final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
+ m.getStrategy().checkApplicable(PUBLIC_ROOT_PATH, m.getRootModification(), Optional.<TreeNode>of(rootNode));
+ }
+
+ @Override
+ public synchronized DataTreeCandidate prepare(final DataTreeModification modification) {
+ Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
+
+ final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
+ final ModifiedNode root = m.getRootModification();
+
+ if (root.getType() == ModificationType.UNMODIFIED) {
+ return new NoopDataTreeCandidate(PUBLIC_ROOT_PATH, root);
+ }
+
+ rwLock.writeLock().lock();
+ try {
+ final Optional<TreeNode> newRoot = m.getStrategy().apply(m.getRootModification(),
+ Optional.<TreeNode>of(rootNode), rootNode.getSubtreeVersion().next());
+ Preconditions.checkState(newRoot.isPresent(), "Apply strategy failed to produce root node");
+ return new InMemoryDataTreeCandidate(PUBLIC_ROOT_PATH, root, rootNode, newRoot.get());
+ } finally {
+ rwLock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public synchronized void commit(final DataTreeCandidate candidate) {
+ if (candidate instanceof NoopDataTreeCandidate) {
+ return;
+ }
+
+ Preconditions.checkArgument(candidate instanceof InMemoryDataTreeCandidate, "Invalid candidate class %s", candidate.getClass());
+ final InMemoryDataTreeCandidate c = (InMemoryDataTreeCandidate)candidate;
+
+ LOG.debug("Updating datastore from {} to {}", rootNode, c.getAfterRoot());
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Data Tree is {}", StoreUtils.toStringTree(c.getAfterRoot().getData()));
+ }
+
+ // Ready to change the context now, make sure no operations are running
+ rwLock.writeLock().lock();
+ try {
+ Preconditions.checkState(c.getBeforeRoot() == rootNode,
+ String.format("Store tree %s and candidate base %s differ.", rootNode, c.getBeforeRoot()));
+ this.rootNode = c.getAfterRoot();
+ } finally {
+ rwLock.writeLock().unlock();
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+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 com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate {
+ private static abstract class AbstractNode implements DataTreeCandidateNode {
+ private final ModifiedNode mod;
+ private final TreeNode newMeta;
+ private final TreeNode oldMeta;
+
+ protected AbstractNode(final ModifiedNode mod,
+ final TreeNode oldMeta, final TreeNode newMeta) {
+ this.newMeta = newMeta;
+ this.oldMeta = oldMeta;
+ this.mod = Preconditions.checkNotNull(mod);
+ }
+
+ protected final ModifiedNode getMod() {
+ return mod;
+ }
+
+ protected final TreeNode getNewMeta() {
+ return newMeta;
+ }
+
+ protected final TreeNode getOldMeta() {
+ return oldMeta;
+ }
+
+ private static final TreeNode childMeta(final TreeNode parent, final PathArgument id) {
+ if (parent != null) {
+ return parent.getChild(id).orNull();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Iterable<DataTreeCandidateNode> getChildNodes() {
+ return Iterables.transform(mod.getChildren(), new Function<ModifiedNode, DataTreeCandidateNode>() {
+ @Override
+ public DataTreeCandidateNode apply(final ModifiedNode input) {
+ final PathArgument id = input.getIdentifier();
+ return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id));
+ }
+ });
+ }
+
+ @Override
+ public ModificationType getModificationType() {
+ return mod.getType();
+ }
+
+ private Optional<NormalizedNode<?, ?>> optionalData(final TreeNode meta) {
+ if (meta != null) {
+ return Optional.<NormalizedNode<?,?>>of(meta.getData());
+ } else {
+ return Optional.absent();
+ }
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> getDataAfter() {
+ return optionalData(newMeta);
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> getDataBefore() {
+ return optionalData(oldMeta);
+ }
+ }
+
+ private static final class ChildNode extends AbstractNode {
+ public ChildNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) {
+ super(mod, oldMeta, newMeta);
+ }
+
+ @Override
+ public PathArgument getIdentifier() {
+ return getMod().getIdentifier();
+ }
+ }
+
+ private static final class RootNode extends AbstractNode {
+ public RootNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) {
+ super(mod, oldMeta, newMeta);
+ }
+
+ @Override
+ public PathArgument getIdentifier() {
+ throw new IllegalStateException("Attempted to get identifier of the root node");
+ }
+ }
+
+ private final RootNode root;
+
+ InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot,
+ final TreeNode beforeRoot, final TreeNode afterRoot) {
+ super(rootPath);
+ this.root = new RootNode(modificationRoot, beforeRoot, afterRoot);
+ }
+
+ TreeNode getAfterRoot() {
+ return root.getNewMeta();
+ }
+
+ TreeNode getBeforeRoot() {
+ return root.getOldMeta();
+ }
+
+ @Override
+ public DataTreeCandidateNode getRootNode() {
+ return root;
+ }
+}
--- /dev/null
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+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;
+
+/**
+ * A factory for creating in-memory data trees.
+ */
+public final class InMemoryDataTreeFactory implements DataTreeFactory {
+ private static final InMemoryDataTreeFactory INSTANCE = new InMemoryDataTreeFactory();
+
+ private InMemoryDataTreeFactory() {
+ // Never instantiated externally
+ }
+
+ @Override
+ public InMemoryDataTree create() {
+ final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME);
+ final NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(root).build();
+
+ return new InMemoryDataTree(TreeNodeFactory.createTreeNode(data, Version.initial()), null);
+ }
+
+ /**
+ * Get an instance of this factory. This method cannot fail.
+ *
+ * @return Data tree factory instance.
+ */
+ public static final InMemoryDataTreeFactory getInstance() {
+ return INSTANCE;
+ }
+}
--- /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.tree.data;
+
+import java.util.Map.Entry;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+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.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+final class InMemoryDataTreeModification implements DataTreeModification {
+ private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTreeModification.class);
+ private final ModificationApplyOperation strategyTree;
+ private final InMemoryDataTreeSnapshot snapshot;
+ private final ModifiedNode rootNode;
+
+ @GuardedBy("this")
+ private boolean sealed = false;
+
+ InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final ModificationApplyOperation resolver) {
+ this.snapshot = Preconditions.checkNotNull(snapshot);
+ this.strategyTree = Preconditions.checkNotNull(resolver);
+ this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode());
+ }
+
+ ModifiedNode getRootModification() {
+ return rootNode;
+ }
+
+ ModificationApplyOperation getStrategy() {
+ return strategyTree;
+ }
+
+ @Override
+ public synchronized void write(final InstanceIdentifier path, final NormalizedNode<?, ?> value) {
+ checkSealed();
+ resolveModificationFor(path).write(value);
+ }
+
+ @Override
+ public synchronized void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ checkSealed();
+ mergeImpl(resolveModificationFor(path),data);
+ }
+
+ private void mergeImpl(final OperationWithModification op,final NormalizedNode<?,?> data) {
+
+ if(data instanceof NormalizedNodeContainer<?,?,?>) {
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ NormalizedNodeContainer<?,?,NormalizedNode<PathArgument, ?>> dataContainer = (NormalizedNodeContainer) data;
+ for(NormalizedNode<PathArgument, ?> child : dataContainer.getValue()) {
+ PathArgument childId = child.getIdentifier();
+ mergeImpl(op.forChild(childId), child);
+ }
+ }
+ op.merge(data);
+ }
+
+ @Override
+ public synchronized void delete(final InstanceIdentifier path) {
+ checkSealed();
+ resolveModificationFor(path).delete();
+ }
+
+ @Override
+ public synchronized Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
+ /*
+ * Walk the tree from the top, looking for the first node between root and
+ * the requested path which has been modified. If no such node exists,
+ * we use the node itself.
+ */
+ final Entry<InstanceIdentifier, ModifiedNode> entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, ModifiedNode.IS_TERMINAL_PREDICATE);
+ final InstanceIdentifier key = entry.getKey();
+ final ModifiedNode mod = entry.getValue();
+
+ final Optional<TreeNode> result = resolveSnapshot(key, mod);
+ if (result.isPresent()) {
+ NormalizedNode<?, ?> data = result.get().getData();
+ return NormalizedNodeUtils.findNode(key, data, path);
+ } else {
+ return Optional.absent();
+ }
+ }
+
+ private Optional<TreeNode> resolveSnapshot(final InstanceIdentifier path,
+ final ModifiedNode modification) {
+ final Optional<Optional<TreeNode>> potentialSnapshot = modification.getSnapshotCache();
+ if(potentialSnapshot.isPresent()) {
+ return potentialSnapshot.get();
+ }
+
+ try {
+ return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
+ snapshot.getRootNode().getSubtreeVersion().next());
+ } catch (Exception e) {
+ LOG.error("Could not create snapshot for {}:{}", path,modification,e);
+ throw e;
+ }
+ }
+
+ private ModificationApplyOperation resolveModificationStrategy(final InstanceIdentifier path) {
+ LOG.trace("Resolving modification apply strategy for {}", path);
+ return TreeNodeUtils.findNodeChecked(strategyTree, path);
+ }
+
+ private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
+ ModifiedNode modification = rootNode;
+ // We ensure strategy is present.
+ ModificationApplyOperation operation = resolveModificationStrategy(path);
+ for (PathArgument pathArg : path.getPath()) {
+ modification = modification.modifyChild(pathArg);
+ }
+ return OperationWithModification.from(operation, modification);
+ }
+
+ @Override
+ public synchronized void seal() {
+ Preconditions.checkState(!sealed, "Attempted to seal an already-sealed Data Tree.");
+ sealed = true;
+ rootNode.seal();
+ }
+
+ @GuardedBy("this")
+ private void checkSealed() {
+ Preconditions.checkState(!sealed, "Data Tree is sealed. No further modifications allowed.");
+ }
+
+ @Override
+ public String toString() {
+ return "MutableDataTree [modification=" + rootNode + "]";
+ }
+
+ @Override
+ public synchronized DataTreeModification newModification() {
+ Preconditions.checkState(sealed, "Attempted to chain on an unsealed modification");
+
+ // FIXME: transaction chaining
+ throw new UnsupportedOperationException("Implement this as part of transaction chaining");
+ }
+}
--- /dev/null
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+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 com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+final class InMemoryDataTreeSnapshot implements DataTreeSnapshot {
+ private final ModificationApplyOperation applyOper;
+ private final SchemaContext schemaContext;
+ private final TreeNode rootNode;
+
+ InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final TreeNode rootNode,
+ final ModificationApplyOperation applyOper) {
+ this.schemaContext = Preconditions.checkNotNull(schemaContext);
+ this.rootNode = Preconditions.checkNotNull(rootNode);
+ this.applyOper = Preconditions.checkNotNull(applyOper);
+ }
+
+ TreeNode getRootNode() {
+ return rootNode;
+ }
+
+ SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
+ return NormalizedNodeUtils.findNode(rootNode.getData(), path);
+ }
+
+ @Override
+ public InMemoryDataTreeModification newModification() {
+ return new InMemoryDataTreeModification(this, applyOper);
+ }
+
+ @Override
+ public String toString() {
+ return rootNode.getSubtreeVersion().toString();
+ }
+
+}
\ No newline at end of file
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.md.sal.dom.store.impl;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import com.google.common.base.Optional;
-import com.google.common.primitives.UnsignedLong;
/**
*
- * Operation responsible for applying {@link NodeModification} on tree.
+ * Operation responsible for applying {@link ModifiedNode} on tree.
*
* Operation is composite - operation on top level node consists of
* suboperations on child nodes. This allows to walk operation hierarchy and
* Implementations MUST expose all nested suboperations which operates on child
* nodes expose via {@link #getChild(PathArgument)} method.
* <li>Same suboperations SHOULD be used when invoked via
- * {@link #apply(NodeModification, Optional)} if applicable.
+ * {@link #apply(ModifiedNode, Optional)} if applicable.
*
*
* Hierarchical composite operation which is responsible for applying
*
*
*/
-public interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
+interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
/**
*
* If it is not possible to apply Operation on provided Metadata
* node
* @return new {@link StoreMetadataNode} if operation resulted in updating
- * node, {@link Optional#absent()} if {@link NodeModification}
+ * node, {@link Optional#absent()} if {@link ModifiedNode}
* resulted in deletion of this node.
*/
- Optional<StoreMetadataNode> apply(NodeModification modification, Optional<StoreMetadataNode> storeMeta, UnsignedLong subtreeVersion);
+ Optional<TreeNode> apply(ModifiedNode modification, Optional<TreeNode> storeMeta, Version subtreeVersion);
/**
*
* @param modification to be verified.
* @throws IllegalArgumentException If provided NodeModification does not adhere to the structure.
*/
- void verifyStructure(NodeModification modification) throws IllegalArgumentException;
+ void verifyStructure(ModifiedNode modification) throws IllegalArgumentException;
/**
* Returns a suboperation for specified tree node
Optional<ModificationApplyOperation> getChild(PathArgument child);
/**
- *
- * Checks if provided node modification could be applied to current metadata node.
- *
- * @param modification Modification
- * @param current Metadata Node to which modification should be applied
- * @return true if modification is applicable
- * false if modification is no applicable
+ *
+ * Checks if provided node modification could be applied to current metadata node.
+ *
+ * @param modification Modification
+ * @param current Metadata Node to which modification should be applied
+ * @return true if modification is applicable
+ * false if modification is no applicable
* @throws DataPreconditionFailedException
- */
- void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
+ */
+ void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<TreeNode> current) throws DataPreconditionFailedException;
}
* 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.tree;
-
-import static com.google.common.base.Preconditions.checkState;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
*
* This tree is lazily created and populated via {@link #modifyChild(PathArgument)}
* and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
- *
*/
-public class NodeModification implements StoreTreeNode<NodeModification>, Identifiable<PathArgument> {
+final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<PathArgument>, NodeModification {
- public static final Predicate<NodeModification> IS_TERMINAL_PREDICATE = new Predicate<NodeModification>() {
+ public static final Predicate<ModifiedNode> IS_TERMINAL_PREDICATE = new Predicate<ModifiedNode>() {
@Override
- public boolean apply(final NodeModification input) {
- return input.getModificationType() == ModificationType.WRITE //
- || input.getModificationType() == ModificationType.DELETE //
- || input.getModificationType() == ModificationType.MERGE;
+ public boolean apply(final ModifiedNode input) {
+ switch (input.getType()) {
+ case DELETE:
+ case MERGE:
+ case WRITE:
+ return true;
+ case SUBTREE_MODIFIED:
+ case UNMODIFIED:
+ return false;
+ }
+
+ throw new IllegalArgumentException(String.format("Unhandled modification type %s", input.getType()));
}
};
+
+ private final Map<PathArgument, ModifiedNode> children = new LinkedHashMap<>();
+ private final Optional<TreeNode> original;
private final PathArgument identifier;
private ModificationType modificationType = ModificationType.UNMODIFIED;
-
-
- private final Optional<StoreMetadataNode> original;
-
+ private Optional<TreeNode> snapshotCache;
private NormalizedNode<?, ?> value;
- private Optional<StoreMetadataNode> snapshotCache;
-
- private final Map<PathArgument, NodeModification> childModification;
-
- @GuardedBy("this")
- private boolean sealed = false;
-
- protected NodeModification(final PathArgument identifier, final Optional<StoreMetadataNode> original) {
+ private ModifiedNode(final PathArgument identifier, final Optional<TreeNode> original) {
this.identifier = identifier;
this.original = original;
- childModification = new LinkedHashMap<>();
}
/**
*
* @return
*/
- public NormalizedNode<?, ?> getWritenValue() {
+ public NormalizedNode<?, ?> getWrittenValue() {
return value;
}
* Returns original store metadata
* @return original store metadata
*/
- public final Optional<StoreMetadataNode> getOriginal() {
+ @Override
+ public Optional<TreeNode> getOriginal() {
return original;
}
*
* @return modification type
*/
- public final ModificationType getModificationType() {
+ @Override
+ public ModificationType getType() {
return modificationType;
}
*
*/
@Override
- public Optional<NodeModification> getChild(final PathArgument child) {
- return Optional.<NodeModification> fromNullable(childModification.get(child));
+ public Optional<ModifiedNode> getChild(final PathArgument child) {
+ return Optional.<ModifiedNode> fromNullable(children.get(child));
}
/**
*
- * Returns child modification if child was modified, creates {@link NodeModification}
+ * Returns child modification if child was modified, creates {@link ModifiedNode}
* for child otherwise.
*
* If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED}
* changes modification type to {@link ModificationType#SUBTREE_MODIFIED}
*
* @param child
- * @return {@link NodeModification} for specified child, with {@link #getOriginal()}
- * containing child metadata if child was present in original data.
+ * @return {@link ModifiedNode} for specified child, with {@link #getOriginal()}
+ * containing child metadata if child was present in original data.
*/
- public synchronized NodeModification modifyChild(final PathArgument child) {
- checkSealed();
+ public ModifiedNode modifyChild(final PathArgument child) {
clearSnapshot();
- if(modificationType == ModificationType.UNMODIFIED) {
+ if (modificationType == ModificationType.UNMODIFIED) {
updateModificationType(ModificationType.SUBTREE_MODIFIED);
}
- final NodeModification potential = childModification.get(child);
+ final ModifiedNode potential = children.get(child);
if (potential != null) {
return potential;
}
- Optional<StoreMetadataNode> currentMetadata = Optional.absent();
- if(original.isPresent()) {
- currentMetadata = original.get().getChild(child);
+
+ final Optional<TreeNode> currentMetadata;
+ if (original.isPresent()) {
+ final TreeNode orig = original.get();
+ currentMetadata = orig.getChild(child);
+ } else {
+ currentMetadata = Optional.absent();
}
- NodeModification newlyCreated = new NodeModification(child,currentMetadata);
- childModification.put(child, newlyCreated);
+
+ ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata);
+ children.put(child, newlyCreated);
return newlyCreated;
}
*
* @return all recorded direct child modifications
*/
- public Iterable<NodeModification> getModifications() {
- return childModification.values();
+ @Override
+ public Iterable<ModifiedNode> getChildren() {
+ return children.values();
}
-
/**
*
* Records a delete for associated node.
*
*/
- public synchronized void delete() {
- checkSealed();
+ public void delete() {
clearSnapshot();
updateModificationType(ModificationType.DELETE);
- childModification.clear();
+ children.clear();
this.value = null;
}
*
* @param value
*/
- public synchronized void write(final NormalizedNode<?, ?> value) {
- checkSealed();
+ public void write(final NormalizedNode<?, ?> value) {
clearSnapshot();
updateModificationType(ModificationType.WRITE);
- childModification.clear();
+ children.clear();
this.value = value;
}
- public synchronized void merge(final NormalizedNode<?, ?> data) {
- checkSealed();
+ public void merge(final NormalizedNode<?, ?> data) {
clearSnapshot();
updateModificationType(ModificationType.MERGE);
// FIXME: Probably merge with previous value.
this.value = data;
}
- @GuardedBy("this")
- private void checkSealed() {
- checkState(!sealed, "Node Modification is sealed. No further changes allowed.");
- }
-
- public synchronized void seal() {
- sealed = true;
+ void seal() {
clearSnapshot();
- for(NodeModification child : childModification.values()) {
+ for (ModifiedNode child : children.values()) {
child.seal();
}
}
snapshotCache = null;
}
- public Optional<StoreMetadataNode> storeSnapshot(final Optional<StoreMetadataNode> snapshot) {
+ public Optional<TreeNode> storeSnapshot(final Optional<TreeNode> snapshot) {
snapshotCache = snapshot;
return snapshot;
}
- public Optional<Optional<StoreMetadataNode>> getSnapshotCache() {
+ public Optional<Optional<TreeNode>> getSnapshotCache() {
return Optional.fromNullable(snapshotCache);
}
- public boolean hasAdditionalModifications() {
- return !childModification.isEmpty();
- }
-
@GuardedBy("this")
private void updateModificationType(final ModificationType type) {
modificationType = type;
@Override
public String toString() {
return "NodeModification [identifier=" + identifier + ", modificationType="
- + modificationType + ", childModification=" + childModification + "]";
+ + modificationType + ", childModification=" + children + "]";
}
- public static NodeModification createUnmodified(final StoreMetadataNode metadataTree) {
- return new NodeModification(metadataTree.getIdentifier(), Optional.of(metadataTree));
+ public static ModifiedNode createUnmodified(final TreeNode metadataTree) {
+ return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree));
}
-
}
--- /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.tree.data;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+
+import com.google.common.base.Optional;
+
+interface NodeModification extends Identifiable<PathArgument> {
+ ModificationType getType();
+ Optional<TreeNode> getOriginal();
+ Iterable<? extends NodeModification> getChildren();
+}
--- /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.tree.data;
+
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+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 com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+final class NoopDataTreeCandidate extends AbstractDataTreeCandidate {
+ private static final DataTreeCandidateNode ROOT = new DataTreeCandidateNode() {
+ @Override
+ public ModificationType getModificationType() {
+ return ModificationType.UNMODIFIED;
+ }
+
+ @Override
+ public Iterable<DataTreeCandidateNode> getChildNodes() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public PathArgument getIdentifier() {
+ throw new IllegalStateException("Attempted to read identifier of the no-operation change");
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> getDataAfter() {
+ return Optional.absent();
+ }
+
+ @Override
+ public Optional<NormalizedNode<?, ?>> getDataBefore() {
+ return Optional.absent();
+ }
+ };
+
+ protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot) {
+ super(rootPath);
+ Preconditions.checkArgument(modificationRoot.getType() == ModificationType.UNMODIFIED);
+ }
+
+ @Override
+ public DataTreeCandidateNode getRootNode() {
+ return ROOT;
+ }
+}
--- /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.tree.data;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ListEntryModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafSetEntryModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.MutableTreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
+
+ private final Class<? extends NormalizedNode<?, ?>> nodeClass;
+
+ protected NormalizedNodeContainerModificationStrategy(final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+ this.nodeClass = nodeClass;
+ }
+
+ @Override
+ public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+ if (modification.getType() == ModificationType.WRITE) {
+
+ }
+ for (ModifiedNode childModification : modification.getChildren()) {
+ resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification);
+ }
+ }
+
+ @Override
+ protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
+ final Optional<TreeNode> current) throws DataPreconditionFailedException {
+ // FIXME: Implement proper write check for replacement of node container
+ // prerequisite is to have transaction chain available for clients
+ // otherwise this will break chained writes to same node.
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+ checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
+ checkArgument(writtenValue instanceof NormalizedNodeContainer);
+
+ NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue;
+ for (Object child : container.getValue()) {
+ checkArgument(child instanceof NormalizedNode);
+
+ /*
+ * FIXME: fail-fast semantics:
+ *
+ * We can validate the data structure here, aborting the commit
+ * before it ever progresses to being committed.
+ */
+ }
+ }
+
+ @Override
+ protected TreeNode applyWrite(final ModifiedNode modification,
+ final Optional<TreeNode> currentMeta, final Version subtreeVersion) {
+ final Version nodeVersion;
+ if (currentMeta.isPresent()) {
+ nodeVersion = currentMeta.get().getVersion().next();
+ } else {
+ nodeVersion = subtreeVersion;
+ }
+
+ final NormalizedNode<?, ?> newValue = modification.getWrittenValue();
+ final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, nodeVersion);
+
+ if (Iterables.isEmpty(modification.getChildren())) {
+ return newValueMeta;
+ }
+
+ /*
+ * This is where things get interesting. The user has performed a write and
+ * then she applied some more modifications to it. So we need to make sense
+ * of that an apply the operations on top of the written value. We could have
+ * done it during the write, but this operation is potentially expensive, so
+ * we have left it out of the fast path.
+ *
+ * As it turns out, once we materialize the written data, we can share the
+ * code path with the subtree change. So let's create an unsealed TreeNode
+ * and run the common parts on it -- which end with the node being sealed.
+ */
+ final MutableTreeNode mutable = newValueMeta.mutable();
+ mutable.setSubtreeVersion(subtreeVersion);
+
+ @SuppressWarnings("rawtypes")
+ final NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
+
+ return mutateChildren(mutable, dataBuilder, nodeVersion, modification.getChildren());
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data,
+ final Version nodeVersion, final Iterable<ModifiedNode> modifications) {
+
+ for (ModifiedNode mod : modifications) {
+ final PathArgument id = mod.getIdentifier();
+ final Optional<TreeNode> cm = meta.getChild(id);
+
+ Optional<TreeNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
+ if (result.isPresent()) {
+ final TreeNode tn = result.get();
+ meta.addChild(tn);
+ data.addChild(tn.getData());
+ } else {
+ meta.removeChild(id);
+ data.removeChild(id);
+ }
+ }
+
+ meta.setData(data.build());
+ return meta.seal();
+ }
+
+ @Override
+ protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+ final Version subtreeVersion) {
+ // For Node Containers - merge is same as subtree change - we only replace children.
+ return applySubtreeChange(modification, currentMeta, subtreeVersion);
+ }
+
+ @Override
+ public TreeNode applySubtreeChange(final ModifiedNode modification,
+ final TreeNode currentMeta, final Version subtreeVersion) {
+ // Bump subtree version to its new target
+ final Version updatedSubtreeVersion = currentMeta.getSubtreeVersion().next();
+
+ final MutableTreeNode newMeta = currentMeta.mutable();
+ newMeta.setSubtreeVersion(updatedSubtreeVersion);
+
+ @SuppressWarnings("rawtypes")
+ NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
+
+ return mutateChildren(newMeta, dataBuilder, updatedSubtreeVersion, modification.getChildren());
+ }
+
+ @Override
+ protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+ final Optional<TreeNode> current) throws DataPreconditionFailedException {
+ checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction.");
+ checkChildPreconditions(path, modification, current);
+ }
+
+ private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+ final TreeNode currentMeta = current.get();
+ for (NodeModification childMod : modification.getChildren()) {
+ final PathArgument childId = childMod.getIdentifier();
+ final Optional<TreeNode> childMeta = currentMeta.getChild(childId);
+
+ InstanceIdentifier childPath = StoreUtils.append(path, childId);
+ resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta);
+ }
+ }
+
+ @Override
+ protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
+ final Optional<TreeNode> current) throws DataPreconditionFailedException {
+ if(current.isPresent()) {
+ checkChildPreconditions(path, modification,current);
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
+
+ public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+ private final Map<PathArgument, ModificationApplyOperation> childNodes;
+
+ public ChoiceModificationStrategy(final ChoiceNode schemaNode) {
+ super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class);
+ ImmutableMap.Builder<PathArgument, ModificationApplyOperation> child = ImmutableMap.builder();
+
+ for (ChoiceCaseNode caze : schemaNode.getCases()) {
+ for (DataSchemaNode cazeChild : caze.getChildNodes()) {
+ SchemaAwareApplyOperation childNode = from(cazeChild);
+ child.put(new NodeIdentifier(cazeChild.getQName()), childNode);
+ }
+ }
+ childNodes = child.build();
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+ return Optional.fromNullable(childNodes.get(child));
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
+ return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
+ }
+ }
+
+ public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
+ super((Class) LeafSetNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof OrderedLeafSetNode<?>);
+ return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+ if (identifier instanceof NodeWithValue) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+ }
+
+ public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ protected OrderedMapModificationStrategy(final ListSchemaNode schema) {
+ super(OrderedMapNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof OrderedMapNode);
+ return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+ if (identifier instanceof NodeIdentifierWithPredicates) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ public String toString() {
+ return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]";
+ }
+ }
+
+ public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) {
+ super((Class) LeafSetNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new LeafSetEntryModificationStrategy(schema));
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof LeafSetNode<?>);
+ return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+ if (identifier instanceof NodeWithValue) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+ }
+
+ public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy {
+
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ protected UnorderedMapModificationStrategy(final ListSchemaNode schema) {
+ super(MapNode.class);
+ entryStrategy = Optional.<ModificationApplyOperation> of(new ListEntryModificationStrategy(schema));
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof MapNode);
+ return ImmutableMapNodeBuilder.create((MapNode) original);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
+ if (identifier instanceof NodeIdentifierWithPredicates) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ public String toString() {
+ return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]";
+ }
+ }
+}
* 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;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import com.google.common.base.Optional;
-import com.google.common.primitives.UnsignedLong;
-public class OperationWithModification {
+final class OperationWithModification {
- private final NodeModification modification;
+ private final ModifiedNode modification;
private final ModificationApplyOperation applyOperation;
- private OperationWithModification(final ModificationApplyOperation op, final NodeModification mod) {
+ private OperationWithModification(final ModificationApplyOperation op, final ModifiedNode mod) {
this.modification = mod;
this.applyOperation = op;
}
return this;
}
- public NodeModification getModification() {
+ public ModifiedNode getModification() {
return modification;
}
return applyOperation;
}
- public Optional<StoreMetadataNode> apply(final Optional<StoreMetadataNode> data, final UnsignedLong subtreeVersion) {
+ public Optional<TreeNode> apply(final Optional<TreeNode> data, final Version subtreeVersion) {
return applyOperation.apply(modification, data, subtreeVersion);
}
public static OperationWithModification from(final ModificationApplyOperation operation,
- final NodeModification modification) {
+ final ModifiedNode modification) {
return new OperationWithModification(operation, modification);
}
}
public OperationWithModification forChild(final PathArgument childId) {
- NodeModification childMod = modification.modifyChild(childId);
+ ModifiedNode childMod = modification.modifyChild(childId);
Optional<ModificationApplyOperation> childOp = applyOperation.getChild(childId);
return from(childOp.get(),childMod);
}
--- /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.tree.data;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ContainerModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.ChoiceModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedLeafSetModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedMapModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.UnorderedLeafSetModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafModificationStrategy;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
+ private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class);
+
+ public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
+ if (schemaNode instanceof ContainerSchemaNode) {
+ return new ContainerModificationStrategy((ContainerSchemaNode) schemaNode);
+ } else if (schemaNode instanceof ListSchemaNode) {
+ return fromListSchemaNode((ListSchemaNode) schemaNode);
+ } else if (schemaNode instanceof ChoiceNode) {
+ return new ChoiceModificationStrategy((ChoiceNode) schemaNode);
+ } else if (schemaNode instanceof LeafListSchemaNode) {
+ return fromLeafListSchemaNode((LeafListSchemaNode) schemaNode);
+ } else if (schemaNode instanceof LeafSchemaNode) {
+ return new LeafModificationStrategy((LeafSchemaNode) schemaNode);
+ }
+ throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass());
+ }
+
+ public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree,
+ final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) {
+ AugmentationSchema augSchema = null;
+
+ allAugments:
+ for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) {
+ for (DataSchemaNode child : potential.getChildNodes()) {
+ if (identifier.getPossibleChildNames().contains(child.getQName())) {
+ augSchema = potential;
+ break allAugments;
+ }
+ }
+ }
+
+ if (augSchema != null) {
+ return new DataNodeContainerModificationStrategy.AugmentationModificationStrategy(augSchema, resolvedTree);
+ }
+ return null;
+ }
+
+ public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException {
+ if(!condition) {
+ throw new DataPreconditionFailedException(path, message);
+ }
+ return condition;
+ }
+
+ private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) {
+ List<QName> keyDefinition = schemaNode.getKeyDefinition();
+ if (keyDefinition == null || keyDefinition.isEmpty()) {
+ return new UnkeyedListModificationStrategy(schemaNode);
+ }
+ if (schemaNode.isUserOrdered()) {
+ return new OrderedMapModificationStrategy(schemaNode);
+ }
+
+ return new NormalizedNodeContainerModificationStrategy.UnorderedMapModificationStrategy(schemaNode);
+ }
+
+ private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) {
+ if(schemaNode.isUserOrdered()) {
+ return new OrderedLeafSetModificationStrategy(schemaNode);
+ } else {
+ return new UnorderedLeafSetModificationStrategy(schemaNode);
+ }
+ }
+
+ private static final void checkNotConflicting(final InstanceIdentifier path, final TreeNode original, final TreeNode current) throws DataPreconditionFailedException {
+ checkDataPrecondition(path, original.getVersion().equals(current.getVersion()),
+ "Node was replaced by other transaction.");
+ checkDataPrecondition(path, original.getSubtreeVersion().equals(current.getSubtreeVersion()),
+ "Node children was modified by other transaction");
+ }
+
+ protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) {
+ Optional<ModificationApplyOperation> potential = getChild(child);
+ checkArgument(potential.isPresent(), "Operation for child %s is not defined.", child);
+ return potential.get();
+ }
+
+ @Override
+ public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException {
+ if (modification.getType() == ModificationType.WRITE) {
+ verifyWrittenStructure(modification.getWrittenValue());
+ }
+ }
+
+ @Override
+ public final void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+ switch (modification.getType()) {
+ case DELETE:
+ checkDeleteApplicable(modification, current);
+ case SUBTREE_MODIFIED:
+ checkSubtreeModificationApplicable(path, modification, current);
+ return;
+ case WRITE:
+ checkWriteApplicable(path, modification, current);
+ return;
+ case MERGE:
+ checkMergeApplicable(path, modification, current);
+ return;
+ case UNMODIFIED:
+ return;
+ default:
+ throw new UnsupportedOperationException("Suplied modification type "+ modification.getType()+ "is not supported.");
+ }
+
+ }
+
+ protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+ Optional<TreeNode> original = modification.getOriginal();
+ if (original.isPresent() && current.isPresent()) {
+ /*
+ * We need to do conflict detection only and only if the value of leaf changed
+ * before two transactions. If value of leaf is unchanged between two transactions
+ * it should not cause transaction to fail, since result of this merge
+ * leads to same data.
+ */
+ if(!original.get().getData().equals(current.get().getData())) {
+ checkNotConflicting(path, original.get(), current.get());
+ }
+ }
+ }
+
+ protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional<TreeNode> current) throws DataPreconditionFailedException {
+ Optional<TreeNode> original = modification.getOriginal();
+ if (original.isPresent() && current.isPresent()) {
+ checkNotConflicting(path, original.get(), current.get());
+ } else if(original.isPresent()) {
+ throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
+ }
+ }
+
+ private void checkDeleteApplicable(final NodeModification modification, final Optional<TreeNode> current) {
+ // Delete is always applicable, we do not expose it to subclasses
+ if (current.isPresent()) {
+ LOG.trace("Delete operation turned to no-op on missing node {}", modification);
+ }
+ }
+
+ @Override
+ public final Optional<TreeNode> apply(final ModifiedNode modification,
+ final Optional<TreeNode> currentMeta, final Version subtreeVersion) {
+
+ switch (modification.getType()) {
+ case DELETE:
+ return modification.storeSnapshot(Optional.<TreeNode> absent());
+ case SUBTREE_MODIFIED:
+ Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification",
+ modification);
+ return modification.storeSnapshot(Optional.of(applySubtreeChange(modification, currentMeta.get(),
+ subtreeVersion)));
+ case MERGE:
+ if(currentMeta.isPresent()) {
+ return modification.storeSnapshot(Optional.of(applyMerge(modification,currentMeta.get(),subtreeVersion)));
+ } // Fallback to write is intentional - if node is not preexisting merge is same as write
+ case WRITE:
+ return modification.storeSnapshot(Optional.of(applyWrite(modification, currentMeta, subtreeVersion)));
+ case UNMODIFIED:
+ return currentMeta;
+ default:
+ throw new IllegalArgumentException("Provided modification type is not supported.");
+ }
+ }
+
+ protected abstract TreeNode applyMerge(ModifiedNode modification,
+ TreeNode currentMeta, Version subtreeVersion);
+
+ protected abstract TreeNode applyWrite(ModifiedNode modification,
+ Optional<TreeNode> currentMeta, Version subtreeVersion);
+
+ protected abstract TreeNode applySubtreeChange(ModifiedNode modification,
+ TreeNode currentMeta, Version subtreeVersion);
+
+ protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path, final NodeModification modification,
+ final Optional<TreeNode> current) throws DataPreconditionFailedException;
+
+ protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
+
+ public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
+
+ private final Optional<ModificationApplyOperation> entryStrategy;
+
+ protected UnkeyedListModificationStrategy(final ListSchemaNode schema) {
+ entryStrategy = Optional.<ModificationApplyOperation> of(new UnkeyedListItemModificationStrategy(schema));
+ }
+
+ @Override
+ protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+ final Version subtreeVersion) {
+ return applyWrite(modification, Optional.of(currentMeta), subtreeVersion);
+ }
+
+ @Override
+ protected TreeNode applySubtreeChange(final ModifiedNode modification,
+ final TreeNode currentMeta, final Version subtreeVersion) {
+ throw new UnsupportedOperationException("UnkeyedList does not support subtree change.");
+ }
+
+ @Override
+ protected TreeNode applyWrite(final ModifiedNode modification,
+ final Optional<TreeNode> currentMeta, final Version subtreeVersion) {
+ return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), subtreeVersion);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+ if (child instanceof NodeIdentifier) {
+ return entryStrategy;
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+
+ }
+
+ @Override
+ protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+ final Optional<TreeNode> current) throws DataPreconditionFailedException {
+ throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
+ }
+ }
+}
--- /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.tree.data;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
+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.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+import com.google.common.base.Optional;
+
+abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
+
+ private final T schema;
+ private final Class<? extends NormalizedNode<?, ?>> nodeClass;
+
+ protected ValueNodeModificationStrategy(final T schema, final Class<? extends NormalizedNode<?, ?>> nodeClass) {
+ super();
+ this.schema = schema;
+ this.nodeClass = nodeClass;
+ }
+
+ @Override
+ protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+ checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
+ }
+
+ @Override
+ public Optional<ModificationApplyOperation> getChild(final PathArgument child) {
+ throw new UnsupportedOperationException("Node " + schema.getPath()
+ + "is leaf type node. Child nodes not allowed");
+ }
+
+ @Override
+ protected TreeNode applySubtreeChange(final ModifiedNode modification,
+ final TreeNode currentMeta, final Version subtreeVersion) {
+ throw new UnsupportedOperationException("Node " + schema.getPath()
+ + "is leaf type node. Subtree change is not allowed.");
+ }
+
+ @Override
+ protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta,
+ final Version subtreeVersion) {
+ // Just overwrite whatever was there
+ return applyWrite(modification, null, subtreeVersion);
+ }
+
+ @Override
+ protected TreeNode applyWrite(final ModifiedNode modification,
+ final Optional<TreeNode> currentMeta, final Version subtreeVersion) {
+ return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), subtreeVersion);
+ }
+
+ @Override
+ protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification,
+ final Optional<TreeNode> current) throws DataPreconditionFailedException {
+ throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
+ }
+
+ public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy<LeafListSchemaNode> {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) {
+ super(schema, (Class) LeafSetEntryNode.class);
+ }
+ }
+
+ public static class LeafModificationStrategy extends ValueNodeModificationStrategy<LeafSchemaNode> {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected LeafModificationStrategy(final LeafSchemaNode schema) {
+ super(schema, (Class) LeafNode.class);
+ }
+ }
+}
\ No newline at end of file
--- /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.tree.spi;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Preconditions;
+
+/*
+ * A very basic data tree node.
+ */
+abstract class AbstractTreeNode implements TreeNode {
+ private final NormalizedNode<?, ?> data;
+ private final Version version;
+
+ protected AbstractTreeNode(final NormalizedNode<?, ?> data, final Version version) {
+ this.data = Preconditions.checkNotNull(data);
+ this.version = Preconditions.checkNotNull(version);
+ }
+
+ @Override
+ public PathArgument getIdentifier() {
+ return data.getIdentifier();
+ }
+
+ @Override
+ public final Version getVersion() {
+ return version;
+ }
+
+ @Override
+ public final NormalizedNode<?, ?> getData() {
+ return data;
+ }
+}
--- /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.tree.spi;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * A TreeNode capable of holding child nodes. The fact that any of the children
+ * changed is tracked by the subtree version.
+ */
+final class ContainerNode extends AbstractTreeNode {
+ private final Map<PathArgument, TreeNode> children;
+ private final Version subtreeVersion;
+
+ protected ContainerNode(final NormalizedNode<?, ?> data, final Version version,
+ final Map<PathArgument, TreeNode> children, final Version subtreeVersion) {
+ super(data, version);
+ this.children = Preconditions.checkNotNull(children);
+ this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
+ }
+
+ @Override
+ public Version getSubtreeVersion() {
+ return subtreeVersion;
+ }
+
+ @Override
+ public Optional<TreeNode> getChild(final PathArgument key) {
+ return Optional.fromNullable(children.get(key));
+ }
+
+ @Override
+ public MutableTreeNode mutable() {
+ return new Mutable(this);
+ }
+
+ private static final class Mutable implements MutableTreeNode {
+ private final Map<PathArgument, TreeNode> children;
+ private final Version version;
+ private NormalizedNode<?, ?> data;
+ private Version subtreeVersion;
+
+ private Mutable(final ContainerNode parent) {
+ this.data = parent.getData();
+ this.children = new HashMap<>(parent.children);
+ this.subtreeVersion = parent.getSubtreeVersion();
+ this.version = parent.getVersion();
+ }
+
+ @Override
+ public Optional<TreeNode> getChild(final PathArgument child) {
+ return Optional.fromNullable(children.get(child));
+ }
+
+ @Override
+ public void setSubtreeVersion(final Version subtreeVersion) {
+ this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
+ }
+
+ @Override
+ public void addChild(final TreeNode child) {
+ children.put(child.getIdentifier(), child);
+ }
+
+ @Override
+ public void removeChild(final PathArgument id) {
+ children.remove(id);
+ }
+
+ @Override
+ public TreeNode seal() {
+ final Map<PathArgument, TreeNode> realChildren;
+
+ if (children.isEmpty()) {
+ realChildren = Collections.emptyMap();
+ } else {
+ realChildren = children;
+ }
+
+ return new ContainerNode(data, version, realChildren, subtreeVersion);
+ }
+
+ @Override
+ public void setData(final NormalizedNode<?, ?> data) {
+ this.data = Preconditions.checkNotNull(data);
+ }
+ }
+
+ private static ContainerNode create(final Version version, final NormalizedNode<?, ?> data,
+ final Iterable<NormalizedNode<?, ?>> children) {
+ final Map<PathArgument, TreeNode> map = new HashMap<>();
+
+ for (NormalizedNode<?, ?> child : children) {
+ map.put(child.getIdentifier(), TreeNodeFactory.createTreeNode(child, version));
+ }
+
+ return new ContainerNode(data, version, map, version);
+ }
+
+ public static ContainerNode create(final Version version, final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container) {
+ return create(version, container, container.getValue());
+ }
+
+ public static ContainerNode create(final Version version, final OrderedNodeContainer<NormalizedNode<?, ?>> container) {
+ return create(version, container, container.getValue());
+ }
+}
--- /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.tree.spi;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface MutableTreeNode extends StoreTreeNode<TreeNode> {
+ void setData(NormalizedNode<?, ?> data);
+ void setSubtreeVersion(Version subtreeVersion);
+ void addChild(TreeNode child);
+ void removeChild(PathArgument id);
+ TreeNode seal();
+}
--- /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.tree.spi;
+
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/*
+ * A very basic data tree node. It has a version (when it was last modified),
+ * a subtree version (when any of its children were modified) and some read-only
+ * data.
+ */
+public interface TreeNode extends Identifiable<PathArgument>, StoreTreeNode<TreeNode> {
+ /**
+ * Get the data node version.
+ *
+ * @return Current data node version.
+ */
+ Version getVersion();
+
+ /**
+ * Get the subtree version.
+ *
+ * @return Current subtree version.
+ */
+ Version getSubtreeVersion();
+
+ /**
+ * Get a read-only view of the underlying data.
+ *
+ * @return Unmodifiable view of the underlying data.
+ */
+ NormalizedNode<?, ?> getData();
+
+ /**
+ * Get a mutable, isolated copy of the node.
+ *
+ * @return Mutable copy
+ */
+ MutableTreeNode mutable();
+}
--- /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.tree.spi;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer;
+
+public final class TreeNodeFactory {
+ private TreeNodeFactory() {
+ throw new UnsupportedOperationException("Utility class should not be instantiated");
+ }
+
+ /**
+ * Create a new AbstractTreeNode from a data node, descending recursively as needed.
+ * This method should only ever be used for new data.
+ *
+ * @param data data node
+ * @param version data node version
+ * @return new AbstractTreeNode instance, covering the data tree provided
+ */
+ public static final TreeNode createTreeNode(final NormalizedNode<?, ?> data, final Version version) {
+ if (data instanceof NormalizedNodeContainer<?, ?, ?>) {
+ @SuppressWarnings("unchecked")
+ NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> container = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) data;
+ return ContainerNode.create(version, container);
+
+ }
+ if (data instanceof OrderedNodeContainer<?>) {
+ @SuppressWarnings("unchecked")
+ OrderedNodeContainer<NormalizedNode<?, ?>> container = (OrderedNodeContainer<NormalizedNode<?, ?>>) data;
+ return ContainerNode.create(version, container);
+ }
+
+ return new ValueNode(data, version);
+ }
+}
--- /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.tree.spi;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+final class ValueNode extends AbstractTreeNode {
+ private static final Logger LOG = LoggerFactory.getLogger(ValueNode.class);
+
+ protected ValueNode(final NormalizedNode<?, ?> data, final Version version) {
+ super(data, version);
+ }
+
+ @Override
+ public Optional<TreeNode> getChild(final PathArgument childId) {
+ LOG.warn("Attempted to access child {} of value-node {}", childId, this);
+ return Optional.absent();
+ }
+
+ @Override
+ public Version getSubtreeVersion() {
+ return getVersion();
+ }
+
+ @Override
+ public MutableTreeNode mutable() {
+ /**
+ * Value nodes can only we read/written/delete, which does a straight
+ * replace. That means they don't haver need to be made mutable.
+ */
+ throw new UnsupportedOperationException(String.format("Attempted to mutate value-node %s", this));
+ }
+}
--- /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.tree.spi;
+
+/**
+ * The concept of a version, either node version, or a subtree version. The
+ * only interface contract this class has is that no two versions are the
+ * same.
+ */
+public final class Version {
+ private Version() {
+
+ }
+
+ /**
+ * Create a new version, distinct from any other version.
+ *
+ * @return a new version.
+ */
+ public Version next() {
+ return new Version();
+ }
+
+ /**
+ * Create an initial version.
+ *
+ * @return a new version.
+ */
+ public static final Version initial() {
+ return new Version();
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.util.Hashtable;
+
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProviders;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+public class BrokerConfigActivator implements AutoCloseable {
+
+ private static InstanceIdentifier ROOT = InstanceIdentifier.builder()
+ .toInstance();
+
+ private DataProviderService dataService;
+
+ private ServiceRegistration<DataBrokerService> dataReg = null;
+ private ServiceRegistration<DataProviderService> dataProviderReg = null;
+ private ServiceRegistration<MountService> mountReg = null;
+ private ServiceRegistration<MountProvisionService> mountProviderReg = null;
+ private SchemaService schemaService = null;
+ private ServiceRegistration<RpcProvisionRegistry> rpcProvisionRegistryReg = null;
+ private MountPointManagerImpl mountService = null;
+
+ private SchemaAwareDataStoreAdapter wrappedStore = null;
+
+ public void start(final BrokerImpl broker, final DataStore store,
+ final DOMDataBroker asyncBroker, final BundleContext context) {
+
+ final Hashtable<String, String> emptyProperties = new Hashtable<String, String>();
+ broker.setBundleContext(context);
+
+ final ServiceReference<SchemaService> serviceRef = context
+ .getServiceReference(SchemaService.class);
+ schemaService = context.<SchemaService> getService(serviceRef);
+
+ broker.setRouter(new SchemaAwareRpcBroker("/", SchemaContextProviders
+ .fromSchemaService(schemaService)));
+
+ if (asyncBroker == null) {
+ dataService = new DataBrokerImpl();
+ dataProviderReg = context.registerService(
+ DataProviderService.class, dataService, emptyProperties);
+
+ wrappedStore = new SchemaAwareDataStoreAdapter();
+ wrappedStore.changeDelegate(store);
+ wrappedStore.setValidationEnabled(false);
+ context.registerService(SchemaServiceListener.class, wrappedStore,
+ emptyProperties);
+
+ dataService.registerConfigurationReader(ROOT, wrappedStore);
+ dataService.registerCommitHandler(ROOT, wrappedStore);
+ dataService.registerOperationalReader(ROOT, wrappedStore);
+ } else {
+ BackwardsCompatibleDataBroker compatibleDataBroker = new BackwardsCompatibleDataBroker(
+ asyncBroker);
+ context.registerService(SchemaServiceListener.class,
+ compatibleDataBroker, emptyProperties);
+ dataService = compatibleDataBroker;
+ }
+
+ mountService = new MountPointManagerImpl();
+ dataReg = context.registerService(DataBrokerService.class, dataService,
+ emptyProperties);
+ mountReg = context.registerService(MountService.class, mountService,
+ emptyProperties);
+ mountProviderReg = context.registerService(MountProvisionService.class,
+ mountService, emptyProperties);
+
+ rpcProvisionRegistryReg = context
+ .registerService(RpcProvisionRegistry.class,
+ broker.getRouter(), emptyProperties);
+ }
+
+ @Override
+ public void close() {
+
+ if (dataReg != null) {
+ dataReg.unregister();
+ dataReg = null;
+ }
+ if (dataProviderReg != null) {
+ dataProviderReg.unregister();
+ dataProviderReg = null;
+ }
+ if (mountReg != null) {
+ mountReg.unregister();
+ mountReg = null;
+ }
+ if (mountProviderReg != null) {
+ mountProviderReg.unregister();
+ mountProviderReg = null;
+ }
+ if (rpcProvisionRegistryReg != null) {
+ rpcProvisionRegistryReg.unregister();
+ rpcProvisionRegistryReg = null;
+ }
+ }
+
+ /**
+ * @return the dataService
+ */
+ public DataProviderService getDataService() {
+ return dataService;
+ }
+
+ /**
+ * @param dataService
+ * the dataService to set
+ */
+ public void setDataService(final DataProviderService dataService) {
+ this.dataService = dataService;
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.dom.broker
-
-import java.util.Hashtable
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.core.api.data.DataProviderService
-import org.opendaylight.controller.sal.core.api.data.DataStore
-import org.opendaylight.controller.sal.core.api.model.SchemaService
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
-import org.opendaylight.controller.sal.core.api.mount.MountService
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.osgi.framework.BundleContext
-import org.osgi.framework.ServiceRegistration
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProviders
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
-import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker
-import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl
-import com.google.common.util.concurrent.MoreExecutors
-import com.google.common.collect.ImmutableMap
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType
-import org.opendaylight.controller.sal.core.spi.data.DOMStore
-import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore
-import java.util.concurrent.Executors
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker
-
-class BrokerConfigActivator implements AutoCloseable {
-
- private static val ROOT = InstanceIdentifier.builder().toInstance();
-
- @Property
- private var DataProviderService dataService;
-
- private var ServiceRegistration<DataBrokerService> dataReg;
- private var ServiceRegistration<DataProviderService> dataProviderReg;
- private var ServiceRegistration<MountService> mountReg;
- private var ServiceRegistration<MountProvisionService> mountProviderReg;
- private var SchemaService schemaService;
- private var ServiceRegistration<RpcProvisionRegistry> rpcProvisionRegistryReg;
- private var MountPointManagerImpl mountService;
-
- SchemaAwareDataStoreAdapter wrappedStore
-
- public def void start(BrokerImpl broker, DataStore store, DOMDataBroker asyncBroker,BundleContext context) {
- val emptyProperties = new Hashtable<String, String>();
- broker.setBundleContext(context);
-
- val serviceRef = context.getServiceReference(SchemaService);
- schemaService = context.getService(serviceRef);
-
- broker.setRouter(new SchemaAwareRpcBroker("/", SchemaContextProviders.fromSchemaService(schemaService)));
-
-
- if(asyncBroker == null) {
- dataService = new DataBrokerImpl();
- dataProviderReg = context.registerService(DataProviderService, dataService, emptyProperties);
-
- wrappedStore = new SchemaAwareDataStoreAdapter();
- wrappedStore.changeDelegate(store);
- wrappedStore.setValidationEnabled(false);
- context.registerService(SchemaServiceListener, wrappedStore, emptyProperties)
-
- dataService.registerConfigurationReader(ROOT, wrappedStore);
- dataService.registerCommitHandler(ROOT, wrappedStore);
- dataService.registerOperationalReader(ROOT, wrappedStore);
- } else {
- val compatibleDataBroker = new BackwardsCompatibleDataBroker(asyncBroker);
- context.registerService(SchemaServiceListener,compatibleDataBroker,emptyProperties);
- dataService = compatibleDataBroker;
- }
-
-
-//
-
- mountService = new MountPointManagerImpl();
- dataReg = context.registerService(DataBrokerService, dataService, emptyProperties);
- mountReg = context.registerService(MountService, mountService, emptyProperties);
- mountProviderReg = context.registerService(MountProvisionService, mountService, emptyProperties);
-
- rpcProvisionRegistryReg = context.registerService(RpcProvisionRegistry, broker.getRouter(), emptyProperties);
- }
-
- override def close() {
- dataReg?.unregister();
- dataProviderReg?.unregister();
- mountReg?.unregister();
- mountProviderReg?.unregister();
- rpcProvisionRegistryReg?.unregister();
- }
-
-}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.dom.broker;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Consumer;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
+
+public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
+ private final static Logger log = LoggerFactory.getLogger(BrokerImpl.class);
+
+ // Broker Generic Context
+ private final Set<ConsumerContextImpl> sessions = Collections
+ .synchronizedSet(new HashSet<ConsumerContextImpl>());
+ private final Set<ProviderContextImpl> providerSessions = Collections
+ .synchronizedSet(new HashSet<ProviderContextImpl>());
+
+ private BundleContext bundleContext = null;
+
+ private AutoCloseable deactivator = null;
+
+ private RpcRouter router = null;
+
+ @Override
+ public ConsumerSession registerConsumer(final Consumer consumer,
+ final BundleContext ctx) {
+ checkPredicates(consumer);
+ log.trace("Registering consumer {}", consumer);
+ final ConsumerContextImpl session = newSessionFor(consumer, ctx);
+ consumer.onSessionInitiated(session);
+ sessions.add(session);
+ return session;
+ }
+
+ @Override
+ public ProviderSession registerProvider(final Provider provider,
+ final BundleContext ctx) {
+ checkPredicates(provider);
+ final ProviderContextImpl session = newSessionFor(provider, ctx);
+ provider.onSessionInitiated(session);
+ providerSessions.add(session);
+ return session;
+ }
+
+ protected Future<RpcResult<CompositeNode>> invokeRpcAsync(final QName rpc,
+ final CompositeNode input) {
+ return router.invokeRpc(rpc, input);
+ }
+
+ // Validation
+ private void checkPredicates(final Provider prov) {
+ Preconditions.checkNotNull(prov, "Provider should not be null.");
+ for (ProviderContextImpl session : providerSessions) {
+ if (prov.equals(session.getProvider()))
+ throw new IllegalStateException("Provider already registered");
+ }
+
+ }
+
+ private void checkPredicates(final Consumer cons) {
+ Preconditions.checkNotNull(cons, "Consumer should not be null.");
+ for (ConsumerContextImpl session : sessions) {
+ if (cons.equals(session.getConsumer()))
+ throw new IllegalStateException("Consumer already registered");
+ }
+ }
+
+ // Private Factory methods
+ private ConsumerContextImpl newSessionFor(final Consumer provider,
+ final BundleContext ctx) {
+ ConsumerContextImpl ret = new ConsumerContextImpl(provider, ctx);
+ ret.setBroker(this);
+ return ret;
+ }
+
+ private ProviderContextImpl newSessionFor(final Provider provider,
+ final BundleContext ctx) {
+ ProviderContextImpl ret = new ProviderContextImpl(provider, ctx);
+ ret.setBroker(this);
+ return ret;
+ }
+
+ protected void consumerSessionClosed(
+ final ConsumerContextImpl consumerContextImpl) {
+ sessions.remove(consumerContextImpl);
+ providerSessions.remove(consumerContextImpl);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (deactivator != null) {
+ deactivator.close();
+ deactivator = null;
+ }
+ }
+
+ @Override
+ public RpcRegistration addRpcImplementation(final QName rpcType,
+ final RpcImplementation implementation)
+ throws IllegalArgumentException {
+ return router.addRpcImplementation(rpcType, implementation);
+ }
+
+ @Override
+ public RoutedRpcRegistration addRoutedRpcImplementation(
+ final QName rpcType, final RpcImplementation implementation) {
+ return router.addRoutedRpcImplementation(rpcType, implementation);
+ }
+
+ @Override
+ public void setRoutedRpcDefaultDelegate(
+ final RoutedRpcDefaultImplementation defaultImplementation) {
+ router.setRoutedRpcDefaultDelegate(defaultImplementation);
+ }
+
+ @Override
+ public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
+ final RpcRegistrationListener listener) {
+ return router.addRpcRegistrationListener(listener);
+ }
+
+ @Override
+ public <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(
+ final L listener) {
+ return router.registerRouteChangeListener(listener);
+ }
+
+ @Override
+ public Set<QName> getSupportedRpcs() {
+ return router.getSupportedRpcs();
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(
+ final QName rpc, final CompositeNode input) {
+ return router.invokeRpc(rpc, input);
+ }
+
+ /**
+ * @return the bundleContext
+ */
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ /**
+ * @param bundleContext
+ * the bundleContext to set
+ */
+ public void setBundleContext(final BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ /**
+ * @return the deactivator
+ */
+ public AutoCloseable getDeactivator() {
+ return deactivator;
+ }
+
+ /**
+ * @param deactivator
+ * the deactivator to set
+ */
+ public void setDeactivator(final AutoCloseable deactivator) {
+ this.deactivator = deactivator;
+ }
+
+ /**
+ * @return the router
+ */
+ public RpcRouter getRouter() {
+ return router;
+ }
+
+ /**
+ * @param router
+ * the router to set
+ */
+ public void setRouter(final RpcRouter router) {
+ this.router = router;
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.dom.broker;
-
-import com.google.common.util.concurrent.ListenableFuture
-import java.util.Collections
-import java.util.HashSet
-import java.util.Set
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener
-import org.opendaylight.controller.sal.core.api.Broker
-import org.opendaylight.controller.sal.core.api.Consumer
-import org.opendaylight.controller.sal.core.api.Provider
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.osgi.framework.BundleContext
-import org.slf4j.LoggerFactory
-import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
-import org.opendaylight.controller.sal.core.api.RpcImplementation
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation
-
-public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
- private static val log = LoggerFactory.getLogger(BrokerImpl);
-
- // Broker Generic Context
- private val Set<ConsumerContextImpl> sessions = Collections.synchronizedSet(new HashSet<ConsumerContextImpl>());
- private val Set<ProviderContextImpl> providerSessions = Collections.synchronizedSet(
- new HashSet<ProviderContextImpl>());
-
- @Property
- private var BundleContext bundleContext;
-
- @Property
- private var AutoCloseable deactivator;
-
- @Property
- private var RpcRouter router;
-
- override registerConsumer(Consumer consumer, BundleContext ctx) {
- checkPredicates(consumer);
- log.trace("Registering consumer " + consumer);
- val session = newSessionFor(consumer, ctx);
- consumer.onSessionInitiated(session);
- sessions.add(session);
- return session;
- }
-
- override registerProvider(Provider provider, BundleContext ctx) {
- checkPredicates(provider);
-
- val session = newSessionFor(provider, ctx);
- provider.onSessionInitiated(session);
- providerSessions.add(session);
- return session;
- }
-
- protected def ListenableFuture<RpcResult<CompositeNode>> invokeRpcAsync(QName rpc, CompositeNode input) {
- return router.invokeRpc(rpc, input);
- }
-
- // Validation
- private def void checkPredicates(Provider prov) {
- if (prov == null)
- throw new IllegalArgumentException("Provider should not be null.");
- for (ProviderContextImpl session : providerSessions) {
- if (prov.equals(session.getProvider()))
- throw new IllegalStateException("Provider already registered");
- }
-
- }
-
- private def void checkPredicates(Consumer cons) {
- if (cons == null)
- throw new IllegalArgumentException("Consumer should not be null.");
- for (ConsumerContextImpl session : sessions) {
- if (cons.equals(session.getConsumer()))
- throw new IllegalStateException("Consumer already registered");
- }
- }
-
- // Private Factory methods
- private def ConsumerContextImpl newSessionFor(Consumer provider, BundleContext ctx) {
- val ret = new ConsumerContextImpl(provider, ctx);
- ret.broker = this;
- return ret;
- }
-
- private def ProviderContextImpl newSessionFor(Provider provider, BundleContext ctx) {
- val ret = new ProviderContextImpl(provider, ctx);
- ret.broker = this;
- return ret;
- }
-
- protected def void consumerSessionClosed(ConsumerContextImpl consumerContextImpl) {
- sessions.remove(consumerContextImpl);
- providerSessions.remove(consumerContextImpl);
- }
-
- override close() throws Exception {
- deactivator?.close();
- }
-
- override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException {
- router.addRpcImplementation(rpcType,implementation);
- }
-
- override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
- router.addRoutedRpcImplementation(rpcType,implementation);
- }
-
- override setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultImplementation) {
- router.setRoutedRpcDefaultDelegate(defaultImplementation);
- }
-
- override addRpcRegistrationListener(RpcRegistrationListener listener) {
- return router.addRpcRegistrationListener(listener);
- }
-
- override <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> registerRouteChangeListener(L listener) {
- return router.registerRouteChangeListener(listener);
- }
-
- override getSupportedRpcs() {
- return router.getSupportedRpcs();
- }
-
- override invokeRpc(QName rpc, CompositeNode input) {
- return router.invokeRpc(rpc,input)
- }
-
-}
--- /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.sal.dom.broker;
+
+import java.util.Collection;
+import java.util.concurrent.Future;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.controller.sal.core.api.Consumer;
+import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy;
+import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.MutableClassToInstanceMap;
+
+class ConsumerContextImpl implements ConsumerSession {
+
+ private final ClassToInstanceMap<BrokerService> instantiatedServices = MutableClassToInstanceMap
+ .create();
+ private final BundleContext context;
+ private final Consumer consumer;
+
+ private BrokerImpl broker = null;
+ @GuardedBy("this")
+ private boolean closed = false;
+
+ public ConsumerContextImpl(final Consumer consumer, final BundleContext ctx) {
+ this.consumer = consumer;
+ this.context = ctx;
+ }
+
+ @Override
+ public Future<RpcResult<CompositeNode>> rpc(final QName rpc,
+ final CompositeNode input) {
+ return broker.invokeRpcAsync(rpc, input);
+ }
+
+ @Override
+ public <T extends BrokerService> T getService(final Class<T> service) {
+ final T localProxy = instantiatedServices.getInstance(service);
+ if (localProxy != null) {
+ return localProxy;
+ }
+ final ServiceReference<T> serviceRef = context
+ .getServiceReference(service);
+ if (serviceRef == null) {
+ return null;
+ }
+ final T serviceImpl = context.getService(serviceRef);
+ final T ret = ProxyFactory.createProxy(serviceRef, serviceImpl);
+ if (ret != null) {
+ instantiatedServices.putInstance(service, ret);
+ }
+ return ret;
+ }
+
+ @Override
+ public void close() {
+ synchronized (this) {
+ if (closed) {
+ return;
+ }
+ this.closed = true;
+ }
+
+ Collection<BrokerService> toStop = instantiatedServices.values();
+ for (BrokerService brokerService : toStop) {
+ if (brokerService instanceof AbstractBrokerServiceProxy<?>) {
+ ((AbstractBrokerServiceProxy<?>) brokerService).close();
+ }
+ }
+ broker.consumerSessionClosed(this);
+ }
+
+ @Override
+ public synchronized boolean isClosed() {
+ return closed;
+ }
+
+ /**
+ * @return the broker
+ */
+ public BrokerImpl getBroker() {
+ return broker;
+ }
+
+ /**
+ * @param broker
+ * the broker to set
+ */
+ public void setBroker(final BrokerImpl broker) {
+ this.broker = broker;
+ }
+
+ /**
+ * @return the _consumer
+ */
+ public Consumer getConsumer() {
+ return consumer;
+ }
+}
+++ /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.sal.dom.broker
-
-import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
-import org.opendaylight.controller.sal.core.api.BrokerService
-import org.opendaylight.controller.sal.core.api.Consumer
-import org.osgi.framework.BundleContext
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy
-import com.google.common.collect.ClassToInstanceMap
-import com.google.common.collect.MutableClassToInstanceMap
-import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory
-
-class ConsumerContextImpl implements ConsumerSession {
-
- @Property
- private val Consumer consumer;
-
- @Property
- private var BrokerImpl broker;
-
- private val ClassToInstanceMap<BrokerService> instantiatedServices = MutableClassToInstanceMap.create();
- private boolean closed = false;
-
- private BundleContext context;
-
- public new(Consumer consumer, BundleContext ctx) {
- this._consumer = consumer;
- this.context = ctx;
- }
-
- override rpc(QName rpc, CompositeNode input) {
- return broker.invokeRpcAsync(rpc, input);
- }
-
- override <T extends BrokerService> T getService(Class<T> service) {
- val localProxy = instantiatedServices.getInstance(service);
- if(localProxy != null) {
- return localProxy;
- }
- val serviceRef = context.getServiceReference(service);
- if(serviceRef == null) {
- return null;
- }
- val serviceImpl = context.getService(serviceRef);
-
-
- val ret = ProxyFactory.createProxy(serviceRef,serviceImpl);
- if(ret != null) {
- instantiatedServices.putInstance(service, ret);
- }
- return ret;
- }
-
- override close() {
- val toStop = instantiatedServices.values();
- this.closed = true;
- for (BrokerService brokerService : toStop) {
- if(brokerService instanceof AbstractBrokerServiceProxy<?>) {
- (brokerService as AutoCloseable).close();
- }
- }
- broker.consumerSessionClosed(this);
- }
-
- override isClosed() {
- return closed;
- }
-}
import static com.google.common.base.Preconditions.checkState;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Enumeration;
+import java.util.List;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
-public class GlobalBundleScanningSchemaServiceImpl implements //
- SchemaContextProvider, //
- SchemaService, //
- ServiceTrackerCustomizer<SchemaServiceListener, SchemaServiceListener>, //
- AutoCloseable {
- private static final Logger logger = LoggerFactory.getLogger(GlobalBundleScanningSchemaServiceImpl.class);
-
- private ListenerRegistry<SchemaServiceListener> listeners;
-
- private BundleContext context;
- private final BundleScanner scanner = new BundleScanner();
-
- private BundleTracker<ImmutableSet<Registration<URL>>> bundleTracker;
+public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvider, SchemaService, ServiceTrackerCustomizer<SchemaServiceListener, SchemaServiceListener>, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(GlobalBundleScanningSchemaServiceImpl.class);
+ private final ListenerRegistry<SchemaServiceListener> listeners = new ListenerRegistry<>();
private final URLSchemaContextResolver contextResolver = new URLSchemaContextResolver();
+ private final BundleScanner scanner = new BundleScanner();
+ private final BundleContext context;
private ServiceTracker<SchemaServiceListener, SchemaServiceListener> listenerTracker;
-
+ private BundleTracker<Iterable<Registration<URL>>> bundleTracker;
private boolean starting = true;
- public ListenerRegistry<SchemaServiceListener> getListeners() {
- return listeners;
- }
-
- public void setListeners(final ListenerRegistry<SchemaServiceListener> listeners) {
- this.listeners = listeners;
+ public GlobalBundleScanningSchemaServiceImpl(final BundleContext context) {
+ this.context = Preconditions.checkNotNull(context);
}
public BundleContext getContext() {
return context;
}
- public void setContext(final BundleContext context) {
- this.context = context;
- }
-
public void start() {
checkState(context != null);
- if (listeners == null) {
- listeners = new ListenerRegistry<>();
- }
listenerTracker = new ServiceTracker<>(context, SchemaServiceListener.class, GlobalBundleScanningSchemaServiceImpl.this);
- bundleTracker = new BundleTracker<ImmutableSet<Registration<URL>>>(context, BundleEvent.RESOLVED
- | BundleEvent.UNRESOLVED, scanner);
+ bundleTracker = new BundleTracker<>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
bundleTracker.open();
listenerTracker.open();
starting = false;
try {
listener.getInstance().onGlobalContextUpdated(snapshot);
} catch (Exception e) {
- logger.error("Exception occured during invoking listener", e);
+ LOG.error("Exception occured during invoking listener", e);
}
}
if (services != null) {
try {
listener.onGlobalContextUpdated(snapshot);
} catch (Exception e) {
- logger.error("Exception occured during invoking listener", e);
+ LOG.error("Exception occured during invoking listener {}", listener, e);
}
}
}
}
- private class BundleScanner implements BundleTrackerCustomizer<ImmutableSet<Registration<URL>>> {
+ private class BundleScanner implements BundleTrackerCustomizer<Iterable<Registration<URL>>> {
@Override
- public ImmutableSet<Registration<URL>> addingBundle(final Bundle bundle, final BundleEvent event) {
+ public Iterable<Registration<URL>> addingBundle(final Bundle bundle, final BundleEvent event) {
if (bundle.getBundleId() == 0) {
- return ImmutableSet.of();
+ return Collections.emptyList();
}
- Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
- Builder<Registration<URL>> builder = ImmutableSet.<Registration<URL>> builder();
- while (enumeration != null && enumeration.hasMoreElements()) {
- Registration<URL> reg = contextResolver.registerSource(enumeration.nextElement());
- builder.add(reg);
+ final Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
+ if (enumeration == null) {
+ return Collections.emptyList();
}
- ImmutableSet<Registration<URL>> urls = builder.build();
- if(urls.isEmpty()) {
- return urls;
+
+ final List<Registration<URL>> urls = new ArrayList<>();
+ while (enumeration.hasMoreElements()) {
+ final URL u = enumeration.nextElement();
+ try {
+ urls.add(contextResolver.registerSource(u));
+ LOG.debug("Registered {}", u);
+ } catch (Exception e) {
+ LOG.warn("Failed to register {}, ignoring it", e);
+ }
}
- tryToUpdateSchemaContext();
- return urls;
+
+ if (!urls.isEmpty()) {
+ LOG.debug("Loaded {} new URLs, rebuilding schema context", urls.size());
+ tryToUpdateSchemaContext();
+ }
+
+ return ImmutableList.copyOf(urls);
}
@Override
- public void modifiedBundle(final Bundle bundle, final BundleEvent event, final ImmutableSet<Registration<URL>> object) {
- logger.debug("Modified bundle {} {} {}", bundle, event, object);
+ public void modifiedBundle(final Bundle bundle, final BundleEvent event, final Iterable<Registration<URL>> object) {
+ LOG.debug("Modified bundle {} {} {}", bundle, event, object);
}
/**
*/
@Override
- public synchronized void removedBundle(final Bundle bundle, final BundleEvent event, final ImmutableSet<Registration<URL>> urls) {
+ public synchronized void removedBundle(final Bundle bundle, final BundleEvent event, final Iterable<Registration<URL>> urls) {
for (Registration<URL> url : urls) {
try {
url.close();
} catch (Exception e) {
- e.printStackTrace();
+ LOG.warn("Failed do unregister URL {}, proceeding", url, e);
}
}
tryToUpdateSchemaContext();
}
public synchronized void tryToUpdateSchemaContext() {
- if(starting ) {
+ if (starting) {
return;
}
Optional<SchemaContext> schema = contextResolver.tryToUpdateSchemaContext();
@Override
public ListenableFuture<RpcResult<CompositeNode>> rpc(QName type, CompositeNode input) {
- return null;
+ return rpcs.invokeRpc( type, input );
}
@Override
--- /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.sal.dom.broker;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class MountPointManagerImpl implements MountProvisionService {
+
+ private final ListenerRegistry<MountProvisionListener> listeners =
+ ListenerRegistry.create();
+ private final ConcurrentMap<InstanceIdentifier, MountPointImpl> mounts =
+ new ConcurrentHashMap<>();
+ private DataProviderService dataBroker = null;
+
+ @Override
+ public MountProvisionInstance createMountPoint(final InstanceIdentifier path) {
+ checkState(!mounts.containsKey(path), "Mount already created");
+ final MountPointImpl mount = new MountPointImpl(path);
+ registerMountPoint(mount);
+ mounts.put(path, mount);
+ notifyMountCreated(path);
+ return mount;
+ }
+
+ public void notifyMountCreated(final InstanceIdentifier identifier) {
+ for (final ListenerRegistration<MountProvisionListener> listener : listeners
+ .getListeners()) {
+ listener.getInstance().onMountPointCreated(identifier);
+ }
+ }
+
+ public Object registerMountPoint(final MountPointImpl impl) {
+ // FIXME: Why is thie commented out? Either we need it or we don't
+ // dataBroker?.registerConfigurationReader(impl.mountPath,impl.readWrapper);
+ // dataBroker?.registerOperationalReader(impl.mountPath,impl.readWrapper);
+ return null;
+ }
+
+ @Override
+ public MountProvisionInstance createOrGetMountPoint(
+ final InstanceIdentifier path) {
+ final MountPointImpl mount = mounts.get(path);
+ if (mount == null) {
+ return createMountPoint(path);
+ }
+ return mount;
+ }
+
+ @Override
+ public MountProvisionInstance getMountPoint(final InstanceIdentifier path) {
+ return mounts.get(path);
+ }
+
+ /**
+ * @return the dataBroker
+ */
+ public DataProviderService getDataBroker() {
+ return dataBroker;
+ }
+
+ /**
+ * @param dataBroker
+ * the dataBroker to set
+ */
+ public void setDataBroker(final DataProviderService dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ public ListenerRegistration<MountProvisionListener> registerProvisionListener(
+ final MountProvisionListener listener) {
+ return listeners.register(listener);
+ }
+}
+++ /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.sal.dom.broker
-
-
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import java.util.concurrent.ConcurrentMap
-import java.util.concurrent.ConcurrentHashMap
-import static com.google.common.base.Preconditions.*;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService.MountProvisionListener
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry
-
-class MountPointManagerImpl implements MountProvisionService {
-
- @Property
- DataProviderService dataBroker;
-
- val ListenerRegistry<MountProvisionListener> listeners = ListenerRegistry.create()
-
- ConcurrentMap<InstanceIdentifier,MountPointImpl> mounts = new ConcurrentHashMap();
-
- override createMountPoint(InstanceIdentifier path) {
- checkState(!mounts.containsKey(path),"Mount already created");
- val mount = new MountPointImpl(path);
- registerMountPoint(mount);
- mounts.put(path,mount);
- notifyMountCreated(path);
- return mount;
- }
-
- def notifyMountCreated(InstanceIdentifier identifier) {
- for(listener : listeners) {
- listener.instance.onMountPointCreated(identifier);
- }
- }
-
- def registerMountPoint(MountPointImpl impl) {
- //dataBroker?.registerConfigurationReader(impl.mountPath,impl.readWrapper);
- //dataBroker?.registerOperationalReader(impl.mountPath,impl.readWrapper);
- }
-
- override registerProvisionListener(MountProvisionListener listener) {
- listeners.register(listener)
- }
-
-
- override createOrGetMountPoint(InstanceIdentifier path) {
- val mount = mounts.get(path);
- if(mount === null) {
- return createMountPoint(path)
- }
- return mount;
- }
-
-
- override getMountPoint(InstanceIdentifier path) {
- mounts.get(path);
- }
-}
--- /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.sal.dom.broker;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.osgi.framework.BundleContext;
+
+class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession {
+ private final Set<RpcRegistrationWrapper> registrations = new HashSet<>();
+ private final Provider provider;
+
+ public ProviderContextImpl(final Provider provider, final BundleContext ctx) {
+ super(null, ctx);
+ this.provider = provider;
+ }
+
+ @Override
+ public RpcRegistrationWrapper addRpcImplementation(final QName rpcType,
+ final RpcImplementation implementation) throws IllegalArgumentException {
+ final RpcRegistration origReg = getBroker().getRouter()
+ .addRpcImplementation(rpcType, implementation);
+ final RpcRegistrationWrapper newReg = new RpcRegistrationWrapper(
+ origReg);
+ registrations.add(newReg);
+ return newReg;
+ }
+
+ protected boolean removeRpcImplementation(final RpcRegistrationWrapper implToRemove) {
+ return registrations.remove(implToRemove);
+ }
+
+ @Override
+ public void close() {
+ for (final RpcRegistrationWrapper reg : registrations) {
+ reg.close();
+ }
+ }
+
+ @Override
+ public RoutedRpcRegistration addMountedRpcImplementation(
+ final QName rpcType, final RpcImplementation implementation) {
+ throw new UnsupportedOperationException(
+ "TODO: auto-generated method stub");
+ }
+
+ @Override
+ public RoutedRpcRegistration addRoutedRpcImplementation(
+ final QName rpcType, final RpcImplementation implementation) {
+ throw new UnsupportedOperationException(
+ "TODO: auto-generated method stub");
+ }
+
+ @Override
+ public Set<QName> getSupportedRpcs() {
+ return getBroker().getRouter().getSupportedRpcs();
+ }
+
+ @Override
+ public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
+ final RpcRegistrationListener listener) {
+ return getBroker().getRouter().addRpcRegistrationListener(listener);
+ }
+
+ /**
+ * @return the provider
+ */
+ public Provider getProvider() {
+ return provider;
+ }
+
+ /**
+ * @param provider
+ * the provider to set
+ */
+}
+++ /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.sal.dom.broker
-
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
-import org.opendaylight.controller.sal.core.api.Provider
-import org.opendaylight.controller.sal.core.api.RpcImplementation
-import org.opendaylight.yangtools.yang.common.QName
-import org.osgi.framework.BundleContext
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
-import org.opendaylight.yangtools.concepts.Registration
-
-import java.util.Set
-import java.util.HashSet
-
-class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession {
-
- @Property
- private val Provider provider;
-
- private val Set<Registration<?>> registrations = new HashSet();
-
- new(Provider provider, BundleContext ctx) {
- super(null, ctx);
- this._provider = provider;
- }
-
- override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException {
- val origReg = broker.router.addRpcImplementation(rpcType, implementation);
- val newReg = new RpcRegistrationWrapper(origReg);
- registrations.add(newReg);
- return newReg;
- }
-
- protected def removeRpcImplementation(RpcRegistrationWrapper implToRemove) throws IllegalArgumentException {
- registrations.remove(implToRemove);
- }
-
- override close() {
-
- for (reg : registrations) {
- reg.close()
- }
- super.close
- }
-
- override addMountedRpcImplementation(QName rpcType, RpcImplementation implementation) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
- override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
- override getSupportedRpcs() {
- broker.router.supportedRpcs;
- }
-
- override addRpcRegistrationListener(RpcRegistrationListener listener) {
- broker.router.addRpcRegistrationListener(listener);
- }
-}
-
-class RpcRegistrationWrapper implements RpcRegistration {
-
-
- @Property
- val RpcRegistration delegate
-
- new(RpcRegistration delegate) {
- _delegate = delegate
- }
-
- override getInstance() {
- delegate.instance
- }
-
- override close() {
- delegate.close
- }
-
- override getType() {
- delegate.type
- }
-}
-
--- /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.sal.dom.broker;
+
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+
+import com.google.common.base.Preconditions;
+
+public class RpcRegistrationWrapper implements RpcRegistration {
+
+ private final RpcRegistration delegate;
+
+ public RpcRegistrationWrapper(final RpcRegistration delegate) {
+ this.delegate = Preconditions.checkNotNull(delegate);
+ }
+
+ @Override
+ public RpcImplementation getInstance() {
+ return delegate.getInstance();
+ }
+
+ @Override
+ public void close() {
+ delegate.close();
+ }
+
+ @Override
+ public QName getType() {
+ return delegate.getType();
+ }
+
+ /**
+ * @return the delegate
+ */
+ public RpcRegistration getDelegate() {
+ return delegate;
+ }
+}
\ No newline at end of file
--- /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.sal.dom.broker.impl;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Iterables;
+
+public class DataReaderRouter extends
+AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
+ private final static Logger LOG = LoggerFactory
+ .getLogger(DataReaderRouter.class);
+ private final static URI NETCONF_NAMESPACE = URI
+ .create("urn:ietf:params:xml:ns:netconf:base:1.0");
+ private final static QName NETCONF_DATA = new QName(NETCONF_NAMESPACE,
+ "data");
+
+ @Override
+ protected CompositeNodeTOImpl merge(final InstanceIdentifier path,
+ final Iterable<CompositeNode> data) {
+ PathArgument pathArgument = Iterables.getLast(path.getPath(), null);
+ boolean empty = true;
+ QName name = (pathArgument == null ? null : pathArgument.getNodeType());
+ final ArrayList<Node<?>> nodes = new ArrayList<Node<?>>();
+ final HashMap<QName, SimpleNode<?>> keyNodes = new HashMap<QName, SimpleNode<?>>();
+ for (final CompositeNode dataBit : data) {
+ try {
+ if (pathArgument != null && dataBit != null) {
+ empty = false;
+ final Map<QName, SimpleNode<?>> keyNodesLocal = getKeyNodes(
+ pathArgument, dataBit);
+ nodes.addAll(this.childrenWithout(dataBit,
+ keyNodesLocal.entrySet()));
+ } else if (dataBit != null) {
+ empty = false;
+ nodes.addAll(dataBit.getValue());
+ }
+ } catch (IllegalStateException e) {
+ LOG.error("BUG: Readed data for path {} was invalid", path, e);
+ }
+ }
+ if (empty) {
+ return null;
+ }
+ /**
+ * Reading from Root
+ *
+ */
+ if (pathArgument == null) {
+ return new CompositeNodeTOImpl(NETCONF_DATA, null, nodes);
+ }
+ final ArrayList<Node<?>> finalNodes = new ArrayList<Node<?>>(
+ nodes.size() + keyNodes.size());
+ finalNodes.addAll(keyNodes.values());
+ finalNodes.addAll(nodes);
+ return new CompositeNodeTOImpl(name, null, finalNodes);
+ }
+
+ protected Map<QName, SimpleNode<?>> _getKeyNodes(
+ final PathArgument argument, final CompositeNode node) {
+ return Collections.emptyMap();
+ }
+
+ protected Map<QName, SimpleNode<?>> _getKeyNodes(
+ final NodeIdentifierWithPredicates argument,
+ final CompositeNode node) {
+ final HashMap<QName, SimpleNode<?>> ret = new HashMap<QName, SimpleNode<?>>();
+ for (final Entry<QName, Object> keyValue : argument.getKeyValues()
+ .entrySet()) {
+ final List<SimpleNode<?>> simpleNode = node
+ .getSimpleNodesByName(keyValue.getKey());
+ if (simpleNode != null && !simpleNode.isEmpty()) {
+ checkState(
+ simpleNode.size() <= 1,
+ "Only one simple node for key $s is allowed in node $s",
+ keyValue.getKey(), node);
+ checkState(
+ simpleNode.get(0).getValue() == keyValue.getValue(),
+ "Key node must equal to instance identifier value in node $s",
+ node);
+ ret.put(keyValue.getKey(), simpleNode.get(0));
+ }
+ final List<CompositeNode> compositeNode = node
+ .getCompositesByName(keyValue.getKey());
+ checkState(compositeNode == null || compositeNode.isEmpty(),
+ "Key node must be Simple Node, not composite node.");
+ }
+ return ret;
+ }
+
+ public Map<QName, SimpleNode<?>> getKeyNodes(
+ final InstanceIdentifier.PathArgument argument,
+ final CompositeNode node) {
+ if (argument instanceof InstanceIdentifier.NodeIdentifierWithPredicates) {
+ return _getKeyNodes(
+ (InstanceIdentifier.NodeIdentifierWithPredicates) argument,
+ node);
+ } else if (argument != null) {
+ return _getKeyNodes(argument, node);
+ } else {
+ throw new IllegalArgumentException("Unhandled parameter types: "
+ + Arrays.<Object> asList(argument, node).toString());
+ }
+ }
+
+ private Collection<? extends Node<?>> childrenWithout(
+ final CompositeNode node,
+ final Set<Entry<QName, SimpleNode<?>>> entries) {
+ if (entries.isEmpty()) {
+ return node.getValue();
+ }
+ final List<Node<?>> filteredNodes = new ArrayList<Node<?>>();
+ for (final Node<?> scannedNode : node.getValue()) {
+ if (!entries.contains(scannedNode.getNodeType())) {
+ filteredNodes.add(scannedNode);
+ }
+ }
+ return filteredNodes;
+ }
+
+}
+++ /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.sal.dom.broker.impl
-
-import java.net.URI
-import java.util.ArrayList
-import java.util.Collection
-import java.util.Collections
-import java.util.HashMap
-import java.util.Map
-import java.util.Map.Entry
-import java.util.Set
-import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.data.api.SimpleNode
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import org.slf4j.LoggerFactory
-
-import static com.google.common.base.Preconditions.*
-
-class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
- private static val LOG = LoggerFactory.getLogger(DataReaderRouter);
- private static val NETCONF_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0")
- private static val NETCONF_DATA = new QName(NETCONF_NAMESPACE,"data");
-
- override protected merge(InstanceIdentifier path, Iterable<CompositeNode> data) {
- val pathArgument = path.path.last;
- var empty = true;
- var name = pathArgument?.nodeType;
- val nodes = new ArrayList<Node<?>>();
- val keyNodes = new HashMap<QName, SimpleNode<?>>();
- for(dataBit : data) {
- try {
- if(pathArgument != null && dataBit != null) {
- empty = false;
- val keyNodesLocal = getKeyNodes(pathArgument,dataBit);
- nodes.addAll(dataBit.childrenWithout(keyNodesLocal.entrySet));
- } else if (dataBit != null) {
- empty = false;
- nodes.addAll(dataBit.children)
- }
- } catch (IllegalStateException e) {
- LOG.error("BUG: Readed data for path {} was invalid",path,e);
- }
- }
- if(empty) {
- return null;
- }
- /**
- * Reading from Root
- *
- */
- if(pathArgument == null) {
- return new CompositeNodeTOImpl(NETCONF_DATA,null,nodes);
- }
- val finalNodes = new ArrayList<Node<?>>();
- finalNodes.addAll(keyNodes.values);
- finalNodes.addAll(nodes);
- return new CompositeNodeTOImpl(name,null,finalNodes);
- }
-
-
-
- dispatch def Map<QName, SimpleNode<?>> getKeyNodes(PathArgument argument, CompositeNode node) {
- return Collections.emptyMap();
- }
-
- dispatch def getKeyNodes(NodeIdentifierWithPredicates argument, CompositeNode node) {
- val ret = new HashMap<QName, SimpleNode<?>>();
- for (keyValue : argument.keyValues.entrySet) {
- val simpleNode = node.getSimpleNodesByName(keyValue.key);
- if(simpleNode !== null && !simpleNode.empty) {
- checkState(simpleNode.size <= 1,"Only one simple node for key $s is allowed in node $s",keyValue.key,node);
- checkState(simpleNode.get(0).value == keyValue.value,"Key node must equal to instance identifier value in node $s",node);
- ret.put(keyValue.key,simpleNode.get(0));
- }
- val compositeNode = node.getCompositesByName(keyValue.key);
- checkState(compositeNode === null || compositeNode.empty,"Key node must be Simple Node, not composite node.");
- }
- return ret;
- }
-
- def Collection<? extends Node<?>> childrenWithout(CompositeNode node, Set<Entry<QName, SimpleNode<?>>> entries) {
- if(entries.empty) {
- return node.children;
- }
- val filteredNodes = new ArrayList<Node<?>>();
- for(scannedNode : node.children) {
- if(!entries.contains(scannedNode.nodeType)) {
- filteredNodes.add(scannedNode);
- }
- }
- return filteredNodes;
- }
-
-}
--- /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.sal.dom.broker.impl;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+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.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class HashMapDataStore implements DataStore, AutoCloseable {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(HashMapDataStore.class);
+
+ private final Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap<InstanceIdentifier, CompositeNode>();
+ private final Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap<InstanceIdentifier, CompositeNode>();
+
+ @Override
+ public boolean containsConfigurationPath(final InstanceIdentifier path) {
+ return configuration.containsKey(path);
+ }
+
+ @Override
+ public boolean containsOperationalPath(final InstanceIdentifier path) {
+ return operational.containsKey(path);
+ }
+
+ @Override
+ public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
+ return configuration.keySet();
+ }
+
+ @Override
+ public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
+ return operational.keySet();
+ }
+
+ @Override
+ public CompositeNode readConfigurationData(final InstanceIdentifier path) {
+ LOG.trace("Reading configuration path {}", path);
+ return configuration.get(path);
+ }
+
+ @Override
+ public CompositeNode readOperationalData(InstanceIdentifier path) {
+ LOG.trace("Reading operational path {}", path);
+ return operational.get(path);
+ }
+
+ @Override
+ public DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
+ final DataModification<InstanceIdentifier, CompositeNode> modification) {
+ return new HashMapDataStoreTransaction(modification, this);
+ }
+
+ public RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
+ return Rpcs.<Void> getRpcResult(true, null,
+ Collections.<RpcError> emptySet());
+ }
+
+ public RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
+ final DataModification<InstanceIdentifier, CompositeNode> modification = transaction
+ .getModification();
+ for (final InstanceIdentifier removal : modification
+ .getRemovedConfigurationData()) {
+ LOG.trace("Removing configuration path {}", removal);
+ remove(configuration, removal);
+ }
+ for (final InstanceIdentifier removal : modification
+ .getRemovedOperationalData()) {
+ LOG.trace("Removing operational path {}", removal);
+ remove(operational, removal);
+ }
+ if (LOG.isTraceEnabled()) {
+ for (final InstanceIdentifier a : modification
+ .getUpdatedConfigurationData().keySet()) {
+ LOG.trace("Adding configuration path {}", a);
+ }
+ for (final InstanceIdentifier a : modification
+ .getUpdatedOperationalData().keySet()) {
+ LOG.trace("Adding operational path {}", a);
+ }
+ }
+ configuration.putAll(modification.getUpdatedConfigurationData());
+ operational.putAll(modification.getUpdatedOperationalData());
+
+ return Rpcs.<Void> getRpcResult(true, null,
+ Collections.<RpcError> emptySet());
+ }
+
+ public void remove(final Map<InstanceIdentifier, CompositeNode> map,
+ final InstanceIdentifier identifier) {
+ Set<InstanceIdentifier> affected = new HashSet<InstanceIdentifier>();
+ for (final InstanceIdentifier path : map.keySet()) {
+ if (identifier.contains(path)) {
+ affected.add(path);
+ }
+ }
+ for (final InstanceIdentifier pathToRemove : affected) {
+ LOG.trace("Removed path {}", pathToRemove);
+ map.remove(pathToRemove);
+ }
+ }
+
+ @Override
+ public void close() {
+ // NOOP
+ }
+}
+++ /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.sal.dom.broker.impl
-
-import org.opendaylight.controller.md.sal.common.api.data.DataModification
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
-import org.opendaylight.yangtools.yang.common.RpcResult
-import java.util.Map
-import java.util.concurrent.ConcurrentHashMap
-import org.opendaylight.controller.sal.common.util.Rpcs
-import java.util.Collections
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.controller.sal.core.api.data.DataStore
-import java.util.HashSet
-import org.slf4j.LoggerFactory
-import org.slf4j.Logger
-
-final class HashMapDataStore implements DataStore, AutoCloseable {
- private val Logger LOG = LoggerFactory.getLogger(HashMapDataStore)
-
- val Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap();
- val Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap();
-
-
-
- override containsConfigurationPath(InstanceIdentifier path) {
- return configuration.containsKey(path)
- }
-
- override containsOperationalPath(InstanceIdentifier path) {
- return operational.containsKey(path)
- }
-
- override getStoredConfigurationPaths() {
- configuration.keySet
- }
-
- override getStoredOperationalPaths() {
- operational.keySet
- }
-
- override readConfigurationData(InstanceIdentifier path) {
- LOG.trace("Reading configuration path {}", path)
- configuration.get(path);
- }
-
- override readOperationalData(InstanceIdentifier path) {
- LOG.trace("Reading operational path {}", path)
- operational.get(path);
- }
-
-
-
- override requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
- return new HashMapDataStoreTransaction(modification, this);
- }
-
- def RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
- return Rpcs.getRpcResult(true, null, Collections.emptySet);
- }
-
- def RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
- val modification = transaction.modification;
- for (removal : modification.removedConfigurationData) {
- LOG.trace("Removing configuration path {}", removal)
- remove(configuration,removal);
- }
- for (removal : modification.removedOperationalData) {
- LOG.trace("Removing operational path {}", removal)
- remove(operational,removal);
- }
- if (LOG.isTraceEnabled()) {
- for (a : modification.updatedConfigurationData.keySet) {
- LOG.trace("Adding configuration path {}", a)
- }
- for (a : modification.updatedOperationalData.keySet) {
- LOG.trace("Adding operational path {}", a)
- }
- }
- configuration.putAll(modification.updatedConfigurationData);
- operational.putAll(modification.updatedOperationalData);
-
- return Rpcs.getRpcResult(true, null, Collections.emptySet);
- }
-
- def remove(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier identifier) {
- val affected = new HashSet<InstanceIdentifier>();
- for(path : map.keySet) {
- if(identifier.contains(path)) {
- affected.add(path);
- }
- }
- for(pathToRemove : affected) {
- LOG.trace("Removed path {}", pathToRemove)
- map.remove(pathToRemove);
- }
-
- }
-
-
- override close() {
- // NOOP
- }
-
-}
-
-class HashMapDataStoreTransaction implements //
-DataCommitTransaction<InstanceIdentifier, CompositeNode> {
- @Property
- val DataModification<InstanceIdentifier, CompositeNode> modification
-
- @Property
- val HashMapDataStore datastore;
-
- new(
- DataModification<InstanceIdentifier, CompositeNode> modify,
- HashMapDataStore store
- ) {
- _modification = modify;
- _datastore = store;
- }
-
- override finish() throws IllegalStateException {
- datastore.finish(this);
-
- }
-
- override getModification() {
- this._modification;
- }
-
- override rollback() throws IllegalStateException {
- datastore.rollback(this);
- }
-}
--- /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.sal.dom.broker.impl;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class HashMapDataStoreTransaction implements
+ DataCommitTransaction<InstanceIdentifier, CompositeNode> {
+ private final DataModification<InstanceIdentifier, CompositeNode> modification;
+ private final HashMapDataStore datastore;
+
+ HashMapDataStoreTransaction(
+ final DataModification<InstanceIdentifier, CompositeNode> modify,
+ final HashMapDataStore store) {
+ modification = modify;
+ datastore = store;
+ }
+
+ @Override
+ public RpcResult<Void> finish() throws IllegalStateException {
+ return datastore.finish(this);
+ }
+
+ @Override
+ public DataModification<InstanceIdentifier, CompositeNode> getModification() {
+ return this.modification;
+ }
+
+ @Override
+ public RpcResult<Void> rollback() throws IllegalStateException {
+ return datastore.rollback(this);
+ }
+}
\ No newline at end of file
import com.google.common.collect.ImmutableSet;
public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataStore> implements //
- DataStore, //
- SchemaContextListener, //
- AutoCloseable {
+DataStore, //
+SchemaContextListener, //
+AutoCloseable {
private final static Logger LOG = LoggerFactory.getLogger(SchemaAwareDataStoreAdapter.class);
private final DataReader<InstanceIdentifier, CompositeNode> reader = new MergeFirstLevelReader();
@Override
- public boolean containsConfigurationPath(InstanceIdentifier path) {
+ public boolean containsConfigurationPath(final InstanceIdentifier path) {
try {
getDelegateReadLock().lock();
return getDelegate().containsConfigurationPath(path);
}
@Override
- public boolean containsOperationalPath(InstanceIdentifier path) {
+ public boolean containsOperationalPath(final InstanceIdentifier path) {
try {
getDelegateReadLock().lock();
return getDelegate().containsOperationalPath(path);
}
@Override
- public CompositeNode readConfigurationData(InstanceIdentifier path) {
+ public CompositeNode readConfigurationData(final InstanceIdentifier path) {
return reader.readConfigurationData(path);
}
@Override
- public CompositeNode readOperationalData(InstanceIdentifier path) {
+ public CompositeNode readOperationalData(final InstanceIdentifier path) {
return reader.readOperationalData(path);
}
@Override
public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
- DataModification<InstanceIdentifier, CompositeNode> modification) {
+ final DataModification<InstanceIdentifier, CompositeNode> modification) {
validateAgainstSchema(modification);
NormalizedDataModification cleanedUp = prepareMergedTransaction(modification);
cleanedUp.status = TransactionStatus.SUBMITED;
return validationEnabled;
}
- public void setValidationEnabled(boolean validationEnabled) {
+ public void setValidationEnabled(final boolean validationEnabled) {
this.validationEnabled = validationEnabled;
}
- private void validateAgainstSchema(DataModification<InstanceIdentifier, CompositeNode> modification) {
+ private void validateAgainstSchema(final DataModification<InstanceIdentifier, CompositeNode> modification) {
if (!validationEnabled) {
return;
}
}
@Override
- protected void onDelegateChanged(DataStore oldDelegate, DataStore newDelegate) {
+ protected void onDelegateChanged(final DataStore oldDelegate, final DataStore newDelegate) {
// NOOP
}
@Override
- public void onGlobalContextUpdated(SchemaContext context) {
+ public void onGlobalContextUpdated(final SchemaContext context) {
this.schema = context;
}
this.schema = null;
}
- protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified,
- boolean config) {
+ protected CompositeNode mergeData(final InstanceIdentifier path, final CompositeNode stored, final CompositeNode modified,
+ final boolean config) {
// long startTime = System.nanoTime();
try {
DataSchemaNode node = schemaNodeFor(path);
}
}
- private DataSchemaNode schemaNodeFor(InstanceIdentifier path) {
+ private DataSchemaNode schemaNodeFor(final InstanceIdentifier path) {
checkState(schema != null, "YANG Schema is not available");
return YangSchemaUtils.getSchemaNode(schema, path);
}
private NormalizedDataModification prepareMergedTransaction(
- DataModification<InstanceIdentifier, CompositeNode> original) {
+ final DataModification<InstanceIdentifier, CompositeNode> original) {
NormalizedDataModification normalized = new NormalizedDataModification(original);
LOG.trace("Transaction: {} Removed Configuration {}, Removed Operational {}", original.getIdentifier(),
original.getRemovedConfigurationData(), original.getRemovedConfigurationData());
return normalized;
}
- private Iterable<InstanceIdentifier> getConfigurationSubpaths(InstanceIdentifier entry) {
+ private Iterable<InstanceIdentifier> getConfigurationSubpaths(final InstanceIdentifier entry) {
// FIXME: This should be replaced by index
Iterable<InstanceIdentifier> paths = getStoredConfigurationPaths();
}
- public Iterable<InstanceIdentifier> getOperationalSubpaths(InstanceIdentifier entry) {
+ public Iterable<InstanceIdentifier> getOperationalSubpaths(final InstanceIdentifier entry) {
// FIXME: This should be indexed
Iterable<InstanceIdentifier> paths = getStoredOperationalPaths();
return getChildrenPaths(entry, paths);
}
- private static final Iterable<InstanceIdentifier> getChildrenPaths(InstanceIdentifier entry,
- Iterable<InstanceIdentifier> paths) {
+ private static final Iterable<InstanceIdentifier> getChildrenPaths(final InstanceIdentifier entry,
+ final Iterable<InstanceIdentifier> paths) {
ImmutableSet.Builder<InstanceIdentifier> children = ImmutableSet.builder();
for (InstanceIdentifier potential : paths) {
if (entry.contains(potential)) {
private final Comparator<Entry<InstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<InstanceIdentifier, CompositeNode>>() {
@Override
- public int compare(Entry<InstanceIdentifier, CompositeNode> o1, Entry<InstanceIdentifier, CompositeNode> o2) {
+ public int compare(final Entry<InstanceIdentifier, CompositeNode> o1, final Entry<InstanceIdentifier, CompositeNode> o2) {
InstanceIdentifier o1Key = o1.getKey();
InstanceIdentifier o2Key = o2.getKey();
return Integer.compare(o1Key.getPath().size(), o2Key.getPath().size());
CompositeNode original = getDelegate().readConfigurationData(path);
ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
if (original != null) {
- childNodes.addAll(original.getChildren());
+ childNodes.addAll(original.getValue());
qname = original.getNodeType();
} else {
qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredConfigurationPaths())
.filter(new Predicate<InstanceIdentifier>() {
@Override
- public boolean apply(InstanceIdentifier input) {
+ public boolean apply(final InstanceIdentifier input) {
if (path.contains(input)) {
int nesting = input.getPath().size() - path.getPath().size();
if (nesting == 1) {
CompositeNode original = getDelegate().readOperationalData(path);
ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
if (original != null) {
- childNodes.addAll(original.getChildren());
+ childNodes.addAll(original.getValue());
qname = original.getNodeType();
} else {
qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredOperationalPaths())
.filter(new Predicate<InstanceIdentifier>() {
@Override
- public boolean apply(InstanceIdentifier input) {
+ public boolean apply(final InstanceIdentifier input) {
if (path.contains(input)) {
int nesting = input.getPath().size() - path.getPath().size();
if (nesting == 1) {
private final Object identifier;
private TransactionStatus status;
- public NormalizedDataModification(DataModification<InstanceIdentifier, CompositeNode> original) {
+ public NormalizedDataModification(final DataModification<InstanceIdentifier, CompositeNode> original) {
super(getDelegate());
identifier = original;
status = TransactionStatus.NEW;
*
* @param entry
*/
- public void deepRemoveOperationalData(InstanceIdentifier entry) {
+ public void deepRemoveOperationalData(final InstanceIdentifier entry) {
Iterable<InstanceIdentifier> paths = getOperationalSubpaths(entry);
removeOperationalData(entry);
for (InstanceIdentifier potential : paths) {
}
}
- public void deepRemoveConfigurationData(InstanceIdentifier entry) {
+ public void deepRemoveConfigurationData(final InstanceIdentifier entry) {
Iterable<InstanceIdentifier> paths = getConfigurationSubpaths(entry);
removeConfigurationData(entry);
for (InstanceIdentifier potential : paths) {
}
}
- public void putDeepConfigurationData(InstanceIdentifier entryKey, CompositeNode entryData) {
+ public void putDeepConfigurationData(final InstanceIdentifier entryKey, final CompositeNode entryData) {
this.putCompositeNodeData(entryKey, entryData, CONFIGURATIONAL_DATA_STORE_MARKER);
}
- public void putDeepOperationalData(InstanceIdentifier entryKey, CompositeNode entryData) {
+ public void putDeepOperationalData(final InstanceIdentifier entryKey, final CompositeNode entryData) {
this.putCompositeNodeData(entryKey, entryData, OPERATIONAL_DATA_STORE_MARKER);
}
}
@Override
- protected CompositeNode mergeConfigurationData(InstanceIdentifier path, CompositeNode stored,
- CompositeNode modified) {
+ protected CompositeNode mergeConfigurationData(final InstanceIdentifier path, final CompositeNode stored,
+ final CompositeNode modified) {
return mergeData(path, stored, modified, true);
}
@Override
- protected CompositeNode mergeOperationalData(InstanceIdentifier path, CompositeNode stored,
- CompositeNode modified) {
+ protected CompositeNode mergeOperationalData(final InstanceIdentifier path, final CompositeNode stored,
+ final CompositeNode modified) {
return mergeData(path, stored, modified, false);
}
- private void putData(InstanceIdentifier entryKey, CompositeNode entryData, String dataStoreIdentifier) {
+ private void putData(final InstanceIdentifier entryKey, final CompositeNode entryData, final String dataStoreIdentifier) {
if (dataStoreIdentifier != null && entryKey != null && entryData != null) {
switch (dataStoreIdentifier) {
case (CONFIGURATIONAL_DATA_STORE_MARKER):
this.putConfigurationData(entryKey, entryData);
- break;
+ break;
case (OPERATIONAL_DATA_STORE_MARKER):
this.putOperationalData(entryKey, entryData);
- break;
+ break;
default:
LOG.error(dataStoreIdentifier + " is NOT valid DataStore switch marker");
}
}
- private void putCompositeNodeData(InstanceIdentifier entryKey, CompositeNode entryData,
- String dataStoreIdentifier) {
+ private void putCompositeNodeData(final InstanceIdentifier entryKey, final CompositeNode entryData,
+ final String dataStoreIdentifier) {
this.putData(entryKey, entryData, dataStoreIdentifier);
- for (Node<?> child : entryData.getChildren()) {
+ for (Node<?> child : entryData.getValue()) {
InstanceIdentifier subEntryId = InstanceIdentifier.builder(entryKey).node(child.getNodeType())
.toInstance();
if (child instanceof CompositeNode) {
}
}
- private Map<QName, Object> getValuesFromListSchema(ListSchemaNode listSchema, CompositeNode entryData) {
+ private Map<QName, Object> getValuesFromListSchema(final ListSchemaNode listSchema, final CompositeNode entryData) {
List<QName> keyDef = listSchema.getKeyDefinition();
if (keyDef != null && !keyDef.isEmpty()) {
Map<QName, Object> map = new HashMap<QName, Object>();
--- /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.sal.dom.broker.osgi;
+
+import java.util.Arrays;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.osgi.framework.ServiceReference;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+@SuppressWarnings("unchecked")
+public class ProxyFactory {
+
+ public static <T extends BrokerService> T createProxy(
+ final ServiceReference<T> serviceRef, final T service) {
+
+ Object _createProxyImpl = ProxyFactory.createProxyImpl(serviceRef,
+ service);
+ return ((T) _createProxyImpl);
+ }
+
+ private static Object _createProxyImpl(final ServiceReference<?> ref,
+ final DataBrokerService service) {
+
+ return new DataBrokerServiceProxy(
+ ((ServiceReference<DataBrokerService>) ref), service);
+ }
+
+ private static Object _createProxyImpl(final ServiceReference<?> ref,
+ final DataProviderService service) {
+
+ return new DataProviderServiceProxy(
+ ((ServiceReference<DataProviderService>) ref), service);
+ }
+
+ private static Object _createProxyImpl(final ServiceReference<?> ref,
+ final NotificationPublishService service) {
+
+ return new NotificationPublishServiceProxy(
+ ((ServiceReference<NotificationPublishService>) ref), service);
+ }
+
+ private static Object _createProxyImpl(final ServiceReference<?> ref,
+ final NotificationService service) {
+
+ return new NotificationServiceProxy(
+ ((ServiceReference<NotificationService>) ref), service);
+ }
+
+ private static Object _createProxyImpl(final ServiceReference<?> ref,
+ final MountProvisionService service) {
+
+ return new MountProviderServiceProxy(
+ ((ServiceReference<MountProvisionService>) ref), service);
+ }
+
+ private static Object _createProxyImpl(final ServiceReference<?> ref,
+ final SchemaService service) {
+
+ return new SchemaServiceProxy(((ServiceReference<SchemaService>) ref),
+ service);
+ }
+
+ private static Object _createProxyImpl(final ServiceReference<?> ref,
+ final RpcProvisionRegistry service) {
+
+ return new RpcProvisionRegistryProxy(
+ ((ServiceReference<RpcProvisionRegistry>) ref), service);
+ }
+
+ private static DOMDataBrokerProxy _createProxyImpl(
+ final ServiceReference<?> ref, final DOMDataBroker service) {
+
+ return new DOMDataBrokerProxy(((ServiceReference<DOMDataBroker>) ref),
+ service);
+ }
+
+ private static Object _createProxyImpl(final ServiceReference<?> reference,
+ final BrokerService service) {
+
+ throw new IllegalArgumentException("Not supported class: "
+ + service.getClass().getName());
+ }
+
+ private static Object createProxyImpl(final ServiceReference<?> ref,
+ final BrokerService service) {
+
+ if (service instanceof DOMDataBroker) {
+ return _createProxyImpl(ref, (DOMDataBroker) service);
+ } else if (service instanceof RpcProvisionRegistry) {
+ return _createProxyImpl(ref, (RpcProvisionRegistry) service);
+ } else if (service instanceof DataProviderService) {
+ return _createProxyImpl(ref, (DataProviderService) service);
+ } else if (service instanceof MountProvisionService) {
+ return _createProxyImpl(ref, (MountProvisionService) service);
+ } else if (service instanceof NotificationPublishService) {
+ return _createProxyImpl(ref, (NotificationPublishService) service);
+ } else if (service instanceof DataBrokerService) {
+ return _createProxyImpl(ref, (DataBrokerService) service);
+ } else if (service instanceof SchemaService) {
+ return _createProxyImpl(ref, (SchemaService) service);
+ } else if (service instanceof NotificationService) {
+ return _createProxyImpl(ref, (NotificationService) service);
+ } else if (service != null) {
+ return _createProxyImpl(ref, service);
+ } else {
+ throw new IllegalArgumentException("Unhandled parameter types: "
+ + Arrays.<Object> asList(ref, service).toString());
+ }
+ }
+}
\ No newline at end of file
+++ /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.sal.dom.broker.osgi
-
-import org.opendaylight.controller.sal.core.api.BrokerService
-import org.osgi.framework.ServiceReference
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.core.api.data.DataProviderService
-import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService
-import org.opendaylight.controller.sal.core.api.notify.NotificationService
-import org.opendaylight.controller.sal.core.api.model.SchemaService
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker
-
-class ProxyFactory {
-
- static def <T extends BrokerService> T createProxy(ServiceReference<T> serviceRef, T service) {
- return createProxyImpl(serviceRef, service) as T;
- }
-
-
- private static def dispatch createProxyImpl(ServiceReference<?> ref, DataBrokerService service) {
- new DataBrokerServiceProxy(ref as ServiceReference<DataBrokerService>, service);
- }
-
- private static def dispatch createProxyImpl(ServiceReference<?> ref, DataProviderService service) {
- new DataProviderServiceProxy(ref as ServiceReference<DataProviderService>, service);
- }
-
- private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationPublishService service) {
- new NotificationPublishServiceProxy(ref as ServiceReference<NotificationPublishService>, service);
- }
-
- private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationService service) {
- new NotificationServiceProxy(ref as ServiceReference<NotificationService>, service);
- }
-
- private static def dispatch createProxyImpl(ServiceReference<?> ref, MountProvisionService service) {
- new MountProviderServiceProxy(ref as ServiceReference<MountProvisionService>, service);
- }
-
-
- private static def dispatch createProxyImpl(ServiceReference<?> ref, SchemaService service) {
- new SchemaServiceProxy(ref as ServiceReference<SchemaService>, service);
- }
-
- private static def dispatch createProxyImpl(ServiceReference<?> ref, RpcProvisionRegistry service) {
- new RpcProvisionRegistryProxy(ref as ServiceReference<RpcProvisionRegistry>, service);
- }
-
- private static def dispatch createProxyImpl(ServiceReference<?> ref, DOMDataBroker service) {
- new DOMDataBrokerProxy(ref as ServiceReference<DOMDataBroker>, service)
- }
-
-
- private static def dispatch createProxyImpl(ServiceReference<?> reference, BrokerService service) {
- throw new IllegalArgumentException("Not supported class");
- }
-
-}
public class SchemaServiceActivator implements BundleActivator {
-
+
private ServiceRegistration<SchemaService> schemaServiceReg;
private GlobalBundleScanningSchemaServiceImpl schemaService;
@Override
- public void start(BundleContext context) throws Exception {
- schemaService = new GlobalBundleScanningSchemaServiceImpl();
- schemaService.setContext(context);
+ public void start(final BundleContext context) {
+ schemaService = new GlobalBundleScanningSchemaServiceImpl(context);
schemaService.start();
schemaServiceReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String,String>());
}
-
+
@Override
- public void stop(BundleContext context) throws Exception {
+ public void stop(final BundleContext context) throws Exception {
schemaServiceReg.unregister();
schemaService.close();
}
--- /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.sal.dom.broker.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+public class YangDataOperations {
+
+ public static CompositeNode merge(final DataSchemaNode schema,
+ final CompositeNode stored, final CompositeNode modified,
+ final boolean config) {
+ if (stored == null) {
+ return modified;
+ }
+
+ Preconditions.checkArgument(schema instanceof ListSchemaNode
+ || schema instanceof ContainerSchemaNode,
+ "Supplied node is not data node container.");
+
+ return YangDataOperations.mergeContainer((DataNodeContainer) schema,
+ stored, modified, config);
+ }
+
+ private static Iterable<? extends Node<?>> _mergeMultiple(
+ final LeafSchemaNode node, final List<Node<?>> original,
+ final List<Node<?>> modified, final boolean configurational) {
+ checkArgument(original.size() == 1);
+ checkArgument(modified.size() == 1);
+
+ return modified;
+ }
+
+ private static Iterable<? extends Node<?>> _mergeMultiple(
+ final LeafListSchemaNode node, final List<Node<?>> original,
+ final List<Node<?>> modified, final boolean configurational) {
+ return modified;
+ }
+
+ private static Iterable<? extends Node<?>> _mergeMultiple(
+ final ContainerSchemaNode node, final List<Node<?>> original,
+ final List<Node<?>> modified, final boolean configurational) {
+ checkArgument(original.size() == 1);
+ checkArgument(modified.size() == 1);
+ return Collections.singletonList(merge(node,
+ (CompositeNode) original.get(0),
+ (CompositeNode) modified.get(0), configurational));
+ }
+
+ private static Iterable<? extends Node<?>> _mergeMultiple(
+ final ListSchemaNode node, final List<Node<?>> original,
+ final List<Node<?>> modified, final boolean configurational) {
+
+ if (node.getKeyDefinition() == null
+ || node.getKeyDefinition().isEmpty()) {
+ return modified;
+ }
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ final Map<Map<QName, Object>, CompositeNode> originalMap = YangDataUtils
+ .toIndexMap((List) original, node.getKeyDefinition());
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ final Map<Map<QName, Object>, CompositeNode> modifiedMap = YangDataUtils
+ .toIndexMap((List) modified, node.getKeyDefinition());
+
+ final List<Node<?>> mergedNodes = new ArrayList<Node<?>>(
+ original.size() + modified.size());
+ for (final Map.Entry<Map<QName, Object>, CompositeNode> entry : modifiedMap
+ .entrySet()) {
+ final CompositeNode originalEntry = originalMap.get(entry.getKey());
+ if (originalEntry != null) {
+ originalMap.remove(entry.getKey());
+ mergedNodes.add(merge(node, originalEntry, entry.getValue(),
+ configurational));
+ } else {
+ mergedNodes.add(entry.getValue());
+ }
+ }
+ mergedNodes.addAll(originalMap.values());
+ return mergedNodes;
+ }
+
+ private static Iterable<? extends Node<?>> mergeMultiple(
+ final DataSchemaNode node, final List<Node<?>> original,
+ final List<Node<?>> modified, final boolean configurational) {
+ if (node instanceof ContainerSchemaNode) {
+ return _mergeMultiple((ContainerSchemaNode) node, original,
+ modified, configurational);
+ } else if (node instanceof LeafListSchemaNode) {
+ return _mergeMultiple((LeafListSchemaNode) node, original,
+ modified, configurational);
+ } else if (node instanceof LeafSchemaNode) {
+ return _mergeMultiple((LeafSchemaNode) node, original, modified,
+ configurational);
+ } else if (node instanceof ListSchemaNode) {
+ return _mergeMultiple((ListSchemaNode) node, original, modified,
+ configurational);
+ } else {
+ throw new IllegalArgumentException("Unhandled parameter types: "
+ + Arrays.<Object> asList(node, original, modified,
+ configurational).toString());
+ }
+ }
+
+ private static CompositeNode mergeContainer(final DataNodeContainer schema,
+ final CompositeNode stored, final CompositeNode modified,
+ final boolean config) {
+ if (stored == null) {
+ return modified;
+ }
+ Preconditions.checkNotNull(stored);
+ Preconditions.checkNotNull(modified);
+ Preconditions.checkArgument(Objects.equals(stored.getNodeType(),
+ modified.getNodeType()));
+
+ final List<Node<?>> mergedChildNodes = new ArrayList<Node<?>>(stored
+ .getChildren().size() + modified.getChildren().size());
+ final Set<QName> toProcess = new HashSet<QName>(stored.keySet());
+ toProcess.addAll(modified.keySet());
+
+ for (QName qname : toProcess) {
+ final DataSchemaNode schemaChild = schema.getDataChildByName(qname);
+ final List<Node<?>> storedChildren = stored.get(qname);
+ final List<Node<?>> modifiedChildren = modified.get(qname);
+
+ if (modifiedChildren != null && !modifiedChildren.isEmpty()) {
+ if (storedChildren == null || storedChildren.isEmpty()
+ || schemaChild == null) {
+ mergedChildNodes.addAll(modifiedChildren);
+ } else {
+ final Iterable<? extends Node<?>> _mergeMultiple = mergeMultiple(
+ schemaChild, storedChildren, modifiedChildren,
+ config);
+ Iterables.addAll(mergedChildNodes, _mergeMultiple);
+ }
+ } else if (storedChildren != null && !storedChildren.isEmpty()) {
+ mergedChildNodes.addAll(storedChildren);
+ }
+ }
+ return new CompositeNodeTOImpl(stored.getNodeType(), null,
+ mergedChildNodes);
+ }
+}
+++ /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.sal.dom.broker.util
-
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import static com.google.common.base.Preconditions.*;
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import java.util.ArrayList
-
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import java.util.List
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import java.util.Collections
-import java.util.HashSet
-import org.opendaylight.yangtools.yang.common.QName
-import static extension org.opendaylight.controller.sal.dom.broker.util.YangDataUtils.*;
-
-class YangDataOperations {
-
- static def CompositeNode merge(DataSchemaNode schema, CompositeNode stored, CompositeNode modified, boolean config) {
- if (stored === null) {
- return modified;
- }
-
- if (schema instanceof ListSchemaNode || schema instanceof ContainerSchemaNode) {
- return mergeContainer(schema as DataNodeContainer, stored, modified, config);
- }
- throw new IllegalArgumentException("Supplied node is not data node container.");
- }
-
- private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafSchemaNode node, List<Node<?>> original,
- List<Node<?>> modified, boolean configurational) {
- checkArgument(original.size === 1);
- checkArgument(modified.size === 1);
-
- return modified;
- }
-
- private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafListSchemaNode node,
- List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
- return modified;
- }
-
- private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ContainerSchemaNode node,
- List<Node<?>> original, List<Node<?>> modified, boolean configurational) {
- checkArgument(original.size === 1);
- checkArgument(modified.size === 1);
- return Collections.singletonList(
- merge(node, original.get(0) as CompositeNode, modified.get(0) as CompositeNode, configurational));
- }
-
- private static dispatch def Iterable<? extends Node<?>> mergeMultiple(ListSchemaNode node, List<Node<?>> original,
- List<Node<?>> modified, boolean configurational) {
-
- if(node.keyDefinition === null || node.keyDefinition.empty) {
- return modified;
- }
- val originalMap = (original as List).toIndexMap(node.keyDefinition);
- val modifiedMap = (modified as List).toIndexMap(node.keyDefinition);
-
- val List<Node<?>> mergedNodes = new ArrayList(original.size + modified.size);
- for(entry : modifiedMap.entrySet) {
- val originalEntry = originalMap.get(entry.key);
- if(originalEntry != null) {
- originalMap.remove(entry.key);
- mergedNodes.add(merge(node,originalEntry,entry.value,configurational));
- } else {
- mergedNodes.add(entry.value);
- }
- }
- mergedNodes.addAll(originalMap.values);
- return mergedNodes;
- }
-
- static private def CompositeNode mergeContainer(DataNodeContainer schema, CompositeNode stored,
- CompositeNode modified, boolean config) {
- if (stored == null) {
- return modified;
- }
- checkNotNull(stored)
- checkNotNull(modified)
- checkArgument(stored.nodeType == modified.nodeType);
-
- val mergedChildNodes = new ArrayList<Node<?>>(stored.children.size + modified.children.size);
-
- val toProcess = new HashSet<QName>(stored.keySet);
- toProcess.addAll(modified.keySet);
-
- for (qname : toProcess) {
- val schemaChild = schema.getDataChildByName(qname);
- val storedChildren = stored.get(qname);
- val modifiedChildren = modified.get(qname);
-
- if (modifiedChildren !== null && !modifiedChildren.empty) {
- if (storedChildren === null || storedChildren.empty || schemaChild === null) {
- mergedChildNodes.addAll(modifiedChildren);
- } else {
- mergedChildNodes.addAll(mergeMultiple(schemaChild, storedChildren, modifiedChildren, config));
- }
- } else if (storedChildren !== null && !storedChildren.empty) {
- mergedChildNodes.addAll(storedChildren);
- }
- }
- return new CompositeNodeTOImpl(stored.nodeType, null, mergedChildNodes);
- }
-
-}
-package org.opendaylight.controller.md.sal.dom.store.impl;
+/*
+ * 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.tree.data;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.Test;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version;
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.ContainerNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import com.google.common.base.Optional;
-import com.google.common.primitives.UnsignedLong;
/**
*
.withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_ONE_NAME)) //
.withChild(mapEntry(INNER_LIST_QNAME, NAME_QNAME, TWO_TWO_NAME)) //
.build()) //
- .build();
+ .build();
private SchemaContext schemaContext;
+ private ModificationApplyOperation applyOper;
@Before
public void prepare() {
schemaContext = TestModel.createTestContext();
assertNotNull("Schema context must not be null.", schemaContext);
+ applyOper = SchemaAwareApplyOperation.from(schemaContext);
}
/**
.withNodeIdentifier(new NodeIdentifier(TEST_QNAME))
.withChild(
mapNodeBuilder(OUTER_LIST_QNAME)
- .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
- .withChild(BAR_NODE).build()).build();
+ .withChild(mapEntry(OUTER_LIST_QNAME, ID_QNAME, ONE_ID))
+ .withChild(BAR_NODE).build()).build();
}
@Test
public void basicReadWrites() {
- MutableDataTree modificationTree = MutableDataTree.from(
- DataAndMetadataSnapshot.builder() //
- .setMetadataTree(StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5))) //
- .setSchemaContext(schemaContext) //
- .build(), new SchemaAwareApplyOperationRoot(schemaContext));
- Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.read(OUTER_LIST_2_PATH);
+ DataTreeModification modificationTree = new InMemoryDataTreeModification(new InMemoryDataTreeSnapshot(schemaContext,
+ TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), applyOper),
+ new SchemaAwareApplyOperationRoot(schemaContext));
+ Optional<NormalizedNode<?, ?>> originalBarNode = modificationTree.readNode(OUTER_LIST_2_PATH);
assertTrue(originalBarNode.isPresent());
assertSame(BAR_NODE, originalBarNode.get());
// reads node to /outer-list/1/inner_list/two/value
// and checks if node is already present
- Optional<NormalizedNode<?, ?>> barTwoCModified = modificationTree.read(TWO_TWO_VALUE_PATH);
+ Optional<NormalizedNode<?, ?>> barTwoCModified = modificationTree.readNode(TWO_TWO_VALUE_PATH);
assertTrue(barTwoCModified.isPresent());
assertEquals(ImmutableNodes.leafNode(VALUE_QNAME, "test"), barTwoCModified.get());
// delete node to /outer-list/1/inner_list/two/value
modificationTree.delete(TWO_TWO_VALUE_PATH);
- Optional<NormalizedNode<?, ?>> barTwoCAfterDelete = modificationTree.read(TWO_TWO_VALUE_PATH);
+ Optional<NormalizedNode<?, ?>> barTwoCAfterDelete = modificationTree.readNode(TWO_TWO_VALUE_PATH);
assertFalse(barTwoCAfterDelete.isPresent());
}
- public MutableDataTree createEmptyModificationTree() {
+ public DataTreeModification createEmptyModificationTree() {
/**
* Creates empty Snapshot with associated schema context.
*/
- DataAndMetadataSnapshot emptySnapshot = DataAndMetadataSnapshot.createEmpty(schemaContext);
+ DataTree t = InMemoryDataTreeFactory.getInstance().create();
+ t.setSchemaContext(schemaContext);
/**
*
* context.
*
*/
- MutableDataTree modificationTree = MutableDataTree.from(emptySnapshot, new SchemaAwareApplyOperationRoot(
- schemaContext));
- return modificationTree;
+ return t.takeSnapshot().newModification();
}
@Test
public void createFromEmptyState() {
- MutableDataTree modificationTree = createEmptyModificationTree();
+ DataTreeModification modificationTree = createEmptyModificationTree();
/**
* Writes empty container node to /test
*
/**
* Reads list node from /test/outer-list
*/
- Optional<NormalizedNode<?, ?>> potentialOuterList = modificationTree.read(OUTER_LIST_PATH);
+ Optional<NormalizedNode<?, ?>> potentialOuterList = modificationTree.readNode(OUTER_LIST_PATH);
assertTrue(potentialOuterList.isPresent());
/**
* Reads container node from /test and verifies that it contains test
* node
*/
- Optional<NormalizedNode<?, ?>> potentialTest = modificationTree.read(TEST_PATH);
+ Optional<NormalizedNode<?, ?>> potentialTest = modificationTree.readNode(TEST_PATH);
ContainerNode containerTest = assertPresentAndType(potentialTest, ContainerNode.class);
/**
@Test
public void writeSubtreeReadChildren() {
- MutableDataTree modificationTree = createEmptyModificationTree();
+ DataTreeModification modificationTree = createEmptyModificationTree();
modificationTree.write(TEST_PATH, createTestContainer());
- Optional<NormalizedNode<?, ?>> potential = modificationTree.read(TWO_TWO_PATH);
- MapEntryNode node = assertPresentAndType(potential, MapEntryNode.class);
+ Optional<NormalizedNode<?, ?>> potential = modificationTree.readNode(TWO_TWO_PATH);
+ assertPresentAndType(potential, MapEntryNode.class);
}
@Test
public void writeSubtreeDeleteChildren() {
- MutableDataTree modificationTree = createEmptyModificationTree();
+ DataTreeModification modificationTree = createEmptyModificationTree();
modificationTree.write(TEST_PATH, createTestContainer());
// We verify data are present
- Optional<NormalizedNode<?, ?>> potentialBeforeDelete = modificationTree.read(TWO_TWO_PATH);
- MapEntryNode node = assertPresentAndType(potentialBeforeDelete, MapEntryNode.class);
+ Optional<NormalizedNode<?, ?>> potentialBeforeDelete = modificationTree.readNode(TWO_TWO_PATH);
+ assertPresentAndType(potentialBeforeDelete, MapEntryNode.class);
modificationTree.delete(TWO_TWO_PATH);
- Optional<NormalizedNode<?, ?>> potentialAfterDelete = modificationTree.read(TWO_TWO_PATH);
+ Optional<NormalizedNode<?, ?>> potentialAfterDelete = modificationTree.readNode(TWO_TWO_PATH);
assertFalse(potentialAfterDelete.isPresent());
}
* 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;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-public class SchemaAwareApplyOperationRoot extends SchemaAwareApplyOperation.DataNodeContainerModificationStrategy<ContainerSchemaNode> {
+public class SchemaAwareApplyOperationRoot extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
private final SchemaContext context;
public SchemaAwareApplyOperationRoot(final SchemaContext context) {
+++ /dev/null
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
- <modelVersion>4.0.0</modelVersion>\r
- <parent>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-parent</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </parent>\r
- <artifactId>sal-core-demo</artifactId>\r
- <scm>\r
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
- </scm>\r
-\r
- <dependencies>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-broker-impl</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>yang-data-util</artifactId>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.slf4j</groupId>\r
- <artifactId>slf4j-simple</artifactId>\r
- <version>1.7.2</version>\r
- <scope>runtime</scope>\r
- </dependency>\r
- </dependencies>\r
- <build>\r
- <plugins>\r
- <plugin>\r
- <artifactId>maven-assembly-plugin</artifactId>\r
- <version>2.4</version>\r
- <configuration>\r
- <descriptorRefs>\r
- <descriptorRef>jar-with-dependencies</descriptorRef>\r
- </descriptorRefs>\r
- <archive>\r
- <manifest>\r
- <mainClass>org.opendaylight.controller.sal.demo.SALDemo</mainClass>\r
- </manifest>\r
- </archive>\r
- </configuration>\r
- <executions>\r
- <execution>\r
- <id>make-assembly</id>\r
- <phase>package</phase>\r
- <goals>\r
- <goal>single</goal>\r
- </goals>\r
- </execution>\r
- </executions>\r
- </plugin>\r
-\r
- </plugins>\r
-\r
- </build>\r
-</project>\r
+++ /dev/null
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.sal.demo;\r
-\r
-import java.util.Collection;\r
-import java.util.HashSet;\r
-import java.util.Set;\r
-\r
-import org.opendaylight.controller.sal.core.api.Consumer;\r
-import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;\r
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;\r
-import org.opendaylight.controller.sal.core.api.notify.NotificationService;\r
-import org.opendaylight.controller.yang.common.QName;\r
-import org.opendaylight.controller.yang.data.api.CompositeNode;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-\r
-public class DemoConsumerImpl implements Consumer {\r
-\r
- private ConsumerSession session;\r
- private NotificationService notificationService;\r
- private final String name;\r
- private static Logger log = LoggerFactory.getLogger("AlertLogger");\r
-\r
- private boolean changeAware;\r
-\r
- public DemoConsumerImpl(String name) {\r
- this.name = name;\r
- }\r
-\r
- private NotificationListener alertLogger = new NotificationListener() {\r
-\r
- @Override\r
- public void onNotification(CompositeNode notification) {\r
- System.out.println(name\r
- + ": Received alert: "\r
- + notification.getFirstSimpleByName(\r
- DemoUtils.contentNodeName).getValue());\r
- log.info("AlertLogger: Received notification: " + notification);\r
- }\r
-\r
- @Override\r
- public Set<QName> getSupportedNotifications() {\r
- Set<QName> supported = new HashSet<QName>();\r
- supported.add(DemoUtils.alertNotification);\r
- return supported;\r
- }\r
- };\r
-\r
- private NotificationListener changeLogger = new NotificationListener() {\r
-\r
- @Override\r
- public void onNotification(CompositeNode notification) {\r
- System.out.println(name\r
- + ": Received change: "\r
- + notification.getFirstSimpleByName(\r
- DemoUtils.contentNodeName).getValue());\r
- log.info("ChangeLogger: Received notification: " + notification);\r
- }\r
-\r
- @Override\r
- public Set<QName> getSupportedNotifications() {\r
- Set<QName> supported = new HashSet<QName>();\r
- supported.add(DemoUtils.alertNotification);\r
- return supported;\r
- }\r
- };\r
-\r
- @Override\r
- public void onSessionInitiated(ConsumerSession session) {\r
- this.session = session;\r
- this.notificationService = session\r
- .getService(NotificationService.class);\r
- notificationService.addNotificationListener(\r
- DemoUtils.alertNotification, alertLogger);\r
- if (isChangeAware()) {\r
- notificationService.addNotificationListener(\r
- DemoUtils.changeNotification, changeLogger);\r
- }\r
- }\r
-\r
- @Override\r
- public Collection<ConsumerFunctionality> getConsumerFunctionality() {\r
- Set<ConsumerFunctionality> func = new HashSet<ConsumerFunctionality>();\r
- func.add(alertLogger);\r
- return func;\r
- }\r
-\r
- public void closeSession() {\r
- session.close();\r
- }\r
-\r
- public boolean isChangeAware() {\r
- return changeAware;\r
- }\r
-\r
- public void setChangeAware(boolean changeAware) {\r
- this.changeAware = changeAware;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.demo;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.notify.NotificationProviderService;
-import org.opendaylight.controller.yang.data.api.Node;
-import org.opendaylight.controller.yang.data.util.Nodes;
-
-
-public class DemoProviderImpl implements
- org.opendaylight.controller.sal.core.api.Provider {
-
- private ProviderSession session;
- private NotificationProviderService notifier;
-
- @Override
- public void onSessionInitiated(ProviderSession session) {
- this.session = session;
- notifier = session.getService(NotificationProviderService.class);
- }
-
- @Override
- public Collection<ProviderFunctionality> getProviderFunctionality() {
- return Collections.emptySet();
- }
-
- public void sendAlertNotification(String content) {
- List<Node<?>> nodes = new ArrayList<Node<?>>();
- nodes.add(DemoUtils.contentNode(content));
-
- if (notifier == null) {
- System.out.println("Provider: Error: Session not available");
- System.out
- .println(" Notification Service not available");
- return;
- }
- notifier.sendNotification(Nodes.containerNode(
- DemoUtils.alertNotification, nodes));
- }
-
- public void sendChangeNotification(String content) {
- List<Node<?>> nodes = new ArrayList<Node<?>>();
- nodes.add(DemoUtils.contentNode(content));
-
- if (notifier == null) {
- System.out.println("Provider: Error: Session not available");
- System.out
- .println(" Notification Service not available");
- return;
- }
- notifier.sendNotification(Nodes.containerNode(
- DemoUtils.changeNotification, nodes));
- }
-
- public void closeSession() {
- session.close();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.demo;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Date;
-
-import org.opendaylight.controller.yang.common.QName;
-import org.opendaylight.controller.yang.data.api.Node;
-import org.opendaylight.controller.yang.data.util.Nodes;
-
-
-public class DemoUtils {
-
- public static final URI namespace = uri("urn:cisco:prototype:sal:demo");
- public static final Date revision = new Date();
-
- public static final QName alertNotification = qName("alert");
- public static final QName changeNotification = qName("change");
-
- public static final QName contentNodeName = qName("content");
-
- public static URI uri(String str) {
- try {
- return new URI(str);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- public static QName qName(String str) {
- return new QName(namespace, revision, str);
- }
-
- public static Node<?> contentNode(String content) {
- return Nodes.leafNode(contentNodeName, content);
- }
-}
+++ /dev/null
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.sal.demo;\r
-\r
-import java.io.BufferedReader;\r
-import java.io.IOException;\r
-import java.io.InputStreamReader;\r
-\r
-import org.opendaylight.controller.sal.core.impl.BrokerImpl;\r
-import org.opendaylight.controller.sal.core.impl.NotificationModule;\r
-\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class SALDemo {\r
- protected static final Logger logger = LoggerFactory\r
- .getLogger(SALDemo.class);\r
-\r
- static BrokerImpl broker;\r
- static DemoProviderImpl provider;\r
- static DemoConsumerImpl consumer1;\r
- static DemoConsumerImpl consumer2;\r
-\r
- public static void main(String[] args) {\r
-\r
- initialize();\r
- initializeProvider();\r
- displayHelp();\r
-\r
- BufferedReader in = new BufferedReader(new InputStreamReader(System.in));\r
- String s;\r
- try {\r
- while (true) {\r
-\r
- System.out.print("\nEnter your choice (0 - list): ");\r
- s = in.readLine();\r
- int choice = Integer.parseInt(s.trim());\r
- try {\r
- switch (choice) {\r
- case 0:\r
- displayHelp();\r
- break;\r
- case 1:\r
- registerProvider();\r
- break;\r
- case 2:\r
- registerConsumer1();\r
- break;\r
- case 3:\r
- registerConsumer2();\r
- break;\r
- case 4:\r
- sendAlert(in);\r
- break;\r
- case 5:\r
- sendChange(in);\r
- break;\r
- case 6:\r
- unregisterConsumer1();\r
- break;\r
- case 7:\r
- unregisterConsumer2();\r
- break;\r
- case 8:\r
- unregisterProvider();\r
- break;\r
- case 9:\r
- return;\r
- default:\r
- System.out.println("Please enter valid input.");\r
- break;\r
- }\r
- } catch (Exception e) {\r
- System.out\r
- .println("Operation failed. Reason exception raised: "\r
- + e.getClass().getSimpleName());\r
- System.out.println(" Message: " + e.getMessage());\r
- }\r
-\r
- }\r
- } catch (IOException e) {\r
-\r
- logger.error("",e);\r
- }\r
- }\r
-\r
- private static void registerConsumer1() {\r
- broker.registerConsumer(consumer1);\r
- }\r
-\r
- private static void registerConsumer2() {\r
- broker.registerConsumer(consumer2);\r
- }\r
-\r
- private static void sendAlert(BufferedReader in) throws IOException {\r
- System.out.print("Please enter notification content:");\r
- String content = in.readLine();\r
- provider.sendAlertNotification(content);\r
- }\r
-\r
- private static void sendChange(BufferedReader in) throws IOException {\r
- System.out.print("Please enter notification content:");\r
- String content = in.readLine();\r
- provider.sendChangeNotification(content);\r
- }\r
-\r
- private static void unregisterConsumer1() {\r
- consumer1.closeSession();\r
- }\r
-\r
- private static void unregisterConsumer2() {\r
- consumer2.closeSession();\r
- }\r
-\r
- private static void unregisterProvider() {\r
- provider.closeSession();\r
- }\r
-\r
- private static void displayHelp() {\r
- System.out.println("Usage: ");\r
- System.out.println(" 0) Display Help");\r
- System.out.println(" 1) Register Provider");\r
- System.out.println(" 2) Register Consumer 1 (listening on alert)");\r
- System.out\r
- .println(" 3) Register Consumer 2 (listening on alert,change)");\r
- System.out.println(" 4) Send Alert Notification");\r
- System.out.println(" 5) Send Change Notification");\r
- System.out.println(" 6) Unregister Consumer 1");\r
- System.out.println(" 7) Unregister Consumer 2");\r
- System.out.println(" 8) Unregister Provider");\r
- System.out.println(" 9) Exit");\r
-\r
- }\r
-\r
- private static void initializeProvider() {\r
- provider = new DemoProviderImpl();\r
- }\r
-\r
- private static void initialize() {\r
- System.out.println("Initializing broker");\r
- broker = new BrokerImpl();\r
- NotificationModule notifyModule = new NotificationModule();\r
- broker.addModule(notifyModule);\r
-\r
- consumer1 = new DemoConsumerImpl("Consumer 1");\r
- consumer2 = new DemoConsumerImpl("Consumer 2");\r
- consumer2.setChangeAware(true);\r
- }\r
-\r
- private static void registerProvider() {\r
- broker.registerProvider(provider);\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.sal.demo;
\ No newline at end of file
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
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;
import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceListener;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
import org.opendaylight.protocol.framework.ReconnectStrategy;
import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
import org.opendaylight.protocol.framework.TimedReconnectStrategy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider;
import org.opendaylight.yangtools.yang.model.util.repo.FilesystemSchemaCachingProvider;
import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final boolean candidateSupported;
private final boolean rollbackSupported;
- public NetconfDeviceTwoPhaseCommitTransaction(NetconfDevice device,
- DataModification<InstanceIdentifier, CompositeNode> modification,
- boolean candidateSupported, boolean rollbackOnErrorSupported) {
+ public NetconfDeviceTwoPhaseCommitTransaction(final NetconfDevice device,
+ final DataModification<InstanceIdentifier, CompositeNode> modification,
+ final boolean candidateSupported, final boolean rollbackOnErrorSupported) {
this.device = Preconditions.checkNotNull(device);
this.modification = Preconditions.checkNotNull(modification);
this.candidateSupported = candidateSupported;
}
}
- private void sendMerge(InstanceIdentifier key, CompositeNode value) throws InterruptedException, ExecutionException {
+ private void sendMerge(final InstanceIdentifier key, final CompositeNode value) throws InterruptedException, ExecutionException {
sendEditRpc(createEditStructure(key, Optional.<String>absent(), Optional.of(value)));
}
- private void sendDelete(InstanceIdentifier toDelete) throws InterruptedException, ExecutionException {
+ private void sendDelete(final InstanceIdentifier toDelete) throws InterruptedException, ExecutionException {
sendEditRpc(createEditStructure(toDelete, Optional.of("delete"), Optional.<CompositeNode> absent()));
}
- private void sendEditRpc(CompositeNode editStructure) throws InterruptedException, ExecutionException {
+ private void sendEditRpc(final CompositeNode editStructure) throws InterruptedException, ExecutionException {
CompositeNodeBuilder<ImmutableCompositeNode> builder = configurationRpcBuilder();
builder.setQName(NETCONF_EDIT_CONFIG_QNAME);
builder.add(editStructure);
return ret;
}
- private CompositeNode createEditStructure(InstanceIdentifier dataPath, Optional<String> operation,
- Optional<CompositeNode> lastChildOverride) {
+ private CompositeNode createEditStructure(final InstanceIdentifier dataPath, final Optional<String> operation,
+ final Optional<CompositeNode> lastChildOverride) {
List<PathArgument> path = dataPath.getPath();
List<PathArgument> reversed = Lists.reverse(path);
CompositeNode previous = null;
builder.setAttribute(NETCONF_OPERATION_QNAME, operation.get());
}
if (lastChildOverride.isPresent()) {
- List<Node<?>> children = lastChildOverride.get().getChildren();
+ List<Node<?>> children = lastChildOverride.get().getValue();
for(Node<?> child : children) {
if(!predicates.containsKey(child.getKey())) {
builder.add(child);
*/
package org.opendaylight.controller.sal.connect.netconf;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+
import javax.activation.UnsupportedDataTypeException;
import javax.annotation.Nullable;
+
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
public class NetconfMapping {
public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
static AtomicInteger messageId = new AtomicInteger(0);
- static Node<?> toFilterStructure(InstanceIdentifier identifier) {
+ static Node<?> toFilterStructure(final InstanceIdentifier identifier) {
Node<?> previous = null;
if (identifier.getPath().isEmpty()) {
return null;
return filter("subtree", previous);
}
- static Node<?> toNode(NodeIdentifierWithPredicates argument, Node<?> node) {
+ static Node<?> toNode(final NodeIdentifierWithPredicates argument, final Node<?> node) {
List<Node<?>> list = new ArrayList<>();
for (Map.Entry<QName, Object> arg : argument.getKeyValues().entrySet()) {
list.add(new SimpleNodeTOImpl(arg.getKey(), null, arg.getValue()));
return new CompositeNodeTOImpl(argument.getNodeType(), null, list);
}
- static Node<?> toNode(PathArgument argument, Node<?> node) {
+ static Node<?> toNode(final PathArgument argument, final Node<?> node) {
if (node != null) {
return new CompositeNodeTOImpl(argument.getNodeType(), null, Collections.<Node<?>> singletonList(node));
} else {
}
}
- static CompositeNode toCompositeNode(NetconfMessage message, Optional<SchemaContext> ctx) {
+ static CompositeNode toCompositeNode(final NetconfMessage message, final Optional<SchemaContext> ctx) {
// TODO: implement general normalization to normalize incoming Netconf
// Message
// for Schema Context counterpart
return null;
}
- static CompositeNode toNotificationNode(NetconfMessage message, Optional<SchemaContext> ctx) {
+ static CompositeNode toNotificationNode(final NetconfMessage message, final Optional<SchemaContext> ctx) {
if (ctx.isPresent()) {
SchemaContext schemaContext = ctx.get();
Set<NotificationDefinition> notifications = schemaContext.getNotifications();
return null;
}
- static NetconfMessage toRpcMessage(QName rpc, CompositeNode node, Optional<SchemaContext> ctx) {
+ static NetconfMessage toRpcMessage(final QName rpc, final CompositeNode node, final Optional<SchemaContext> ctx) {
CompositeNodeTOImpl rpcPayload = wrap(NETCONF_RPC_QNAME, flattenInput(node));
Document w3cPayload = null;
try {
if (input instanceof CompositeNode) {
List<Node<?>> nodes = ImmutableList.<Node<?>> builder() //
- .addAll(input.getChildren()) //
- .addAll(Collections2.filter(node.getChildren(), new Predicate<Node<?>>() {
+ .addAll(input.getValue()) //
+ .addAll(Collections2.filter(node.getValue(), new Predicate<Node<?>>() {
@Override
public boolean apply(@Nullable final Node<?> input) {
return input.getNodeType() != inputQName;
return input;
}
- static RpcResult<CompositeNode> toRpcResult(NetconfMessage message, final QName rpc, Optional<SchemaContext> context) {
+ static RpcResult<CompositeNode> toRpcResult(final NetconfMessage message, final QName rpc, final Optional<SchemaContext> context) {
CompositeNode rawRpc;
if (context.isPresent())
if (isDataRetrieQNameReply(rpc)) {
rawRpc = it.toInstance();
// sys(xmlData)
} else {
- rawRpc = (CompositeNode) toCompositeNode(message, context);
+ rawRpc = toCompositeNode(message, context);
}
else {
rawRpc = (CompositeNode) toCompositeNode(message.getDocument());
return Rpcs.getRpcResult(true, rawRpc, Collections.<RpcError> emptySet());
}
- static Element getDataSubtree(Document doc) {
+ static Element getDataSubtree(final Document doc) {
return (Element) doc.getElementsByTagNameNS(NETCONF_URI.toString(), "data").item(0);
}
- static boolean isDataRetrieQNameReply(QName it) {
+ static boolean isDataRetrieQNameReply(final QName it) {
return NETCONF_URI == it.getNamespace()
&& (it.getLocalName() == NETCONF_GET_CONFIG_QNAME.getLocalName() || it.getLocalName() == NETCONF_GET_QNAME
- .getLocalName());
+ .getLocalName());
}
- static CompositeNodeTOImpl wrap(QName name, Node<?> node) {
+ static CompositeNodeTOImpl wrap(final QName name, final Node<?> node) {
if (node != null) {
return new CompositeNodeTOImpl(name, null, Collections.<Node<?>> singletonList(node));
} else {
}
}
- static CompositeNodeTOImpl wrap(QName name, Node<?> additional, Node<?> node) {
+ static CompositeNodeTOImpl wrap(final QName name, final Node<?> additional, final Node<?> node) {
if (node != null) {
return new CompositeNodeTOImpl(name, null, ImmutableList.of(additional, node));
} else {
}
}
- static ImmutableCompositeNode filter(String type, Node<?> node) {
+ static ImmutableCompositeNode filter(final String type, final Node<?> node) {
CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder(); //
it.setQName(NETCONF_FILTER_QNAME);
it.setAttribute(NETCONF_TYPE_QNAME, type);
}
}
- public static Node<?> toCompositeNode(Document document) {
+ public static Node<?> toCompositeNode(final Document document) {
return XmlDocumentUtils.toDomNode(document);
}
- public static void checkValidReply(NetconfMessage input, NetconfMessage output) {
+ public static void checkValidReply(final NetconfMessage input, final NetconfMessage output) {
String inputMsgId = input.getDocument().getDocumentElement().getAttribute("message-id");
String outputMsgId = output.getDocument().getDocumentElement().getAttribute("message-id");
}
}
- public static void checkSuccessReply(NetconfMessage output) throws NetconfDocumentedException {
+ public static void checkSuccessReply(final NetconfMessage output) throws NetconfDocumentedException {
if(NetconfMessageUtil.isErrorMessage(output)) {
throw new IllegalStateException(String.format("Response contains error: %s", XmlUtil.toString(output.getDocument())));
}
* @param routeId route identifier
* @return remote network address
*/
- private String lookupRemoteAddressForGlobalRpc(RpcRouter.RouteIdentifier routeId){
+ private String lookupRemoteAddressForGlobalRpc(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
checkNotNull(routeId, "route must not be null");
- Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable = routingTableProvider.getRoutingTable();
+ Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable = routingTableProvider.getRoutingTable();
checkNotNull(routingTable.isPresent(), "Routing table is null");
String address = null;
* @param routeId route identifier
* @return remote network address
*/
- private String lookupRemoteAddressForRpc(RpcRouter.RouteIdentifier routeId){
+ private String lookupRemoteAddressForRpc(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
checkNotNull(routeId, "route must not be null");
- Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable = routingTableProvider.getRoutingTable();
+ Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable = routingTableProvider.getRoutingTable();
checkNotNull(routingTable.isPresent(), "Routing table is null");
String address = routingTable.get().getLastAddedRoute(routeId);
*/
private void closeZmqContext() {
ExecutorService exec = Executors.newSingleThreadExecutor();
- FutureTask zmqTermination = new FutureTask(new Runnable() {
+ FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
@Override
public void run() {
package org.opendaylight.controller.sal.connector.remoterpc;
-import org.zeromq.ZMQ;
-
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
+import org.zeromq.ZMQ;
+
/**
* Provides a ZeroMQ Context object
*/
public class Context {
- private ZMQ.Context zmqContext = ZMQ.context(1);
+ private final ZMQ.Context zmqContext = ZMQ.context(1);
private String uri;
private final String DEFAULT_RPC_PORT = "5554";
*/
private String findIpAddress() {
String hostAddress = null;
- Enumeration e = null;
+ Enumeration<?> e = null;
try {
e = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e1) {
NetworkInterface n = (NetworkInterface) e.nextElement();
- Enumeration ee = n.getInetAddresses();
+ Enumeration<?> ee = n.getInetAddresses();
while (ee.hasMoreElements()) {
InetAddress i = (InetAddress) ee.nextElement();
if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
package org.opendaylight.controller.sal.connector.remoterpc;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-
public interface RemoteRpcClient extends AutoCloseable{
void setRoutingTableProvider(RoutingTableProvider provider);
-
+
void stop();
-
+
void start();
}
private ProviderSession brokerSession;
private RpcProvisionRegistry rpcProvisionRegistry;
private BundleContext context;
- private ServiceTracker clusterTracker;
+ private ServiceTracker<?, ?> clusterTracker;
public RemoteRpcProvider(ServerImpl server, ClientImpl client) {
this.server = server;
}
- private RoutingTable<RpcRouter.RouteIdentifier, String> getRoutingTable(){
- Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable =
+ private RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> getRoutingTable(){
+ Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> routingTable =
routingTableProvider.getRoutingTable();
checkState(routingTable.isPresent(), "Routing table is null");
RouteIdentifierImpl routeId = new RouteIdentifierImpl();
routeId.setType(rpc);
- RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+ RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
try {
routingTable.addGlobalRoute(routeId, server.getServerAddress());
RouteIdentifierImpl routeId = new RouteIdentifierImpl();
routeId.setType(rpc);
- RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+ RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
try {
routingTable.removeGlobalRoute(routeId);
*
* @param announcements
*/
- private void announce(Set<RpcRouter.RouteIdentifier> announcements) {
+ private void announce(Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements) {
_logger.debug("Announcing [{}]", announcements);
- RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+ RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
try {
routingTable.addRoutes(announcements, server.getServerAddress());
} catch (RoutingTableException | SystemException e) {
*
* @param removals
*/
- private void remove(Set<RpcRouter.RouteIdentifier> removals){
+ private void remove(Set<RpcRouter.RouteIdentifier<?, ?, ?>> removals){
_logger.debug("Removing [{}]", removals);
- RoutingTable<RpcRouter.RouteIdentifier, String> routingTable = getRoutingTable();
+ RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable = getRoutingTable();
try {
routingTable.removeRoutes(removals, server.getServerAddress());
} catch (RoutingTableException | SystemException e) {
* @param changes
* @return
*/
- private Set<RpcRouter.RouteIdentifier> getRouteIdentifiers(Map<RpcRoutingContext, Set<InstanceIdentifier>> changes) {
+ private Set<RpcRouter.RouteIdentifier<?, ?, ?>> getRouteIdentifiers(Map<RpcRoutingContext, Set<InstanceIdentifier>> changes) {
RouteIdentifierImpl routeId = null;
- Set<RpcRouter.RouteIdentifier> routeIdSet = new HashSet<RpcRouter.RouteIdentifier>();
+ Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdSet = new HashSet<>();
for (RpcRoutingContext context : changes.keySet()){
routeId = new RouteIdentifierImpl();
package org.opendaylight.controller.sal.connector.remoterpc;
-import com.google.common.base.Optional;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
import org.opendaylight.controller.sal.connector.remoterpc.impl.RoutingTableImpl;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
+import com.google.common.base.Optional;
+
public class RoutingTableProvider implements AutoCloseable {
@SuppressWarnings("rawtypes")
final ServiceTracker<RoutingTable,RoutingTable> tracker;
- private RoutingTableImpl routingTableImpl = null;
+ private RoutingTableImpl<?, ?> routingTableImpl = null;
//final private RouteChangeListener routeChangeListener;
-
-
+
+
public RoutingTableProvider(BundleContext ctx){//,RouteChangeListener rcl) {
@SuppressWarnings("rawtypes")
ServiceTracker<RoutingTable, RoutingTable> rawTracker = new ServiceTracker<>(ctx, RoutingTable.class, null);
//routeChangeListener = rcl;
}
-
- public Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> getRoutingTable() {
+
+ public Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> getRoutingTable() {
@SuppressWarnings("unchecked")
- RoutingTable<RpcRouter.RouteIdentifier,String> tracked = tracker.getService();
+ RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> tracked = tracker.getService();
if(tracked instanceof RoutingTableImpl){
if(routingTableImpl != tracked){
- routingTableImpl= (RoutingTableImpl)tracked;
+ routingTableImpl= (RoutingTableImpl<?, ?>)tracked;
//routingTableImpl.setRouteChangeListener(routeChangeListener);
}
}
*/
package org.opendaylight.controller.sal.connector.remoterpc;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Sets;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
-import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashSet;
-import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
/**
* ZeroMq based implementation of RpcRouter.
*/
public class ServerImpl implements RemoteRpcServer {
- private Logger _logger = LoggerFactory.getLogger(ServerImpl.class);
+ private final Logger _logger = LoggerFactory.getLogger(ServerImpl.class);
private ExecutorService serverPool;
protected ServerRequestHandler handler;
private volatile State status = State.STOPPED;
private String serverAddress;
- private int port;
+ private final int port;
public static enum State {
STARTING, STARTED, STOPPED;
*/
private void closeZmqContext() {
ExecutorService exec = Executors.newSingleThreadExecutor();
- FutureTask zmqTermination = new FutureTask(new Runnable() {
+ FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
@Override
public void run() {
* @return
*/
private String findIpAddress() {
- Enumeration e = null;
+ Enumeration<?> e = null;
try {
e = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e1) {
NetworkInterface n = (NetworkInterface) e.nextElement();
- Enumeration ee = n.getInetAddresses();
+ Enumeration<?> ee = n.getInetAddresses();
while (ee.hasMoreElements()) {
InetAddress i = (InetAddress) ee.nextElement();
_logger.debug("Trying address {}", i);
package org.opendaylight.controller.sal.connector.remoterpc;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.RouteIdentifierImpl;
import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
import org.opendaylight.controller.sal.core.api.Broker;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zeromq.ZMQ;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Collection;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
/**
*
*/
public class ServerRequestHandler implements AutoCloseable{
- private Logger _logger = LoggerFactory.getLogger(ServerRequestHandler.class);
+ private final Logger _logger = LoggerFactory.getLogger(ServerRequestHandler.class);
private final String DEFAULT_NAME = "remote-rpc-worker";
- private String dealerAddress;
- private String serverAddress;
- private int workerCount;
- private ZMQ.Context context;
- private Broker.ProviderSession broker;
+ private final String dealerAddress;
+ private final String serverAddress;
+ private final int workerCount;
+ private final ZMQ.Context context;
+ private final Broker.ProviderSession broker;
private RequestHandlerThreadPool workerPool;
private final AtomicInteger threadId = new AtomicInteger();
* Worker to handles RPC request
*/
private class Worker implements Runnable {
- private String name;
+ private final String name;
public Worker(int id){
this.name = DEFAULT_NAME + "-" + id;
}
class MessageHandler{
- private ZMQ.Socket socket;
+ private final ZMQ.Socket socket;
private Message message; //parsed message received on zmq server port
private boolean messageForBroker = false; //if the message is valid and not a "ping" message
CompositeNode payload = (result != null) ? result.getResult() : null;
String recipient = null;
- RpcRouter.RouteIdentifier routeId = null;
+ RpcRouter.RouteIdentifier<?, ?, ?> routeId = null;
if (message != null) {
recipient = message.getSender();
private MessageType type;
private String sender;
private String recipient;
- private RpcRouter.RouteIdentifier route;
+ private RpcRouter.RouteIdentifier<?, ?, ?> route;
private Object payload;
public MessageType getType() {
this.sender = sender;
}
- public RpcRouter.RouteIdentifier getRoute() {
+ public RpcRouter.RouteIdentifier<?, ?, ?> getRoute() {
return route;
}
- public void setRoute(RpcRouter.RouteIdentifier route) {
+ public void setRoute(RpcRouter.RouteIdentifier<?, ?, ?> route) {
this.route = route;
}
return o.readObject();
}
- public static class Response extends Message implements RpcRouter.RpcReply {
+ public static class Response extends Message implements RpcRouter.RpcReply<Object> {
private static final long serialVersionUID = 1L;
private ResponseCode code; // response code
return this;
}
- public MessageBuilder route(RpcRouter.RouteIdentifier route){
+ public MessageBuilder route(RpcRouter.RouteIdentifier<?, ?, ?> route){
message.setRoute(route);
return this;
}
//mock routing table
routingTableProvider = mock(RoutingTableProvider.class);
- RoutingTable<RpcRouter.RouteIdentifier, String> mockRoutingTable = new MockRoutingTable<String, String>();
- Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
+ RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> mockRoutingTable = new MockRoutingTable<String, String>();
+ Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
when(routingTableProvider.getRoutingTable()).thenReturn(optionalRoutingTable);
//mock ClientRequestHandler
private Message handleMessageWithTimeout(final Message request) {
Message response = null;
- FutureTask task = new FutureTask(new Callable<Message>() {
+ FutureTask<?> task = new FutureTask<Message>(new Callable<Message>() {
@Override
public Message call() {
*/
package org.opendaylight.controller.sal.connector.remoterpc;
-import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener;
+import java.util.HashSet;
+import java.util.Set;
+
import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
/**
* Mock implementation of routing table
*/
}
@Override
- public Set getRoutes(Object o) {
+ public Set<String> getRoutes(Object o) {
Set<String> routes = new HashSet<String>();
routes.add("localhost:5554");
return routes;
package org.opendaylight.controller.sal.connector.remoterpc;
-import com.google.common.base.Optional;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+
import junit.framework.Assert;
-import org.junit.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
import org.opendaylight.controller.sal.connector.remoterpc.utils.MessagingUtil;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.zeromq.ZMQ;
+
import zmq.Ctx;
import zmq.SocketBase;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ThreadPoolExecutor;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import com.google.common.base.Optional;
public class ServerImplTest {
server = new ServerImpl(port);
server.setBrokerSession(brokerSession);
- RoutingTable<RpcRouter.RouteIdentifier, String> mockRoutingTable = new MockRoutingTable<String, String>();
- Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
+ RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> mockRoutingTable = new MockRoutingTable<String, String>();
+ Optional<RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String>> optionalRoutingTable = Optional.fromNullable(mockRoutingTable);
when(routingTableProvider.getRoutingTable()).thenReturn(optionalRoutingTable);
when(brokerSession.addRpcRegistrationListener(listener)).thenReturn(null);
- when(brokerSession.getSupportedRpcs()).thenReturn(Collections.EMPTY_SET);
+ when(brokerSession.getSupportedRpcs()).thenReturn(Collections.<QName>emptySet());
when(brokerSession.rpc(null, mock(CompositeNode.class))).thenReturn(null);
server.start();
Thread.sleep(5000);//wait for server to start
Thread[] threads = new Thread[Thread.activeCount()];
Thread.enumerate(threads);
- List<Thread> foundThreads = new ArrayList();
+ List<Thread> foundThreads = new ArrayList<Thread>();
for (Thread t : threads) {
if (t.getName().startsWith(name))
foundThreads.add(t);
package org.opendaylight.controller.sal.connector.remoterpc;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
import junit.framework.Assert;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.sal.core.api.Broker;
import org.zeromq.ZMQ;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import static org.mockito.Mockito.mock;
-
public class ServerRequestHandlerTest {
ServerRequestHandler handler;
ZMQ.Context context;
ExecutorService executorService = Executors.newCachedThreadPool();
- private int workerCount = 2;
- private String mockDealerAddress = "inproc://rpc-request-handler";
- private String mockServerIp = "localhost";
- private int mockServerPort = 5554;
+ private final int workerCount = 2;
+ private final String mockDealerAddress = "inproc://rpc-request-handler";
+ private final String mockServerIp = "localhost";
+ private final int mockServerPort = 5554;
@Before
public void setUp() throws Exception {
Thread[] threads = new Thread[Thread.activeCount()];
Thread.enumerate(threads);
- List<Thread> foundThreads = new ArrayList();
+ List<Thread> foundThreads = new ArrayList<Thread>();
for (Thread t : threads) {
if (t.getName().startsWith(name))
foundThreads.add(t);
package org.opendaylight.controller.sal.connector.remoterpc.utils;
-import junit.framework.Assert;
-import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.zeromq.ZMQ;
-
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
+import junit.framework.Assert;
+
+import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
public class MessagingUtil {
private static final Logger _logger = LoggerFactory.getLogger(MessagingUtil.class);
if (context == null) return;
ExecutorService exec = Executors.newSingleThreadExecutor();
- FutureTask zmqTermination = new FutureTask(new Runnable() {
+ FutureTask<?> zmqTermination = new FutureTask<Void>(new Runnable() {
@Override
public void run() {
package org.opendaylight.controller.sal.connector.remoterpc.utils;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.controller.sal.connector.remoterpc.dto.Message;
import org.opendaylight.controller.sal.connector.remoterpc.util.XmlUtils;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.zeromq.ZMQ;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
public class RemoteServerTestClient {
}
public Message createAddFlowMessage(String serverAddress ){
- RpcRouter.RouteIdentifier routeIdentifier = getAddFlowRpcIdentifier();
+ RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier = getAddFlowRpcIdentifier();
Message addFlow = new Message.MessageBuilder()
.type(Message.MessageType.REQUEST)
return addFlow;
}
- private RpcRouter.RouteIdentifier getAddFlowRpcIdentifier(){
+ private RpcRouter.RouteIdentifier<?, ?, ?> getAddFlowRpcIdentifier(){
throw new UnsupportedOperationException();
}
<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>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-impl</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-restconf</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-yang-types-20130715</artifactId>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<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>
*/
package org.opendaylight.controller.sal.rest.api;
+import org.opendaylight.yangtools.yang.common.QName;
+
public class Draft02 {
- public static class MediaTypes {
- public static final String API = "application/yang.api";
- public static final String DATASTORE = "application/yang.datastore";
- public static final String DATA = "application/yang.data";
- public static final String OPERATION = "application/yang.operation";
- public static final String PATCH = "application/yang.patch";
- public static final String PATCH_STATUS = "application/yang.patch-status";
- public static final String STREAM = "application/yang.stream";
+ public static interface MediaTypes {
+ String API = "application/yang.api";
+ String DATASTORE = "application/yang.datastore";
+ String DATA = "application/yang.data";
+ String OPERATION = "application/yang.operation";
+ String PATCH = "application/yang.patch";
+ String PATCH_STATUS = "application/yang.patch-status";
+ String STREAM = "application/yang.stream";
+ }
+
+ public static interface RestConfModule {
+ String REVISION = "2013-10-19";
+
+ String NAME = "ietf-restconf";
+
+ String NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-restconf";
+
+ String RESTCONF_GROUPING_SCHEMA_NODE = "restconf";
+
+ String RESTCONF_CONTAINER_SCHEMA_NODE = "restconf";
+
+ String MODULES_CONTAINER_SCHEMA_NODE = "modules";
+
+ String MODULE_LIST_SCHEMA_NODE = "module";
+
+ String STREAMS_CONTAINER_SCHEMA_NODE = "streams";
+
+ String STREAM_LIST_SCHEMA_NODE = "stream";
+
+ String OPERATIONS_CONTAINER_SCHEMA_NODE = "operations";
+
+ String ERRORS_GROUPING_SCHEMA_NODE = "errors";
+
+ String ERRORS_CONTAINER_SCHEMA_NODE = "errors";
+
+ String ERROR_LIST_SCHEMA_NODE = "error";
+
+ QName IETF_RESTCONF_QNAME = QName.create( Draft02.RestConfModule.NAMESPACE,
+ Draft02.RestConfModule.REVISION,
+ Draft02.RestConfModule.NAME );
+
+ QName ERRORS_CONTAINER_QNAME = QName.create( IETF_RESTCONF_QNAME, ERRORS_CONTAINER_SCHEMA_NODE );
+
+ QName ERROR_LIST_QNAME = QName.create( IETF_RESTCONF_QNAME, ERROR_LIST_SCHEMA_NODE );
+
+ QName ERROR_TYPE_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-type" );
+
+ QName ERROR_TAG_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-tag" );
+
+ QName ERROR_APP_TAG_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-app-tag" );
+
+ QName ERROR_MESSAGE_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-message" );
+
+ QName ERROR_INFO_QNAME = QName.create( IETF_RESTCONF_QNAME, "error-info" );
}
-
- public static class Paths {
-
+
+
+ public static interface Paths {
+
}
}
import java.io.IOException;
import java.net.URI;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
private MountInstance mountPoint;
private final Logger logger = LoggerFactory.getLogger(JsonMapper.class);
- public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema, MountInstance mountPoint)
+ public void write(final JsonWriter writer, final CompositeNode data, final DataNodeContainer schema, final MountInstance mountPoint)
throws IOException {
Preconditions.checkNotNull(writer);
Preconditions.checkNotNull(data);
foundLists.clear();
}
- private void writeChildrenOfParent(JsonWriter writer, CompositeNode parent, DataNodeContainer parentSchema)
+ private void writeChildrenOfParent(final JsonWriter writer, final CompositeNode parent, final DataNodeContainer parentSchema)
throws IOException {
checkNotNull(parent);
- checkNotNull(parentSchema);
- for (Node<?> child : parent.getChildren()) {
- DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
+ Set<DataSchemaNode> parentSchemaChildNodes = parentSchema == null ?
+ Collections.<DataSchemaNode>emptySet() : parentSchema.getChildNodes();
+
+
+ for (Node<?> child : parent.getValue()) {
+ DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchemaChildNodes);
if (childSchema == null) {
- throw new UnsupportedDataTypeException("Probably the data node \"" + child.getNodeType().getLocalName()
- + "\" is not conform to schema");
- }
+ // Node may not conform to schema or allows "anyxml" - we'll process it.
- if (childSchema instanceof ContainerSchemaNode) {
+ logger.debug( "No schema found for data node \"" + child.getNodeType() );
+
+ handleNoSchemaFound( writer, child, parent );
+ }
+ else if (childSchema instanceof ContainerSchemaNode) {
Preconditions.checkState(child instanceof CompositeNode,
"Data representation of Container should be CompositeNode - " + child.getNodeType());
writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
}
}
- for (Node<?> child : parent.getChildren()) {
- DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
+ for (Node<?> child : parent.getValue()) {
+ DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchemaChildNodes);
if (childSchema instanceof LeafListSchemaNode) {
- foundLeafLists.remove((LeafListSchemaNode) childSchema);
+ foundLeafLists.remove(childSchema);
} else if (childSchema instanceof ListSchemaNode) {
- foundLists.remove((ListSchemaNode) childSchema);
+ foundLists.remove(childSchema);
}
}
}
- private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
+ private void handleNoSchemaFound( final JsonWriter writer, final Node<?> node,
+ final CompositeNode parent ) throws IOException {
+ if( node instanceof SimpleNode<?> ) {
+ writeName( node, null, writer );
+ Object value = node.getValue();
+ if( value != null ) {
+ writer.value( String.valueOf( value ) );
+ }
+ } else { // CompositeNode
+ Preconditions.checkState( node instanceof CompositeNode,
+ "Data representation of Container should be CompositeNode - " + node.getNodeType() );
+
+ writeContainer( writer, (CompositeNode) node, null );
+ }
+ }
+
+ private DataSchemaNode findFirstSchemaForNode(final Node<?> node, final Set<DataSchemaNode> dataSchemaNode) {
for (DataSchemaNode dsn : dataSchemaNode) {
if (node.getNodeType().equals(dsn.getQName())) {
return dsn;
return null;
}
- private void writeContainer(JsonWriter writer, CompositeNode node, ContainerSchemaNode schema) throws IOException {
+ private void writeContainer(final JsonWriter writer, final CompositeNode node, final ContainerSchemaNode schema) throws IOException {
writeName(node, schema, writer);
writer.beginObject();
writeChildrenOfParent(writer, node, schema);
writer.endObject();
}
- private void writeList(JsonWriter writer, CompositeNode nodeParent, CompositeNode node, ListSchemaNode schema)
+ private void writeList(final JsonWriter writer, final CompositeNode nodeParent, final CompositeNode node, final ListSchemaNode schema)
throws IOException {
writeName(node, schema, writer);
writer.beginArray();
writer.endArray();
}
- private void writeLeafList(JsonWriter writer, CompositeNode nodeParent, SimpleNode<?> node,
- LeafListSchemaNode schema) throws IOException {
+ private void writeLeafList(final JsonWriter writer, final CompositeNode nodeParent, final SimpleNode<?> node,
+ final LeafListSchemaNode schema) throws IOException {
writeName(node, schema, writer);
writer.beginArray();
writer.endArray();
}
- private void writeLeaf(JsonWriter writer, SimpleNode<?> node, LeafSchemaNode schema) throws IOException {
+ private void writeLeaf(final JsonWriter writer, final SimpleNode<?> node, final LeafSchemaNode schema) throws IOException {
writeName(node, schema, writer);
writeValueOfNodeByType(writer, node, schema.getType(), schema);
}
- private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type,
- DataSchemaNode schema) throws IOException {
+ private void writeValueOfNodeByType(final JsonWriter writer, final SimpleNode<?> node, final TypeDefinition<?> type,
+ final DataSchemaNode schema) throws IOException {
TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(type);
}
}
- private void writeIdentityValuesDTOToJson(JsonWriter writer, IdentityValuesDTO valueDTO) throws IOException {
+ private void writeIdentityValuesDTOToJson(final JsonWriter writer, final IdentityValuesDTO valueDTO) throws IOException {
StringBuilder result = new StringBuilder();
for (IdentityValue identityValue : valueDTO.getValuesWithNamespaces()) {
result.append("/");
writer.value(result.toString());
}
- private void writeModuleNameAndIdentifier(StringBuilder result, IdentityValue identityValue) {
+ private void writeModuleNameAndIdentifier(final StringBuilder result, final IdentityValue identityValue) {
String moduleName = ControllerContext.getInstance().findModuleNameByNamespace(
URI.create(identityValue.getNamespace()));
if (moduleName != null && !moduleName.isEmpty()) {
result.append(identityValue.getValue());
}
- private void writeStringRepresentation(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> baseType,
- Class<?> requiredType) throws IOException {
+ private void writeStringRepresentation(final JsonWriter writer, final SimpleNode<?> node, final TypeDefinition<?> baseType,
+ final Class<?> requiredType) throws IOException {
Object value = node.getValue();
logger.debug("Value of " + baseType.getQName().getNamespace() + ":" + baseType.getQName().getLocalName()
+ " is not instance of " + requiredType.getClass() + " but is " + node.getValue().getClass());
}
}
- private void writeEmptyDataTypeToJson(JsonWriter writer) throws IOException {
+ private void writeEmptyDataTypeToJson(final JsonWriter writer) throws IOException {
writer.beginArray();
writer.nullValue();
writer.endArray();
}
- private void writeName(Node<?> node, DataSchemaNode schema, JsonWriter writer) throws IOException {
+ private void writeName(final Node<?> node, final DataSchemaNode schema, final JsonWriter writer) throws IOException {
String nameForOutput = node.getNodeType().getLocalName();
- if (schema.isAugmenting()) {
+ if ( schema != null && schema.isAugmenting()) {
ControllerContext contContext = ControllerContext.getInstance();
CharSequence moduleName = null;
if (mountPoint == null) {
private static final long serialVersionUID = -3147729419814417666L;
private final String value;
- public NumberForJsonWriter(String value) {
+ public NumberForJsonWriter(final String value) {
this.value = value;
}
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
@Provider
@Consumes({ Draft02.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.OPERATION + RestconfService.JSON,
public enum JsonToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
INSTANCE;
+ private final static Logger LOG = LoggerFactory.getLogger( JsonToCompositeNodeProvider.class );
+
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return true;
JsonReader jsonReader = new JsonReader();
try {
return jsonReader.read(entityStream);
- } catch (UnsupportedFormatException e) {
- throw new WebApplicationException(e, Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage())
- .build());
+ } catch (Exception e) {
+ LOG.debug( "Error parsing json input", e );
+ throw new RestconfDocumentedException(
+ "Error parsing input: " + e.getMessage(),
+ ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE );
}
}
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
+import com.google.common.collect.ImmutableSet;
+
public class RestconfApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ return ImmutableSet.<Class<?>>of( RestconfDocumentedExceptionMapper.class );
+ }
+
@Override
public Set<Object> getSingletons() {
Set<Object> singletons = new HashSet<>();
return singletons;
}
+
}
--- /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.rest.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Map.Entry;
+
+import javax.activation.UnsupportedDataTypeException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import static org.opendaylight.controller.sal.rest.api.Draft02.RestConfModule.*;
+
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * This class defines an ExceptionMapper that handles RestconfDocumentedExceptions thrown by
+ * resource implementations and translates appropriately to restconf error response as defined in
+ * the RESTCONF RFC draft.
+ *
+ * @author Thomas Pantelis
+ */
+@Provider
+public class RestconfDocumentedExceptionMapper implements ExceptionMapper<RestconfDocumentedException> {
+
+ private final static Logger LOG = LoggerFactory.getLogger( RestconfDocumentedExceptionMapper.class );
+
+ @Context
+ private HttpHeaders headers;
+
+ @Override
+ public Response toResponse( RestconfDocumentedException exception ) {
+
+ LOG.debug( "In toResponse: {}", exception.getMessage() );
+
+ // Default to the content type if there's no Accept header
+
+ MediaType mediaType = headers.getMediaType();
+
+ List<MediaType> accepts = headers.getAcceptableMediaTypes();
+
+ LOG.debug( "Accept headers: {}", accepts );
+
+ if( accepts != null && accepts.size() > 0 ) {
+ mediaType = accepts.get( 0 ); // just pick the first one
+ }
+
+ LOG.debug( "Using MediaType: {}", mediaType );
+
+ List<RestconfError> errors = exception.getErrors();
+ if( errors.isEmpty() ) {
+ // We don't actually want to send any content but, if we don't set any content here,
+ // the tomcat front-end will send back an html error report. To prevent that, set a
+ // single space char in the entity.
+
+ return Response.status( exception.getStatus() )
+ .type( MediaType.TEXT_PLAIN_TYPE )
+ .entity( " " ).build();
+ }
+
+ Status status = errors.iterator().next().getErrorTag().getStatusCode();
+
+ ControllerContext context = ControllerContext.getInstance();
+ DataNodeContainer errorsSchemaNode = (DataNodeContainer)context.getRestconfModuleErrorsSchemaNode();
+
+ if( errorsSchemaNode == null ) {
+ return Response.status( status )
+ .type( MediaType.TEXT_PLAIN_TYPE )
+ .entity( exception.getMessage() ).build();
+ }
+
+ ImmutableList.Builder<Node<?>> errorNodes = ImmutableList.<Node<?>> builder();
+ for( RestconfError error: errors ) {
+ errorNodes.add( toDomNode( error ) );
+ }
+
+ ImmutableCompositeNode errorsNode =
+ ImmutableCompositeNode.create( ERRORS_CONTAINER_QNAME, errorNodes.build() );
+
+ Object responseBody;
+ if( mediaType.getSubtype().endsWith( "json" ) ) {
+ responseBody = toJsonResponseBody( errorsNode, errorsSchemaNode );
+ }
+ else {
+ responseBody = toXMLResponseBody( errorsNode, errorsSchemaNode );
+ }
+
+ return Response.status( status ).type( mediaType ).entity( responseBody ).build();
+ }
+
+ private Object toJsonResponseBody( ImmutableCompositeNode errorsNode,
+ DataNodeContainer errorsSchemaNode ) {
+
+ JsonMapper jsonMapper = new JsonMapper();
+
+ Object responseBody = null;
+ try {
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ JsonWriter writer = new JsonWriter( new OutputStreamWriter( outStream, "UTF-8" ) );
+ writer.setIndent( " " );
+
+ jsonMapper.write( writer, errorsNode, errorsSchemaNode, null );
+ writer.flush();
+
+ responseBody = outStream.toString( "UTF-8" );
+ }
+ catch( IOException e ) {
+ LOG.error( "Error writing error response body", e );
+ }
+
+ return responseBody;
+ }
+
+ private Object toXMLResponseBody( ImmutableCompositeNode errorsNode,
+ DataNodeContainer errorsSchemaNode ) {
+
+ XmlMapper xmlMapper = new XmlMapper();
+
+ Object responseBody = null;
+ try {
+ Document xmlDoc = xmlMapper.write( errorsNode, errorsSchemaNode );
+
+ responseBody = documentToString( xmlDoc );
+ }
+ catch( TransformerException | UnsupportedDataTypeException | UnsupportedEncodingException e ) {
+ LOG.error( "Error writing error response body", e );
+ }
+
+ return responseBody;
+ }
+
+ private String documentToString( Document doc ) throws TransformerException, UnsupportedEncodingException {
+ Transformer transformer = createTransformer();
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+
+ transformer.transform( new DOMSource( doc ), new StreamResult( outStream ) );
+
+ return outStream.toString( "UTF-8" );
+ }
+
+ private Transformer createTransformer() throws TransformerFactoryConfigurationError,
+ TransformerConfigurationException {
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer transformer = tf.newTransformer();
+ transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no" );
+ transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
+ transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
+ transformer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
+ transformer.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "4" );
+ return transformer;
+ }
+
+ private Node<?> toDomNode( RestconfError error ) {
+
+ CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
+ builder.setQName( ERROR_LIST_QNAME );
+
+ addLeaf( builder, ERROR_TYPE_QNAME, error.getErrorType().getErrorTypeTag() );
+ addLeaf( builder, ERROR_TAG_QNAME, error.getErrorTag().getTagValue() );
+ addLeaf( builder, ERROR_MESSAGE_QNAME, error.getErrorMessage() );
+ addLeaf( builder, ERROR_APP_TAG_QNAME, error.getErrorAppTag() );
+
+ Node<?> errorInfoNode = parseErrorInfo( error.getErrorInfo() );
+ if( errorInfoNode != null ) {
+ builder.add( errorInfoNode );
+ }
+
+ return builder.toInstance();
+ }
+
+ private Node<?> parseErrorInfo( String errorInfo ) {
+ if( Strings.isNullOrEmpty( errorInfo ) ) {
+ return null;
+ }
+
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware( true );
+ factory.setCoalescing( true );
+ factory.setIgnoringElementContentWhitespace( true );
+ factory.setIgnoringComments( true );
+
+ // Wrap the error info content in a root <error-info> element so it can be parsed
+ // as XML. The error info content may or may not be XML. If not then it will be
+ // parsed as text content of the <error-info> element.
+
+ String errorInfoWithRoot =
+ new StringBuilder( "<error-info xmlns=\"" ).append( NAMESPACE ).append( "\">" )
+ .append( errorInfo ).append( "</error-info>" ).toString();
+
+ Document doc = null;
+ try {
+ doc = factory.newDocumentBuilder().parse(
+ new InputSource( new StringReader( errorInfoWithRoot ) ) );
+ }
+ catch( Exception e ) {
+ // TODO: what if the content is text that happens to contain invalid markup? Could
+ // wrap in CDATA and try again.
+
+ LOG.warn( "Error parsing restconf error-info, \"" + errorInfo + "\", as XML: " +
+ e.toString() );
+ return null;
+ }
+
+ Node<?> errorInfoNode = XmlDocumentUtils.toDomNode( doc );
+
+ if( errorInfoNode instanceof CompositeNode ) {
+ CompositeNode compositeNode = (CompositeNode)XmlDocumentUtils.toDomNode( doc );
+
+ // At this point the QName for the "error-info" CompositeNode doesn't contain the revision
+ // as it isn't present in the XML. So we'll copy all the child nodes and create a new
+ // CompositeNode with the full QName. This is done so the XML/JSON mapping code can
+ // locate the schema.
+
+ ImmutableList.Builder<Node<?>> childNodes = ImmutableList.builder();
+ for( Entry<QName, List<Node<?>>> entry: compositeNode.entrySet() ) {
+ childNodes.addAll( entry.getValue() );
+ }
+
+ errorInfoNode = ImmutableCompositeNode.create( ERROR_INFO_QNAME, childNodes.build() );
+ }
+
+ return errorInfoNode;
+ }
+
+ private void addLeaf( CompositeNodeBuilder<ImmutableCompositeNode> builder, QName qname,
+ String value ) {
+ if( !Strings.isNullOrEmpty( value ) ) {
+ builder.addLeaf( qname, value );
+ }
+ }
+}
private ListenerRegistration<SchemaServiceListener> listenerRegistration;
private ServiceTracker<Broker, Broker> brokerServiceTrancker;
private BundleContext bundleContext;
- private ProviderSession session;
private Thread webSocketServerThread;
@Override
}
}
webSocketServerThread.interrupt();
- session.close();
brokerServiceTrancker.close();
}
import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
- return true;
+ return type.equals( StructuredData.class );
}
@Override
throws IOException, WebApplicationException {
CompositeNode data = t.getData();
if (data == null) {
- throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
+ throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
}
JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, "UTF-8"));
import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
- return true;
+ return type.equals( StructuredData.class );
}
@Override
throws IOException, WebApplicationException {
CompositeNode data = t.getData();
if (data == null) {
- throw new ResponseException(Response.Status.NOT_FOUND, "No data exists.");
+ throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
}
-
+
XmlMapper xmlMapper = new XmlMapper();
Document domTree = xmlMapper.write(data, (DataNodeContainer) t.getSchema());
try {
transformer.transform(new DOMSource(domTree), new StreamResult(entityStream));
} catch (TransformerException e) {
logger.error("Error during translation of Document to OutputStream", e);
- throw new ResponseException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage());
+ throw new RestconfDocumentedException( e.getMessage(), ErrorType.TRANSPORT,
+ ErrorTag.OPERATION_FAILED );
}
}
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import javax.xml.stream.XMLStreamException;
import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
@Provider
@Consumes({ Draft02.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.OPERATION + RestconfService.XML,
public enum XmlToCompositeNodeProvider implements MessageBodyReader<CompositeNode> {
INSTANCE;
+ private final static Logger LOG = LoggerFactory.getLogger( XmlToCompositeNodeProvider.class );
+
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return true;
try {
return xmlReader.read(entityStream);
} catch (XMLStreamException | UnsupportedFormatException e) {
- throw new ResponseException(Response.Status.BAD_REQUEST, e.getMessage());
+ LOG.debug( "Error parsing json input", e );
+ throw new RestconfDocumentedException(
+ "Error parsing input: " + e.getMessage(),
+ ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE );
}
}
import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
-import org.opendaylight.controller.sal.rest.impl.RestconfProvider;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.common.QName;
private void checkPreconditions() {
if( context == null || dataService == null ) {
- ResponseException _responseException = new ResponseException( Status.SERVICE_UNAVAILABLE,
- RestconfProvider.NOT_INITALIZED_MSG );
- throw _responseException;
+ throw new RestconfDocumentedException( Status.SERVICE_UNAVAILABLE );
}
}
return mountPoint.readOperationalData( path );
}
- public RpcResult<CompositeNode> invokeRpc( final QName type, final CompositeNode payload ) {
+ public Future<RpcResult<CompositeNode>> invokeRpc( final QName type, final CompositeNode payload ) {
this.checkPreconditions();
- final Future<RpcResult<CompositeNode>> future = context.rpc( type, payload );
-
- try {
- return future.get();
- }
- catch( Exception e ) {
- throw new ResponseException( e, "Error invoking RPC " + type );
- }
+ return context.rpc( type, payload );
}
public Future<RpcResult<TransactionStatus>> commitConfigurationDataPut( final InstanceIdentifier path,
if (availableNode != null) {
String errMsg = "Post Configuration via Restconf was not executed because data already exists";
BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
- // FIXME: return correct ietf-restconf:errors -> follow specification
- // (http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48)
- throw new ResponseException(Status.CONFLICT, errMsg);
+
+ throw new RestconfDocumentedException(
+ "Data already exists for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS );
}
BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
transaction.putConfigurationData( path, payload );
if (availableNode != null) {
String errMsg = "Post Configuration via Restconf was not executed because data already exists";
BrokerFacade.LOG.warn((new StringBuilder(errMsg)).append(" : ").append(path).toString());
- // FIXME: return correct ietf-restconf:errors -> follow specification
- // (http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48)
- throw new ResponseException(Status.CONFLICT, errMsg);
+
+ throw new RestconfDocumentedException(
+ "Data already exists for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS );
}
BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
transaction.putConfigurationData( path, payload );
private QName name;
private List<NodeWrapper<?>> values = new ArrayList<>();
- public CompositeNodeWrapper(String localName) {
+ public CompositeNodeWrapper(final String localName) {
this.localName = Preconditions.checkNotNull(localName);
}
- public CompositeNodeWrapper(URI namespace, String localName) {
+ public CompositeNodeWrapper(final URI namespace, final String localName) {
this(localName);
this.namespace = namespace;
}
-
+
@Override
- public void setQname(QName name) {
+ public void setQname(final QName name) {
Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
this.name = name;
}
-
+
@Override
public QName getQname() {
return name;
}
@Override
- public void setNamespace(URI namespace) {
+ public void setNamespace(final URI namespace) {
Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
this.namespace = namespace;
}
- public void addValue(NodeWrapper<?> value) {
+ public void addValue(final NodeWrapper<?> value) {
Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
values.add(value);
}
- public void removeValue(NodeWrapper<CompositeNode> value) {
+ public void removeValue(final NodeWrapper<CompositeNode> value) {
Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
values.remove(value);
}
-
+
public List<NodeWrapper<?>> getValues() {
Preconditions.checkState(compositeNode == null, "Data can be inconsistent.");
return Collections.unmodifiableList(values);
}
-
+
@Override
public boolean isChangeAllowed() {
return compositeNode == null ? true : false;
Preconditions.checkNotNull(namespace);
name = new QName(namespace, localName);
}
-
+
List<Node<?>> nodeValues = new ArrayList<>();
for (NodeWrapper<?> nodeWrapper : values) {
nodeValues.add(nodeWrapper.unwrap());
}
compositeNode = NodeFactory.createMutableCompositeNode(name, null, nodeValues, null, null);
-
+
values = null;
namespace = null;
localName = null;
return unwrap().getNodeType();
}
+ @Deprecated
@Override
public CompositeNode getParent() {
return unwrap().getParent();
return unwrap().getModificationAction();
}
+ /**
+ * @deprecated Use {@link #getValue()} instead.
+ */
+ @Deprecated
@Override
public List<Node<?>> getChildren() {
- return unwrap().getChildren();
+ return unwrap().getValue();
}
@Override
- public List<CompositeNode> getCompositesByName(QName children) {
+ public List<CompositeNode> getCompositesByName(final QName children) {
return unwrap().getCompositesByName(children);
}
@Override
- public List<CompositeNode> getCompositesByName(String children) {
+ public List<CompositeNode> getCompositesByName(final String children) {
return unwrap().getCompositesByName(children);
}
@Override
- public List<SimpleNode<?>> getSimpleNodesByName(QName children) {
+ public List<SimpleNode<?>> getSimpleNodesByName(final QName children) {
return unwrap().getSimpleNodesByName(children);
}
@Override
- public List<SimpleNode<?>> getSimpleNodesByName(String children) {
+ public List<SimpleNode<?>> getSimpleNodesByName(final String children) {
return unwrap().getSimpleNodesByName(children);
}
@Override
- public CompositeNode getFirstCompositeByName(QName container) {
+ public CompositeNode getFirstCompositeByName(final QName container) {
return unwrap().getFirstCompositeByName(container);
}
@Override
- public SimpleNode<?> getFirstSimpleByName(QName leaf) {
+ public SimpleNode<?> getFirstSimpleByName(final QName leaf) {
return unwrap().getFirstSimpleByName(leaf);
}
}
@Override
- public List<Node<?>> setValue(List<Node<?>> value) {
+ public List<Node<?>> setValue(final List<Node<?>> value) {
return unwrap().setValue(value);
}
}
@Override
- public boolean containsKey(Object key) {
+ public boolean containsKey(final Object key) {
return unwrap().containsKey(key);
}
@Override
- public boolean containsValue(Object value) {
+ public boolean containsValue(final Object value) {
return unwrap().containsValue(value);
}
@Override
- public List<Node<?>> get(Object key) {
+ public List<Node<?>> get(final Object key) {
return unwrap().get(key);
}
@Override
- public List<Node<?>> put(QName key, List<Node<?>> value) {
+ public List<Node<?>> put(final QName key, final List<Node<?>> value) {
return unwrap().put(key, value);
}
@Override
- public List<Node<?>> remove(Object key) {
+ public List<Node<?>> remove(final Object key) {
return unwrap().remove(key);
}
@Override
- public void putAll(Map<? extends QName, ? extends List<Node<?>>> m) {
+ public void putAll(final Map<? extends QName, ? extends List<Node<?>>> m) {
unwrap().putAll(m);
}
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.impl.RestUtil;
-import org.opendaylight.controller.sal.rest.impl.RestconfProvider;
import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
import org.opendaylight.controller.sal.restconf.impl.RestCodec;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.yangtools.concepts.Codec;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
private void checkPreconditions() {
if( globalSchema == null ) {
- throw new ResponseException( Status.SERVICE_UNAVAILABLE, RestconfProvider.NOT_INITALIZED_MSG );
+ throw new RestconfDocumentedException( Status.SERVICE_UNAVAILABLE );
}
}
String first = pathArgs.iterator().next();
final String startModule = ControllerContext.toModuleName( first );
if( startModule == null ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "First node in URI has to be in format \"moduleName:nodeName\"" );
+ throw new RestconfDocumentedException(
+ "First node in URI has to be in format \"moduleName:nodeName\"",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
InstanceIdentifierBuilder builder = InstanceIdentifier.builder();
latestModule, null, toMountPointIdentifier );
if( iiWithSchemaNode == null ) {
- throw new ResponseException( Status.BAD_REQUEST, "URI has bad format" );
+ throw new RestconfDocumentedException(
+ "URI has bad format", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
return iiWithSchemaNode;
return builder.toString();
}
+ public Module getRestconfModule() {
+ return findModuleByNameAndRevision( Draft02.RestConfModule.IETF_RESTCONF_QNAME );
+ }
+
+ public DataSchemaNode getRestconfModuleErrorsSchemaNode() {
+ Module restconfModule = getRestconfModule();
+ if( restconfModule == null ) {
+ return null;
+ }
+
+ Set<GroupingDefinition> groupings = restconfModule.getGroupings();
+
+ final Predicate<GroupingDefinition> filter = new Predicate<GroupingDefinition>() {
+ @Override
+ public boolean apply(final GroupingDefinition g) {
+ return Objects.equal(g.getQName().getLocalName(),
+ Draft02.RestConfModule.ERRORS_GROUPING_SCHEMA_NODE);
+ }
+ };
+
+ Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
+
+ final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
+
+ List<DataSchemaNode> instanceDataChildrenByName =
+ this.findInstanceDataChildrenByName(restconfGrouping,
+ Draft02.RestConfModule.ERRORS_CONTAINER_SCHEMA_NODE);
+ return Iterables.getFirst(instanceDataChildrenByName, null);
+ }
+
+ public DataSchemaNode getRestconfModuleRestConfSchemaNode( Module inRestconfModule,
+ String schemaNodeName ) {
+ Module restconfModule = inRestconfModule;
+ if( restconfModule == null ) {
+ restconfModule = getRestconfModule();
+ }
+
+ if( restconfModule == null ) {
+ return null;
+ }
+
+ Set<GroupingDefinition> groupings = restconfModule.getGroupings();
+
+ final Predicate<GroupingDefinition> filter = new Predicate<GroupingDefinition>() {
+ @Override
+ public boolean apply(final GroupingDefinition g) {
+ return Objects.equal(g.getQName().getLocalName(),
+ Draft02.RestConfModule.RESTCONF_GROUPING_SCHEMA_NODE);
+ }
+ };
+
+ Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
+
+ final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
+
+ List<DataSchemaNode> instanceDataChildrenByName =
+ this.findInstanceDataChildrenByName(restconfGrouping,
+ Draft02.RestConfModule.RESTCONF_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
+
+ if (Objects.equal(schemaNodeName, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+ else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+ else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode modules = Iterables.getFirst(instances, null);
+ instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+ Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+ else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+ else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode modules = Iterables.getFirst(instances, null);
+ instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+ Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+ else if(Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+
+ return null;
+ }
+
private static DataSchemaNode childByQName( final ChoiceNode container, final QName name ) {
for( final ChoiceCaseNode caze : container.getCases() ) {
final DataSchemaNode ret = ControllerContext.childByQName( caze, name );
if( Objects.equal( moduleName, ControllerContext.MOUNT_MODULE ) &&
Objects.equal( nodeName, ControllerContext.MOUNT_NODE ) ) {
if( mountPoint != null ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "Restconf supports just one mount point in URI." );
+ throw new RestconfDocumentedException(
+ "Restconf supports just one mount point in URI.",
+ ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED );
}
if( mountService == null ) {
- throw new ResponseException( Status.SERVICE_UNAVAILABLE,
- "MountService was not found. Finding behind mount points does not work." );
+ throw new RestconfDocumentedException(
+ "MountService was not found. Finding behind mount points does not work.",
+ ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED );
}
final InstanceIdentifier partialPath = builder.toInstance();
final MountInstance mount = mountService.getMountPoint( partialPath );
if( mount == null ) {
LOG.debug( "Instance identifier to missing mount point: {}", partialPath );
- throw new ResponseException( Status.BAD_REQUEST,
- "Mount point does not exist." );
+ throw new RestconfDocumentedException(
+ "Mount point does not exist.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
}
final SchemaContext mountPointSchema = mount.getSchemaContext();
if( mountPointSchema == null ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "Mount point does not contain any schema with modules." );
+ throw new RestconfDocumentedException(
+ "Mount point does not contain any schema with modules.",
+ ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT );
}
if( returnJustMountPoint ) {
final String moduleNameBehindMountPoint = toModuleName( strings.get( 1 ) );
if( moduleNameBehindMountPoint == null ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "First node after mount point in URI has to be in format \"moduleName:nodeName\"" );
+ throw new RestconfDocumentedException(
+ "First node after mount point in URI has to be in format \"moduleName:nodeName\"",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
final Module moduleBehindMountPoint = this.getLatestModule( mountPointSchema,
moduleNameBehindMountPoint );
if( moduleBehindMountPoint == null ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "URI has bad format. \"" + moduleName +
- "\" module does not exist in mount point." );
+ throw new RestconfDocumentedException(
+ "\"" +moduleName + "\" module does not exist in mount point.",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
}
List<String> subList = strings.subList( 1, strings.size() );
if( mountPoint == null ) {
module = this.getLatestModule( globalSchema, moduleName );
if( module == null ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "URI has bad format. \"" + moduleName + "\" module does not exist." );
+ throw new RestconfDocumentedException(
+ "\"" + moduleName + "\" module does not exist.",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
}
}
else {
module = schemaContext == null ? null :
this.getLatestModule( schemaContext, moduleName );
if( module == null ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "URI has bad format. \"" + moduleName +
- "\" module does not exist in mount point." );
+ throw new RestconfDocumentedException(
+ "\"" + moduleName + "\" module does not exist in mount point.",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
}
}
targetNode = this.findInstanceDataChildByNameAndNamespace(
parentNode, nodeName, module.getNamespace() );;
if( targetNode == null ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "URI has bad format. Possible reasons:\n" +
- "1. \"" + head + "\" was not found in parent data node.\n" +
- "2. \"" + head + "\" is behind mount point. Then it should be in format \"/" +
- MOUNT + "/" + head + "\"." );
+ throw new RestconfDocumentedException(
+ "URI has bad format. Possible reasons:\n" +
+ " 1. \"" + head + "\" was not found in parent data node.\n" +
+ " 2. \"" + head + "\" is behind mount point. Then it should be in format \"/" +
+ MOUNT + "/" + head + "\".", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
} else {
final List<DataSchemaNode> potentialSchemaNodes =
.append( "\n" );
}
- throw new ResponseException( Status.BAD_REQUEST,
+ throw new RestconfDocumentedException(
"URI has bad format. Node \"" + nodeName +
"\" is added as augment from more than one module. " +
"Therefore the node must have module name and it has to be in format \"moduleName:nodeName\"." +
"\nThe node is added as augment from modules with namespaces:\n" +
- strBuilder.toString() );
+ strBuilder.toString(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
if( potentialSchemaNodes.isEmpty() ) {
- throw new ResponseException( Status.BAD_REQUEST, "URI has bad format. \"" + nodeName +
- "\" was not found in parent data node.\n" );
+ throw new RestconfDocumentedException(
+ "\"" + nodeName + "\" in URI was not found in parent data node",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
}
targetNode = potentialSchemaNodes.iterator().next();
}
if( !this.isListOrContainer( targetNode ) ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "URI has bad format. Node \"" + head +
- "\" must be Container or List yang type." );
+ throw new RestconfDocumentedException(
+ "URI has bad format. Node \"" + head + "\" must be Container or List yang type.",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
int consumed = 1;
final ListSchemaNode listNode = ((ListSchemaNode) targetNode);
final int keysSize = listNode.getKeyDefinition().size();
if( (strings.size() - consumed) < keysSize ) {
- throw new ResponseException( Status.BAD_REQUEST, "Missing key for list \"" +
- listNode.getQName().getLocalName() + "\"." );
+ throw new RestconfDocumentedException(
+ "Missing key for list \"" + listNode.getQName().getLocalName() + "\".",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
final List<String> uriKeyValues = strings.subList( consumed, consumed + keysSize );
{
final String uriKeyValue = uriKeyValues.get( i );
if( uriKeyValue.equals( NULL_VALUE ) ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "URI has bad format. List \"" + listNode.getQName().getLocalName() +
- "\" cannot contain \"null\" value as a key." );
+ throw new RestconfDocumentedException(
+ "URI has bad format. List \"" + listNode.getQName().getLocalName() +
+ "\" cannot contain \"null\" value as a key.",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
this.addKeyValue( keyValues, listNode.getDataChildByName( key ),
}
if( decoded == null ) {
- throw new ResponseException( Status.BAD_REQUEST, uriValue + " from URI can\'t be resolved. " +
- additionalInfo );
+ throw new RestconfDocumentedException(
+ uriValue + " from URI can't be resolved. " + additionalInfo,
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
map.put( node.getQName(), decoded );
return decodedPathArgs;
}
catch( UnsupportedEncodingException e ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "Invalid URL path '" + strings + "': " + e.getMessage() );
+ throw new RestconfDocumentedException(
+ "Invalid URL path '" + strings + "': " + e.getMessage(),
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
}
return URLDecoder.decode( pathArg, URI_ENCODING_CHAR_SET );
}
catch( UnsupportedEncodingException e ) {
- throw new ResponseException( Status.BAD_REQUEST,
- "Invalid URL path arg '" + pathArg + "': " + e.getMessage() );
+ throw new RestconfDocumentedException(
+ "Invalid URL path arg '" + pathArg + "': " + e.getMessage(),
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
}
+++ /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.sal.restconf.impl;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-public class ResponseException extends WebApplicationException {
-
- private static final long serialVersionUID = -5320114450593021655L;
-
- public ResponseException(Status status, String msg) {
- super(Response.status(status).type(MediaType.TEXT_PLAIN_TYPE).entity(msg).build());
- }
-
- public ResponseException(Throwable cause, String msg) {
- super(cause, Response.status(Status.INTERNAL_SERVER_ERROR).
- type(MediaType.TEXT_PLAIN_TYPE).entity(msg).build());
- }
-}
--- /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.impl;
+
+import java.util.List;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response.Status;
+
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Unchecked exception to communicate error information, as defined in the ietf restcong draft,
+ * to be sent to the client.
+ *
+ * @author Devin Avery
+ * @author Thomas Pantelis
+ * @see {@link https://tools.ietf.org/html/draft-bierman-netconf-restconf-02}
+ */
+public class RestconfDocumentedException extends WebApplicationException {
+
+ private static final long serialVersionUID = 1L;
+
+ private final List<RestconfError> errors;
+ private final Status status;
+
+ /**
+ * Constructs an instance with an error message. The error type defaults to APPLICATION and
+ * the error tag defaults to OPERATION_FAILED.
+ *
+ * @param message A string which provides a plain text string describing the error.
+ */
+ public RestconfDocumentedException( String message ) {
+ this( message, RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.OPERATION_FAILED );
+ }
+
+ /**
+ * Constructs an instance with an error message, error type, and error tag.
+ *
+ * @param message A string which provides a plain text string describing the error.
+ * @param errorType The enumerated type indicating the layer where the error occurred.
+ * @param errorTag The enumerated tag representing a more specific error cause.
+ */
+ public RestconfDocumentedException( String message, ErrorType errorType, ErrorTag errorTag ) {
+ this( null, new RestconfError( errorType, errorTag, message ) );
+ }
+
+ /**
+ * Constructs an instance with an error message and exception cause. The stack trace of the
+ * exception is included in the error info.
+ *
+ * @param message A string which provides a plain text string describing the error.
+ * @param cause The underlying exception cause.
+ */
+ public RestconfDocumentedException( String message, Throwable cause ) {
+ this( cause, new RestconfError( RestconfError.ErrorType.APPLICATION,
+ RestconfError.ErrorTag.OPERATION_FAILED, message,
+ null, RestconfError.toErrorInfo( cause ) ) );
+ }
+
+ /**
+ * Constructs an instance with the given error.
+ */
+ public RestconfDocumentedException( RestconfError error ) {
+ this( null, error );
+ }
+
+ /**
+ * Constructs an instance with the given errors.
+ */
+ public RestconfDocumentedException( List<RestconfError> errors ) {
+ this.errors = ImmutableList.copyOf( errors );
+ Preconditions.checkArgument( !this.errors.isEmpty(), "RestconfError list can't be empty" );
+ status = null;
+ }
+
+ /**
+ * Constructs an instance with an HTTP status and no error information.
+ *
+ * @param status the HTTP status.
+ */
+ public RestconfDocumentedException( Status status ) {
+ Preconditions.checkNotNull( status, "Status can't be null" );
+ errors = ImmutableList.of();
+ this.status = status;
+ }
+
+ private RestconfDocumentedException( Throwable cause, RestconfError error ) {
+ super( cause );
+ Preconditions.checkNotNull( error, "RestconfError can't be null" );
+ errors = ImmutableList.of( error );
+ status = null;
+ }
+
+ public List<RestconfError> getErrors() {
+ return errors;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+
+ @Override
+ public String getMessage() {
+ return "errors: " + errors + (status != null ? ", status: " + status : "");
+ }
+}
--- /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.impl;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.opendaylight.yangtools.yang.common.RpcError;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Encapsulates a restconf error as defined in the ietf restconf draft.
+ *
+ * <br><br><b>Note:</b> Enumerations defined within are provided by the ietf restconf draft.
+ *
+ * @author Devin Avery
+ * @see {@link https://tools.ietf.org/html/draft-bierman-netconf-restconf-02}
+ */
+public class RestconfError {
+
+ public static enum ErrorType {
+ /** Errors relating to the transport layer */
+ TRANSPORT,
+ /** Errors relating to the RPC or notification layer */
+ RPC,
+ /** Errors relating to the protocol operation layer. */
+ PROTOCOL,
+ /** Errors relating to the server application layer. */
+ APPLICATION;
+
+ public String getErrorTypeTag() {
+ return name().toLowerCase();
+ }
+
+ public static ErrorType valueOfCaseInsensitive( String value )
+ {
+ try {
+ return ErrorType.valueOf( ErrorType.class, value.toUpperCase() );
+ }
+ catch( IllegalArgumentException e ) {
+ return APPLICATION;
+ }
+ }
+ }
+
+ public static enum ErrorTag {
+ IN_USE( "in-use", Status.fromStatusCode(409)),
+ INVALID_VALUE( "invalid-value", Status.fromStatusCode(400)),
+ TOO_BIG( "too-big", Status.fromStatusCode(413)),
+ MISSING_ATTRIBUTE( "missing-attribute", Status.fromStatusCode(400)),
+ BAD_ATTRIBUTE( "bad-attribute", Status.fromStatusCode(400)),
+ UNKNOWN_ATTRIBUTE( "unknown-attribute", Status.fromStatusCode(400)),
+ BAD_ELEMENT( "bad-element", Status.fromStatusCode(400)),
+ UNKNOWN_ELEMENT( "unknown-element", Status.fromStatusCode(400)),
+ UNKNOWN_NAMESPACE( "unknown-namespace", Status.fromStatusCode(400)),
+ ACCESS_DENIED( "access-denied", Status.fromStatusCode(403)),
+ LOCK_DENIED( "lock-denied", Status.fromStatusCode(409)),
+ RESOURCE_DENIED( "resource-denied", Status.fromStatusCode(409)),
+ ROLLBACK_FAILED( "rollback-failed", Status.fromStatusCode(500)),
+ DATA_EXISTS( "data-exists", Status.fromStatusCode(409)),
+ DATA_MISSING( "data-missing", Status.fromStatusCode(409)),
+ OPERATION_NOT_SUPPORTED( "operation-not-supported", Status.fromStatusCode(501)),
+ OPERATION_FAILED( "operation-failed", Status.fromStatusCode(500)),
+ PARTIAL_OPERATION( "partial-operation", Status.fromStatusCode(500)),
+ MALFORMED_MESSAGE( "malformed-message", Status.fromStatusCode(400));
+
+ private final String tagValue;
+ private final Status statusCode;
+
+ ErrorTag(final String tagValue, final Status statusCode) {
+ this.tagValue = tagValue;
+ this.statusCode = statusCode;
+ }
+
+ public String getTagValue() {
+ return this.tagValue.toLowerCase();
+ }
+
+ public static ErrorTag valueOfCaseInsensitive( String value )
+ {
+ try {
+ return ErrorTag.valueOf( ErrorTag.class, value.toUpperCase().replaceAll( "-","_" ) );
+ }
+ catch( IllegalArgumentException e ) {
+ return OPERATION_FAILED;
+ }
+ }
+
+ public Status getStatusCode() {
+ return statusCode;
+ }
+ }
+
+ private final ErrorType errorType;
+ private final ErrorTag errorTag;
+ private final String errorInfo;
+ private final String errorAppTag;
+ private final String errorMessage;
+ //TODO: Add in the error-path concept as defined in the ietf draft.
+
+ static String toErrorInfo( Throwable cause ) {
+ StringWriter writer = new StringWriter();
+ cause.printStackTrace( new PrintWriter( writer ) );
+ return writer.toString();
+ }
+
+ /**
+ * Constructs a RestConfError
+ *
+ * @param errorType The enumerated type indicating the layer where the error occurred.
+ * @param errorTag The enumerated tag representing a more specific error cause.
+ * @param errorMessage A string which provides a plain text string describing the error.
+ */
+ public RestconfError(ErrorType errorType, ErrorTag errorTag, String errorMessage) {
+ this( errorType, errorTag, errorMessage, null );
+ }
+
+ /**
+ * Constructs a RestConfError object.
+ *
+ * @param errorType The enumerated type indicating the layer where the error occurred.
+ * @param errorTag The enumerated tag representing a more specific error cause.
+ * @param errorMessage A string which provides a plain text string describing the error.
+ * @param errorAppTag A string which represents an application-specific error tag that further
+ * specifies the error cause.
+ */
+ public RestconfError(ErrorType errorType, ErrorTag errorTag, String errorMessage,
+ String errorAppTag) {
+ this( errorType, errorTag, errorMessage, errorAppTag, null );
+ }
+
+ /**
+ * Constructs a RestConfError object.
+ *
+ * @param errorType The enumerated type indicating the layer where the error occurred.
+ * @param errorTag The enumerated tag representing a more specific error cause.
+ * @param errorMessage A string which provides a plain text string describing the error.
+ * @param errorAppTag A string which represents an application-specific error tag that further
+ * specifies the error cause.
+ * @param errorInfo A string, <b>formatted as XML</b>, which contains additional error information.
+ */
+ public RestconfError(ErrorType errorType, ErrorTag errorTag, String errorMessage,
+ String errorAppTag, String errorInfo) {
+ Preconditions.checkNotNull( errorType, "Error type is required for RestConfError" );
+ Preconditions.checkNotNull( errorTag, "Error tag is required for RestConfError");
+ this.errorType = errorType;
+ this.errorTag = errorTag;
+ this.errorMessage = errorMessage;
+ this.errorAppTag = errorAppTag;
+ this.errorInfo = errorInfo;
+ }
+
+ /**
+ * Constructs a RestConfError object from an RpcError.
+ */
+ public RestconfError( RpcError rpcError ) {
+
+ this.errorType = rpcError.getErrorType() == null ? ErrorType.APPLICATION :
+ ErrorType.valueOfCaseInsensitive( rpcError.getErrorType().name() );
+
+ this.errorTag = rpcError.getTag() == null ? ErrorTag.OPERATION_FAILED :
+ ErrorTag.valueOfCaseInsensitive( rpcError.getTag().toString() );
+
+ this.errorMessage = rpcError.getMessage();
+ this.errorAppTag = rpcError.getApplicationTag();
+
+ String errorInfo = null;
+ if( rpcError.getInfo() == null ) {
+ if( rpcError.getCause() != null ) {
+ errorInfo = toErrorInfo( rpcError.getCause() );
+ }
+ else if( rpcError.getSeverity() != null ) {
+ errorInfo = "<severity>" + rpcError.getSeverity().toString().toLowerCase() +
+ "</severity>";
+ }
+ }
+ else {
+ errorInfo = rpcError.getInfo();
+ }
+
+ this.errorInfo = errorInfo;
+ }
+
+ public ErrorType getErrorType() {
+ return errorType;
+ }
+
+ public ErrorTag getErrorTag() {
+ return errorTag;
+ }
+
+ public String getErrorInfo() {
+ return errorInfo;
+ }
+
+ public String getErrorAppTag() {
+ return errorAppTag;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ @Override
+ public String toString() {
+ return "error-type: " + errorType.getErrorTypeTag()
+ + ", error-tag: " + errorTag.getTagValue() + ", "
+ + (errorAppTag != null ? "error-app-tag: " + errorAppTag + ", " : "")
+ + (errorMessage != null ? "error-message: " + errorMessage : "")
+ + (errorInfo != null ? "error-info: " + errorInfo + ", " : "") + "]";
+ }
+
+}
\ No newline at end of file
/**
* 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,
*/
package org.opendaylight.controller.sal.restconf.impl;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
import java.net.URI;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+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.Draft02;
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.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.RestCodec;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.controller.sal.streams.listeners.Notificator;
import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
import org.opendaylight.yangtools.concepts.Codec;
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.InstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
-import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
-@SuppressWarnings("all")
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");
- private final static String RESTCONF_MODULE_DRAFT02_REVISION = "2013-10-19";
-
- private final static String RESTCONF_MODULE_DRAFT02_NAME = "ietf-restconf";
-
- private final static String RESTCONF_MODULE_DRAFT02_NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-restconf";
-
- private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE = "restconf";
-
- private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE = "restconf";
-
- private final static String RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE = "modules";
-
- private final static String RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE = "module";
-
- private final static String RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE = "streams";
-
- private final static String RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE = "stream";
-
- private final static String RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE = "operations";
-
private final static String SAL_REMOTE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote";
private final static String SAL_REMOTE_RPC_SUBSRCIBE = "create-data-change-event-subscription";
final Module restconfModule = this.getRestconfModule();
final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
- final DataSchemaNode moduleSchemaNode =
- this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+ final DataSchemaNode moduleSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+ restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
Set<Module> allModules = this.controllerContext.getAllModules();
for (final Module module : allModules) {
modulesAsData.add(moduleCompositeNode);
}
- final DataSchemaNode modulesSchemaNode =
- this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode modulesSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+ restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
QName qName = modulesSchemaNode.getQName();
final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
return new StructuredData(modulesNode, modulesSchemaNode, null);
final List<Node<?>> streamsAsData = new ArrayList<Node<?>>();
Module restconfModule = this.getRestconfModule();
- final DataSchemaNode streamSchemaNode =
- this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
+ final DataSchemaNode streamSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+ restconfModule, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
for (final String streamName : availableStreams) {
streamsAsData.add(this.toStreamCompositeNode(streamName, streamSchemaNode));
}
- final DataSchemaNode streamsSchemaNode =
- this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode streamsSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+ restconfModule, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
QName qName = streamsSchemaNode.getQName();
final CompositeNode streamsNode = NodeFactory.createImmutableCompositeNode(qName, null, streamsAsData);
return new StructuredData(streamsNode, streamsSchemaNode, null);
modules = this.controllerContext.getAllModules(mountPoint);
}
else {
- throw new ResponseException(Status.BAD_REQUEST,
- "URI has bad format. If modules behind mount point should be showed, URI has to end with " +
- ControllerContext.MOUNT);
+ throw new RestconfDocumentedException(
+ "URI has bad format. If modules behind mount point should be showed, URI has to end with " +
+ ControllerContext.MOUNT, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
Module restconfModule = this.getRestconfModule();
- final DataSchemaNode moduleSchemaNode =
- this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+ final DataSchemaNode moduleSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+ restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
for (final Module module : modules) {
modulesAsData.add(this.toModuleCompositeNode(module, moduleSchemaNode));
}
- final DataSchemaNode modulesSchemaNode =
- this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode modulesSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+ restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
QName qName = modulesSchemaNode.getQName();
final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
return new StructuredData(modulesNode, modulesSchemaNode, mountPoint);
}
if (module == null) {
- throw new ResponseException(Status.BAD_REQUEST,
+ throw new RestconfDocumentedException(
"Module with name '" + moduleNameAndRevision.getLocalName() + "' and revision '" +
- moduleNameAndRevision.getRevision() + "' was not found.");
+ moduleNameAndRevision.getRevision() + "' was not found.",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
}
Module restconfModule = this.getRestconfModule();
- final DataSchemaNode moduleSchemaNode =
- this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+ final DataSchemaNode moduleSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+ restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
final CompositeNode moduleNode = this.toModuleCompositeNode(module, moduleSchemaNode);
return new StructuredData(moduleNode, moduleSchemaNode, mountPoint);
}
modules = this.controllerContext.getAllModules(mountPoint);
}
else {
- throw new ResponseException(Status.BAD_REQUEST,
- "URI has bad format. If operations behind mount point should be showed, URI has to end with " +
- ControllerContext.MOUNT);
+ throw new RestconfDocumentedException(
+ "URI has bad format. If operations behind mount point should be showed, URI has to end with " +
+ ControllerContext.MOUNT, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
return this.operationsFromModulesToStructuredData(modules, mountPoint);
final MountInstance mountPoint) {
final List<Node<?>> operationsAsData = new ArrayList<Node<?>>();
Module restconfModule = this.getRestconfModule();
- final DataSchemaNode operationsSchemaNode =
- this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode operationsSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
+ restconfModule, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
QName qName = operationsSchemaNode.getQName();
SchemaPath path = operationsSchemaNode.getPath();
ContainerSchemaNodeBuilder containerSchemaNodeBuilder =
- new ContainerSchemaNodeBuilder(RESTCONF_MODULE_DRAFT02_NAME, 0, qName, path);
+ new ContainerSchemaNodeBuilder(Draft02.RestConfModule.NAME, 0, qName, path);
final ContainerSchemaNodeBuilder fakeOperationsSchemaNode = containerSchemaNodeBuilder;
for (final Module module : modules) {
Set<RpcDefinition> rpcs = module.getRpcs();
}
private Module getRestconfModule() {
- QName qName = QName.create(RESTCONF_MODULE_DRAFT02_NAMESPACE, RESTCONF_MODULE_DRAFT02_REVISION,
- RESTCONF_MODULE_DRAFT02_NAME);
- final Module restconfModule = this.controllerContext.findModuleByNameAndRevision(qName);
+ Module restconfModule = controllerContext.getRestconfModule();
if (restconfModule == null) {
- throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Restconf module was not found.");
+ throw new RestconfDocumentedException(
+ "ietf-restconf module was not found.", ErrorType.APPLICATION,
+ ErrorTag.OPERATION_NOT_SUPPORTED );
}
return restconfModule;
Iterable<String> split = splitter.split(moduleNameAndRevision);
final List<String> pathArgs = Lists.<String>newArrayList(split);
if (pathArgs.size() < 2) {
- throw new ResponseException(Status.BAD_REQUEST,
- "URI has bad format. End of URI should be in format \'moduleName/yyyy-MM-dd\'");
+ throw new RestconfDocumentedException(
+ "URI has bad format. End of URI should be in format \'moduleName/yyyy-MM-dd\'",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
try {
return QName.create(null, moduleRevision, moduleName);
}
catch (ParseException e) {
- throw new ResponseException(Status.BAD_REQUEST, "URI has bad format. It should be \'moduleName/yyyy-MM-dd\'");
+ throw new RestconfDocumentedException(
+ "URI has bad format. It should be \'moduleName/yyyy-MM-dd\'",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
}
return NodeFactory.createImmutableCompositeNode(moduleSchemaNode.getQName(), null, moduleNodeValues);
}
- private DataSchemaNode getSchemaNode(final Module restconfModule, final String schemaNodeName) {
- Set<GroupingDefinition> groupings = restconfModule.getGroupings();
-
- final Predicate<GroupingDefinition> filter = new Predicate<GroupingDefinition>() {
- @Override
- public boolean apply(final GroupingDefinition g) {
- return Objects.equal(g.getQName().getLocalName(),
- RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE);
- }
- };
-
- Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
-
- final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
-
- List<DataSchemaNode> instanceDataChildrenByName =
- this.controllerContext.findInstanceDataChildrenByName(restconfGrouping,
- RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE);
- final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
-
- if (Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances =
- this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
- RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
- return Iterables.getFirst(instances, null);
- }
- else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances =
- this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
- RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
- return Iterables.getFirst(instances, null);
- }
- else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE)) {
- List<DataSchemaNode> instances =
- this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
- RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
- final DataSchemaNode modules = Iterables.getFirst(instances, null);
- instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
- RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
- return Iterables.getFirst(instances, null);
- }
- else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances =
- this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
- RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
- return Iterables.getFirst(instances, null);
- }
- else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)) {
- List<DataSchemaNode> instances =
- this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
- RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
- final DataSchemaNode modules = Iterables.getFirst(instances, null);
- instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
- RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
- return Iterables.getFirst(instances, null);
- }
-
- return null;
- }
-
@Override
public Object getRoot() {
return null;
@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 RestconfDocumentedException(
+ "Instance identifier was not normalized correctly.",
+ ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED );
+ }
+
+ final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
+ String streamName = null;
+ if (!Iterables.isEmpty(pathIdentifier.getPath())) {
+ String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
+ streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
+ }
- 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);
+ if (Strings.isNullOrEmpty(streamName)) {
+ throw new RestconfDocumentedException(
+ "Path is empty or contains data node which is not Container or List build-in type.",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+ }
- final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
- rpc.getOutput().getQName(), null, output, null, null);
+ 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);
- if (!Notificator.existListenerFor(pathIdentifier)) {
- Notificator.createListener(pathIdentifier, streamName);
- }
+ final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
+ rpc.getOutput().getQName(), null, output, null, null);
- return new StructuredData(responseData, rpc.getOutput(), 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 RestconfDocumentedException(
+ "Content must be empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
-
- 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 RestconfDocumentedException(
+ slashErrorMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+ } else {
+ identifierEncoded = identifier;
+ }
+
+ final String identifierDecoded = controllerContext.urlPathArgDecode(identifierEncoded);
+ RpcDefinition rpc = controllerContext.getRpcDefinition(identifierDecoded);
- throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
+ if (rpc == null) {
+ throw new RestconfDocumentedException(
+ "RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT );
}
- 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) {
- throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
+ private StructuredData callRpc(final RpcExecutor rpcExecutor, final CompositeNode payload) {
+ if (rpcExecutor == null) {
+ throw new RestconfDocumentedException(
+ "RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT );
}
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) {
+
+ Collection<RpcError> rpcErrors = rpcResult.getErrors();
+ if( rpcErrors == null || rpcErrors.isEmpty() ) {
+ throw new RestconfDocumentedException(
+ "The operation was not successful and there were no RPC errors returned",
+ ErrorType.RPC, ErrorTag.OPERATION_FAILED );
+ }
+
+ List<RestconfError> errorList = Lists.newArrayList();
+ for( RpcError rpcError: rpcErrors ) {
+ errorList.add( new RestconfError( rpcError ) );
+ }
+
+ throw new RestconfDocumentedException( errorList );
+ }
}
@Override
}
}
catch( Exception e ) {
- throw new ResponseException( e, "Error updating data" );
+ throw new RestconfDocumentedException( "Error updating data", e );
}
if( status.getResult() == TransactionStatus.COMMITED )
public Response createConfigurationData(final String identifier, final CompositeNode payload) {
URI payloadNS = this.namespace(payload);
if (payloadNS == null) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
+ throw new RestconfDocumentedException(
+ "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE );
}
InstanceIdWithSchemaNode iiWithData = null;
// payload represents mount point data and URI represents path to the mount point
if (this.endsWithMountPoint(identifier)) {
- throw new ResponseException(Status.BAD_REQUEST,
- "URI has bad format. URI should be without \"" + ControllerContext.MOUNT +
- "\" for POST operation.");
+ throw new RestconfDocumentedException(
+ "URI has bad format. URI should be without \"" + ControllerContext.MOUNT +
+ "\" for POST operation.",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
final String completeIdentifier = this.addMountPointIdentifier(identifier);
MountInstance mountPoint = incompleteInstIdWithData.getMountPoint();
final Module module = this.findModule(mountPoint, payload);
if (module == null) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Module was not found for \"" + payloadNS + "\"");
+ throw new RestconfDocumentedException(
+ "Module was not found for \"" + payloadNS + "\"",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
}
String payloadName = this.getName(payload);
status = future == null ? null : future.get();
}
}
- catch( ResponseException e) { throw e; }
catch( Exception e ) {
- throw new ResponseException( e, "Error creating data" );
+ throw new RestconfDocumentedException( "Error creating data", e );
}
if (status == null) {
public Response createConfigurationData(final CompositeNode payload) {
URI payloadNS = this.namespace(payload);
if (payloadNS == null) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
+ throw new RestconfDocumentedException(
+ "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE );
}
final Module module = this.findModule(null, payload);
if (module == null) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)");
+ throw new RestconfDocumentedException(
+ "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)",
+ ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE );
}
String payloadName = this.getName(payload);
status = future == null ? null : future.get();
}
}
- catch( ResponseException e) { throw e; }
catch( Exception e ) {
- throw new ResponseException( e, "Error creating data" );
+ throw new RestconfDocumentedException( "Error creating data", e );
}
if (status == null) {
}
}
catch( Exception e ) {
- throw new ResponseException( e, "Error creating data" );
+ throw new RestconfDocumentedException( "Error creating data", e );
}
if( status.getResult() == TransactionStatus.COMMITED )
public Response subscribeToStream(final String identifier, final UriInfo uriInfo) {
final String streamName = Notificator.createStreamNameFromUri(identifier);
if (Strings.isNullOrEmpty(streamName)) {
- throw new ResponseException(Status.BAD_REQUEST, "Stream name is empty.");
+ throw new RestconfDocumentedException(
+ "Stream name is empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
final ListenerAdapter listener = Notificator.getListenerFor(streamName);
if (listener == null) {
- throw new ResponseException(Status.BAD_REQUEST, "Stream was not found.");
+ throw new RestconfDocumentedException(
+ "Stream was not found.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT );
}
broker.registerToListenDataChanges(listener);
}
if (dataNodeKeyValueObject == null) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Data contains list \"" + dataNode.getNodeType().getLocalName() +
- "\" which does not contain key: \"" + key.getLocalName() + "\"");
+ throw new RestconfDocumentedException(
+ "Data contains list \"" + dataNode.getNodeType().getLocalName() +
+ "\" which does not contain key: \"" + key.getLocalName() + "\"",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
keyValues.put(key, dataNodeKeyValueObject);
if (schema == null) {
QName nodeType = node == null ? null : node.getNodeType();
String localName = nodeType == null ? null : nodeType.getLocalName();
- String _plus = ("Data schema node was not found for " + localName);
- throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
- "Data schema node was not found for " + localName );
+
+ throw new RestconfDocumentedException(
+ "Data schema node was not found for " + localName,
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
if (!(schema instanceof DataNodeContainer)) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Root element has to be container or list yang datatype.");
+ throw new RestconfDocumentedException(
+ "Root element has to be container or list yang datatype.",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
if ((node instanceof CompositeNodeWrapper)) {
try {
this.normalizeNode(((CompositeNodeWrapper) node), schema, null, mountPoint);
}
- catch (NumberFormatException e) {
- throw new ResponseException(Status.BAD_REQUEST, e.getMessage());
+ catch (IllegalArgumentException e) {
+ throw new RestconfDocumentedException(
+ e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
}
final DataSchemaNode schema, final QName previousAugment,
final MountInstance mountPoint) {
if (schema == null) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Data has bad format.\n\"" + nodeBuilder.getLocalName() +
- "\" does not exist in yang schema.");
+ throw new RestconfDocumentedException(
+ "Data has bad format.\n\"" + nodeBuilder.getLocalName() +
+ "\" does not exist in yang schema.",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
QName currentAugment = null;
else {
currentAugment = this.normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint);
if (nodeBuilder.getQname() == null) {
- throw new ResponseException(Status.BAD_REQUEST,
+ throw new RestconfDocumentedException(
"Data has bad format.\nIf data is in XML format then namespace for \"" +
nodeBuilder.getLocalName() +
"\" should be \"" + schema.getQName().getNamespace() + "\".\n" +
"If data is in JSON format then module name for \"" + nodeBuilder.getLocalName() +
"\" should be corresponding to namespace \"" +
- schema.getQName().getNamespace() + "\".");
+ schema.getQName().getNamespace() + "\".",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
}
.append("\n");
}
- throw new ResponseException(Status.BAD_REQUEST,
+ throw new RestconfDocumentedException(
"Node \"" + child.getLocalName() +
"\" is added as augment from more than one module. " +
"Therefore node must have namespace (XML format) or module name (JSON format)." +
- "\nThe node is added as augment from modules with namespaces:\n" + builder);
+ "\nThe node is added as augment from modules with namespaces:\n" + builder,
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
boolean rightNodeSchemaFound = false;
}
if (!rightNodeSchemaFound) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Schema node \"" + child.getLocalName() + "\" was not found in module.");
+ throw new RestconfDocumentedException(
+ "Schema node \"" + child.getLocalName() + "\" was not found in module.",
+ ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT );
}
}
}
if (!foundKey) {
- throw new ResponseException(Status.BAD_REQUEST,
+ throw new RestconfDocumentedException(
"Missing key in URI \"" + listKey.getLocalName() +
- "\" of list \"" + schema.getQName().getLocalName() + "\"");
+ "\" of list \"" + schema.getQName().getLocalName() + "\"",
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
}
}
}
--- /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.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+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;
+ }
+
+ protected RpcResult<CompositeNode> getRpcResult(
+ Future<RpcResult<CompositeNode>> fromFuture ) {
+ try {
+ return fromFuture.get();
+ }
+ catch( InterruptedException e ) {
+ throw new RestconfDocumentedException(
+ "The operation was interrupted while executing and did not complete.",
+ ErrorType.RPC, ErrorTag.PARTIAL_OPERATION );
+ }
+ catch( ExecutionException e ) {
+ Throwable cause = e.getCause();
+ if( cause instanceof CancellationException ) {
+ throw new RestconfDocumentedException(
+ "The operation was cancelled while executing.",
+ ErrorType.RPC, ErrorTag.PARTIAL_OPERATION );
+ }
+ else if( cause != null ){
+ while( cause.getCause() != null ) {
+ cause = cause.getCause();
+ }
+
+ if( cause instanceof IllegalArgumentException ) {
+ throw new RestconfDocumentedException(
+ cause.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+ }
+
+ throw new RestconfDocumentedException(
+ "The operation encountered an unexpected error while executing.", cause );
+ }
+ else {
+ throw new RestconfDocumentedException(
+ "The operation encountered an unexpected error while executing.", e );
+ }
+ }
+ }
+}
\ 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 getRpcResult( 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 org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+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;
+
+/**
+ * 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 RestconfDocumentedException {
+ return getRpcResult( mountPoint.rpc( 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 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
verifyJsonOutput(jsonOutput);
}
- private void verifyJsonOutputForEmptyData(String jsonOutput) {
+ private void verifyJsonOutputForEmptyData(final String jsonOutput) {
assertNotNull(jsonOutput);
StringReader strReader = new StringReader(jsonOutput);
JsonReader jReader = new JsonReader(strReader);
assertNull("Error during reading Json output: " + exception, exception);
}
- private void verifyJsonOutput(String jsonOutput) {
+ private void verifyJsonOutput(final String jsonOutput) {
assertNotNull(jsonOutput);
StringReader strReader = new StringReader(jsonOutput);
JsonReader jReader = new JsonReader(strReader);
assertNull("Error during reading Json output: " + exception, exception);
}
- private Cont jsonReadCont1(JsonReader jReader) throws IOException {
+ private Cont jsonReadCont1(final JsonReader jReader) throws IOException {
jReader.beginObject();
assertNotNull("cont1 is missing.", jReader.hasNext());
}
- private Cont jsonReadCont1Elements(JsonReader jReader, Cont redData) throws IOException {
+ private Cont jsonReadCont1Elements(final JsonReader jReader, final Cont redData) throws IOException {
jReader.beginObject();
while (jReader.hasNext()) {
String keyName = jReader.nextName();
}
- private Lst jsonReadLst11(JsonReader jReader, Lst lst) throws IOException {
+ private Lst jsonReadLst11(final JsonReader jReader, final Lst lst) throws IOException {
jReader.beginArray();
while (jReader.hasNext()) {
return lst;
}
- private LstItem jsonReadLst11Elements(JsonReader jReader) throws IOException {
+ private LstItem jsonReadLst11Elements(final JsonReader jReader) throws IOException {
LstItem lstItem = new LstItem();
jReader.beginObject();
while (jReader.hasNext()) {
return lstItem;
}
- private Lst jsonReadLst112(JsonReader jReader, Lst lst) throws IOException {
+ private Lst jsonReadLst112(final JsonReader jReader, final Lst lst) throws IOException {
jReader.beginArray();
while (jReader.hasNext()) {
LstItem lstItem = jsonReadLst112Elements(jReader);
return lst;
}
- private LstItem jsonReadLst112Elements(JsonReader jReader) throws IOException {
+ private LstItem jsonReadLst112Elements(final JsonReader jReader) throws IOException {
LstItem lstItem = new LstItem();
jReader.beginObject();
if (jReader.hasNext()) {
}
- private Lst jsonReadLst111(JsonReader jReader, Lst lst) throws IOException {
+ private Lst jsonReadLst111(final JsonReader jReader, final Lst lst) throws IOException {
jReader.beginArray();
while (jReader.hasNext()) {
LstItem lstItem = jsonReadLst111Elements(jReader);
return lst;
}
- private LstItem jsonReadLst111Elements(JsonReader jReader) throws IOException {
+ private LstItem jsonReadLst111Elements(final JsonReader jReader) throws IOException {
LstItem lstItem = new LstItem();
jReader.beginObject();
if (jReader.hasNext()) {
return lstItem;
}
- private Object nextValue(JsonReader jReader) throws IOException {
+ private Object nextValue(final JsonReader jReader) throws IOException {
if (jReader.peek().equals(JsonToken.NULL)) {
jReader.nextNull();
return null;
}
}
- private Cont jsonReadCont111(JsonReader jReader, Cont cont) throws IOException {
+ private Cont jsonReadCont111(final JsonReader jReader, Cont cont) throws IOException {
jReader.beginObject();
cont = jsonReadCont111Elements(jReader, cont);
jReader.endObject();
return cont;
}
- private Cont jsonReadCont111Elements(JsonReader jReader, Cont cont) throws IOException {
+ private Cont jsonReadCont111Elements(final JsonReader jReader, final Cont cont) throws IOException {
while (jReader.hasNext()) {
String keyName = jReader.nextName();
if (keyName.equals("lf1111")) {
}
- private Lst jsonReadLst1111(JsonReader jReader, Lst lst) throws IOException {
+ private Lst jsonReadLst1111(final JsonReader jReader, final Lst lst) throws IOException {
jReader.beginArray();
while (jReader.hasNext()) {
LstItem lstItem = jsonReadLst1111Elements(jReader);
return lst;
}
- private LstItem jsonReadLst1111Elements(JsonReader jReader) throws IOException {
+ private LstItem jsonReadLst1111Elements(final JsonReader jReader) throws IOException {
jReader.beginObject();
LstItem lstItem = new LstItem();
while (jReader.hasNext()) {
return lstItem;
}
- private LfLst jsonReadLflstValues(JsonReader jReader, LfLst lfLst) throws IOException {
+ private LfLst jsonReadLflstValues(final JsonReader jReader, final LfLst lfLst) throws IOException {
jReader.beginArray();
while (jReader.hasNext()) {
lfLst.addLf(new Lf(nextValue(jReader)));
return lfLst;
}
- private void checkDataFromJsonEmpty(Cont dataFromJson) {
+ private void checkDataFromJsonEmpty(final Cont dataFromJson) {
assertTrue(dataFromJson.getLfs().isEmpty());
assertTrue(dataFromJson.getLfLsts().isEmpty());
assertTrue(dataFromJson.getConts().isEmpty());
assertEquals(1, lst11_1.getLsts().size());
assertEquals(
lst11_1.getLsts().get("lst111"),
- new Lst("lst111").addLstItem(new LstItem().addLf("lf1111", (int) 35))
- .addLstItem(new LstItem().addLf("lf1111", (int) 34)).addLstItem(new LstItem())
- .addLstItem(new LstItem()));
+ new Lst("lst111").addLstItem(new LstItem().addLf("lf1111", 35))
+ .addLstItem(new LstItem().addLf("lf1111", 34)).addLstItem(new LstItem())
+ .addLstItem(new LstItem()));
assertEquals(lst11_1.getConts().get("cont111"), new Cont("cont111"));
// : lst11_1
assertEquals(1, lst11_2_cont111.getLsts().size());
assertTrue(lst11_2_cont111.getConts().isEmpty());
- assertEquals(new LfLst("lflst1111").addLf((int) 1024).addLf((int) 4096),
+ assertEquals(new LfLst("lflst1111").addLf(1024).addLf(4096),
lst11_2_cont111.getLfLsts().get("lflst1111"));
assertEquals(
- new Lst("lst1111").addLstItem(new LstItem().addLf("lf1111B", (int) 4)).addLstItem(
+ new Lst("lst1111").addLstItem(new LstItem().addLf("lf1111B", 4)).addLstItem(
new LstItem().addLf("lf1111A", "lf1111A str12")), lst11_2_cont111.getLsts().get("lst1111"));
// :-cont111
assertEquals(lst11_2.getLsts().get("lst112"), new Lst("lst112").addLstItem(new LstItem()));
}
- private void checkDataFromJson(Cont dataFromJson) {
+ private void checkDataFromJson(final Cont dataFromJson) {
assertNotNull(dataFromJson.getLfs().get("lf11"));
assertEquals(dataFromJson.getLfs().get("lf11"), new Lf("lf11", "lf"));
checkLst11_2(lst11_2);
}
- private void checkLst11_2(LstItem lst11_2) {
+ private void checkLst11_2(final LstItem lst11_2) {
assertNotNull(lst11_2);
assertEquals(2, lst11_2.getLfs().size());
assertEquals(1, lst11_2.getConts().size());
new LstItem().addLf(new Lf("lf1121", "lf1121 str21")));
}
- private void checkLst11_1(LstItem lst11_1) {
+ private void checkLst11_1(final LstItem lst11_1) {
assertNotNull(lst11_1);
assertEquals(2, lst11_1.getLfs().size());
checkLst11x(lst11_1.getLsts().get("lst112"), new LstItem().addLf(new Lf("lf1121", "lf1121 str11")));
}
- private void checkLst11x(Lst lst, LstItem... lstItems) {
+ private void checkLst11x(final Lst lst, final LstItem... lstItems) {
assertNotNull(lst);
Lst requiredLst = new Lst(lst.getName());
}
- private void checkLst1111(Set<LstItem> lstItems, Lf lf11, Lf lf12, Lf lf21, Lf lf22) {
+ private void checkLst1111(final Set<LstItem> lstItems, final Lf lf11, final Lf lf12, final Lf lf21, final Lf lf22) {
LstItem lst11_1_cont_lst1111_1 = null;
LstItem lst11_1_cont_lst1111_2 = null;
for (LstItem lstItem : lstItems) {
// lst11_1
MutableCompositeNode lst11_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11","simple:yang:types","2013-11-5"), cont1,
null, ModifyAction.CREATE, null);
- cont1.getChildren().add(lst11_1);
+ cont1.getValue().add(lst11_1);
MutableSimpleNode<?> lf111_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111","simple:yang:types","2013-11-5"), lst11_1,
(short) 1, ModifyAction.CREATE, null);
- lst11_1.getChildren().add(lf111_1);
+ lst11_1.getValue().add(lf111_1);
// lst111_1_1
MutableCompositeNode lst111_1_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"),
lst11_1, null, ModifyAction.CREATE, null);
- lst11_1.getChildren().add(lst111_1_1);
+ lst11_1.getValue().add(lst111_1_1);
MutableSimpleNode<?> lf1111_1_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111","simple:yang:types","2013-11-5"),
- lst111_1_1, (int) 34, ModifyAction.CREATE, null);
- lst111_1_1.getChildren().add(lf1111_1_1);
+ lst111_1_1, 34, ModifyAction.CREATE, null);
+ lst111_1_1.getValue().add(lf1111_1_1);
lst111_1_1.init();
// :lst111_1_1
// lst111_1_2
MutableCompositeNode lst111_1_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"),
lst11_1, null, ModifyAction.CREATE, null);
- lst11_1.getChildren().add(lst111_1_2);
+ lst11_1.getValue().add(lst111_1_2);
MutableSimpleNode<?> lf1111_1_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111","simple:yang:types","2013-11-5"),
- lst111_1_2, (int) 35, ModifyAction.CREATE, null);
- lst111_1_2.getChildren().add(lf1111_1_2);
+ lst111_1_2, 35, ModifyAction.CREATE, null);
+ lst111_1_2.getValue().add(lf1111_1_2);
lst111_1_2.init();
// :lst111_1_2
// lst111_1_3
MutableCompositeNode lst111_1_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"),
lst11_1, null, ModifyAction.CREATE, null);
- lst11_1.getChildren().add(lst111_1_3);
+ lst11_1.getValue().add(lst111_1_3);
lst111_1_2.init();
// :lst111_1_3
// lst111_1_4
MutableCompositeNode lst111_1_4 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"),
lst11_1, null, ModifyAction.CREATE, null);
- lst11_1.getChildren().add(lst111_1_4);
+ lst11_1.getValue().add(lst111_1_4);
lst111_1_2.init();
// :lst111_1_4
MutableCompositeNode cont111_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111","simple:yang:types","2013-11-5"),
lst11_1, null, ModifyAction.CREATE, null);
- lst11_1.getChildren().add(cont111_1);
+ lst11_1.getValue().add(cont111_1);
lst11_1.init();
// :lst11_1
// lst11_2
MutableCompositeNode lst11_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11","simple:yang:types","2013-11-5"), cont1,
null, ModifyAction.CREATE, null);
- cont1.getChildren().add(lst11_2);
+ cont1.getValue().add(lst11_2);
MutableSimpleNode<?> lf111_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111","simple:yang:types","2013-11-5"), lst11_2,
(short) 2, ModifyAction.CREATE, null);
- lst11_2.getChildren().add(lf111_2);
+ lst11_2.getValue().add(lf111_2);
// cont111_2
MutableCompositeNode cont111_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111","simple:yang:types","2013-11-5"),
lst11_2, null, ModifyAction.CREATE, null);
- lst11_2.getChildren().add(cont111_2);
+ lst11_2.getValue().add(cont111_2);
MutableSimpleNode<?> lflst1111_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111","simple:yang:types","2013-11-5"),
- cont111_2, (int) 1024, ModifyAction.CREATE, null);
- cont111_2.getChildren().add(lflst1111_2_2);
+ cont111_2, 1024, ModifyAction.CREATE, null);
+ cont111_2.getValue().add(lflst1111_2_2);
MutableSimpleNode<?> lflst1111_2_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111","simple:yang:types","2013-11-5"),
- cont111_2, (int) 4096, ModifyAction.CREATE, null);
- cont111_2.getChildren().add(lflst1111_2_3);
+ cont111_2, 4096, ModifyAction.CREATE, null);
+ cont111_2.getValue().add(lflst1111_2_3);
// lst1111_2
MutableCompositeNode lst1111_2_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"),
cont111_2, null, ModifyAction.CREATE, null);
- cont111_2.getChildren().add(lst1111_2_1);
+ cont111_2.getValue().add(lst1111_2_1);
MutableSimpleNode<?> lf1111B_2_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111B","simple:yang:types","2013-11-5"),
lst1111_2_1, (short) 4, ModifyAction.CREATE, null);
- lst1111_2_1.getChildren().add(lf1111B_2_1);
+ lst1111_2_1.getValue().add(lf1111B_2_1);
lst1111_2_1.init();
MutableCompositeNode lst1111_2_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"),
cont111_2, null, ModifyAction.CREATE, null);
- cont111_2.getChildren().add(lst1111_2_2);
+ cont111_2.getValue().add(lst1111_2_2);
MutableSimpleNode<?> lf1111A_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111A","simple:yang:types","2013-11-5"),
lst1111_2_2, "lf1111A str12", ModifyAction.CREATE, null);
- lst1111_2_2.getChildren().add(lf1111A_2_2);
+ lst1111_2_2.getValue().add(lf1111A_2_2);
lst1111_2_2.init();
// :lst1111_2
MutableCompositeNode lst112_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst112","simple:yang:types","2013-11-5"), lst11_2,
null, ModifyAction.CREATE, null);
- lst11_2.getChildren().add(lst112_2);
+ lst11_2.getValue().add(lst112_2);
lst112_2.init();
lst11_2.init();
// lst11_3
MutableCompositeNode lst11_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11","simple:yang:types","2013-11-5"), cont1,
null, ModifyAction.CREATE, null);
- cont1.getChildren().add(lst11_3);
+ cont1.getValue().add(lst11_3);
MutableSimpleNode<?> lf111_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111","simple:yang:types","2013-11-5"), lst11_3,
(short) 3, ModifyAction.CREATE, null);
- lst11_3.getChildren().add(lf111_3);
+ lst11_3.getValue().add(lf111_3);
// cont111_3
MutableCompositeNode cont111_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111","simple:yang:types","2013-11-5"),
lst11_3, null, ModifyAction.CREATE, null);
- lst11_3.getChildren().add(cont111_3);
+ lst11_3.getValue().add(cont111_3);
MutableCompositeNode lst1111_3_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"),
cont111_3, null, ModifyAction.CREATE, null);
- cont111_3.getChildren().add(lst1111_3_1);
+ cont111_3.getValue().add(lst1111_3_1);
lst1111_3_1.init();
MutableCompositeNode lst1111_3_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"),
cont111_3, null, ModifyAction.CREATE, null);
- cont111_3.getChildren().add(lst1111_3_2);
+ cont111_3.getValue().add(lst1111_3_2);
lst1111_3_2.init();
cont111_3.init();
assertTrue(mtch.matches());
}
- private CompositeNode prepareCompositeNode(Object value) {
+ private CompositeNode prepareCompositeNode(final Object value) {
MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont","identityref:module","2013-12-2"), null, null,
ModifyAction.CREATE, null);
MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont1","identityref:module","2013-12-2"), cont, null,
ModifyAction.CREATE, null);
- cont.getChildren().add(cont1);
+ cont.getValue().add(cont1);
MutableSimpleNode<?> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1","identityref:module","2013-12-2"), cont1, value,
ModifyAction.CREATE, null);
- cont1.getChildren().add(lf1);
+ cont1.getValue().add(lf1);
cont1.init();
cont.init();
import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
import org.slf4j.Logger;
String jsonOutput = null;
jsonOutput = TestUtils
.writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(),
- Collections.EMPTY_SET, prepareDataSchemaNode(),
+ Collections.<Module>emptySet(), prepareDataSchemaNode(),
StructuredDataToJsonProvider.INSTANCE);
assertNotNull(jsonOutput);
assertTrue(jsonOutput.contains("\"lf1\": \"\""));
TestUtils.buildQName("cont", "simple:uri", "2012-12-17"), null, null, ModifyAction.CREATE, null);
MutableSimpleNode<?> lf1 = NodeFactory.createMutableSimpleNode(
TestUtils.buildQName("lf1", "simple:uri", "2012-12-17"), cont, "any value", ModifyAction.CREATE, null);
- cont.getChildren().add(lf1);
+ cont.getValue().add(lf1);
cont.init();
return cont;
}
MutableCompositeNode cont_m1 = NodeFactory.createMutableCompositeNode(
TestUtils.buildQName("cont_m1", uri1, rev1), data, null, null, null);
- data.getChildren().add(cont_m1);
+ data.getValue().add(cont_m1);
MutableSimpleNode<?> lf1_m1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1_m1", uri1, rev1),
cont_m1, "lf1 m1 value", null, null);
- cont_m1.getChildren().add(lf1_m1);
+ cont_m1.getValue().add(lf1_m1);
cont_m1.init();
MutableCompositeNode contB_m1 = NodeFactory.createMutableCompositeNode(
TestUtils.buildQName("contB_m1", uri1, rev1), data, null, null, null);
- data.getChildren().add(contB_m1);
+ data.getValue().add(contB_m1);
contB_m1.init();
String uri2 = "module:two";
String rev2 = "2014-01-17";
MutableCompositeNode cont_m2 = NodeFactory.createMutableCompositeNode(
TestUtils.buildQName("cont_m2", uri2, rev2), data, null, null, null);
- data.getChildren().add(cont_m2);
+ data.getValue().add(cont_m2);
MutableSimpleNode<?> lf1_m2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1_m2", uri2, rev2),
cont_m1, "lf1 m2 value", null, null);
- cont_m2.getChildren().add(lf1_m2);
+ cont_m2.getValue().add(lf1_m2);
cont_m2.init();
MutableCompositeNode contB_m2 = NodeFactory.createMutableCompositeNode(
TestUtils.buildQName("contB_m2", uri2, rev2), data, null, null, null);
- data.getChildren().add(contB_m2);
+ data.getValue().add(contB_m2);
contB_m2.init();
data.init();
import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
import org.slf4j.Logger;
boolean nullPointerExceptionRaised = false;
try {
TestUtils.writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(),
- Collections.EMPTY_SET, prepareDataSchemaNode(), StructuredDataToXmlProvider.INSTANCE);
+ Collections.<Module>emptySet(), prepareDataSchemaNode(), StructuredDataToXmlProvider.INSTANCE);
} catch (WebApplicationException | IOException e) {
LOG.error("WebApplicationException or IOException was raised");
} catch (NullPointerException e) {
TestUtils.buildQName("cont", "simple:uri", "2012-12-17"), null, null, ModifyAction.CREATE, null);
MutableSimpleNode<?> lf1 = NodeFactory.createMutableSimpleNode(
TestUtils.buildQName("lf1", "simple:uri", "2012-12-17"), cont, "any value", ModifyAction.CREATE, null);
- cont.getChildren().add(lf1);
+ cont.getValue().add(lf1);
cont.init();
return cont;
}
import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
/**
- *
+ *
* CnSn = Composite node and Simple node data structure Class contains test of
* serializing simple nodes data values according data types from YANG schema to
* XML file
- *
+ *
*/
public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader {
@BeforeClass
serializeToXml(
prepareCnStructForYangData(
TypeDefinitionAwareCodec.BINARY_DEFAULT_CODEC
- .deserialize("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"),
+ .deserialize("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"),
elName), "<" + elName + ">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567</"
- + elName + ">");
+ + elName + ">");
}
@Test
+ elName + ">str</" + elName + ">");
}
- private void serializeToXml(CompositeNode compositeNode, String... xmlRepresentation)
+ private void serializeToXml(final CompositeNode compositeNode, final String... xmlRepresentation)
throws TransformerFactoryConfigurationError {
String xmlString = "";
try {
}
- private CompositeNode prepareIdentityrefData(String prefix, boolean valueAsQName) {
+ private CompositeNode prepareIdentityrefData(final String prefix, final boolean valueAsQName) {
MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
TestUtils.buildQName("cont", "basic:module", "2013-12-2"), null, null, ModifyAction.CREATE, null);
MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(
TestUtils.buildQName("cont1", "basic:module", "2013-12-2"), cont, null, ModifyAction.CREATE, null);
- cont.getChildren().add(cont1);
+ cont.getValue().add(cont1);
Object value = null;
if (valueAsQName) {
}
MutableSimpleNode<Object> lf11 = NodeFactory.createMutableSimpleNode(
TestUtils.buildQName("lf11", "basic:module", "2013-12-2"), cont1, value, ModifyAction.CREATE, null);
- cont1.getChildren().add(lf11);
+ cont1.getValue().add(lf11);
cont1.init();
cont.init();
return cont;
}
- private CompositeNode prepareCnStructForYangData(Object data, String leafName) {
+ private CompositeNode prepareCnStructForYangData(final Object data, final String leafName) {
MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
ModifyAction.CREATE, null);
MutableSimpleNode<Object> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName(leafName), cont, data,
ModifyAction.CREATE, null);
- cont.getChildren().add(lf1);
+ cont.getValue().add(lf1);
cont.init();
return cont;
cont, Boolean.TRUE, ModifyAction.CREATE, null);
MutableSimpleNode<Object> lfLfref = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfLfref"), cont,
"true", ModifyAction.CREATE, null);
- cont.getChildren().add(lfBoolean);
- cont.getChildren().add(lfLfref);
+ cont.getValue().add(lfBoolean);
+ cont.getValue().add(lfLfref);
cont.init();
return cont;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.*;
+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.impl.NodeFactory;
/**
- *
+ *
* CnSn = Composite node and Simple node data structure Class contains test of
* serializing simple nodes data values according data types from YANG schema to
* XML file
- *
+ *
*/
public class CnSnToXmlWithChoiceTest extends YangAndXmlAndDataSchemaLoader {
@BeforeClass
}
- private CompositeNode prepareCnStructForYangData(String lfName, Object data) {
+ private CompositeNode prepareCnStructForYangData(final String lfName, final Object data) {
MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
ModifyAction.CREATE, null);
MutableSimpleNode<Object> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName(lfName), cont, data,
ModifyAction.CREATE, null);
- cont.getChildren().add(lf1);
+ cont.getValue().add(lf1);
cont.init();
return cont;
*/
package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import java.util.List;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
public class JsonIdentityrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
assertEquals("cont", compositeNode.getNodeType().getLocalName());
- List<Node<?>> childs = compositeNode.getChildren();
+ List<Node<?>> childs = compositeNode.getValue();
assertEquals(1, childs.size());
Node<?> nd = childs.iterator().next();
assertTrue(nd instanceof CompositeNode);
assertEquals("cont1", nd.getNodeType().getLocalName());
- childs = ((CompositeNode) nd).getChildren();
+ childs = ((CompositeNode) nd).getValue();
assertEquals(4, childs.size());
SimpleNode<?> lf11 = null;
SimpleNode<?> lf12 = null;
*/
package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
public class JsonLeafrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
assertEquals("cont", compositeNode.getNodeType().getLocalName());
SimpleNode<?> lf2 = null;
- for (Node<?> childNode : compositeNode.getChildren()) {
+ for (Node<?> childNode : compositeNode.getValue()) {
if (childNode instanceof SimpleNode) {
if (childNode.getNodeType().getLocalName().equals("lf2")) {
lf2 = (SimpleNode<?>) childNode;
assertNotNull(lf2);
assertTrue(lf2.getValue() instanceof String);
- assertEquals("121", (String) lf2.getValue());
+ assertEquals("121", lf2.getValue());
}
package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.Set;
-import javax.ws.rs.WebApplicationException;
-
import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.gson.JsonSyntaxException;
-
public class JsonToCnSnTest {
private static final Logger LOG = LoggerFactory.getLogger(JsonToCnSnTest.class);
CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-leaflist-items.json", true,
JsonToCompositeNodeProvider.INSTANCE);
assertNotNull(compositeNode);
- assertEquals(3, compositeNode.getChildren().size());
+ assertEquals(3, compositeNode.getValue().size());
boolean lflst1_1 = false;
boolean lflst1_2 = false;
boolean lflst1_3 = false;
- for (Node<?> node : compositeNode.getChildren()) {
+ for (Node<?> node : compositeNode.getValue()) {
assertEquals("lflst1", node.getNodeType().getLocalName());
assertTrue(node instanceof SimpleNode<?>);
SimpleNode<?> simpleNode = (SimpleNode<?>) node;
assertNotNull(compositeNode);
assertEquals("cont", compositeNode.getNodeType().getLocalName());
- assertNotNull(compositeNode.getChildren());
- assertEquals(1, compositeNode.getChildren().size());
- Node<?> lfNode = compositeNode.getChildren().iterator().next();
+ assertNotNull(compositeNode.getValue());
+ assertEquals(1, compositeNode.getValue().size());
+ Node<?> lfNode = compositeNode.getValue().iterator().next();
assertTrue(lfNode instanceof SimpleNode<?>);
assertEquals(null, ((SimpleNode<?>) lfNode).getValue());
@Test
public void incorrectTopLevelElementsTest() {
- Throwable cause1 = null;
+ RestconfDocumentedException cause1 = null;
try {
- TestUtils
- .readInputToCnSn("/json-to-cnsn/wrong-top-level1.json", true, JsonToCompositeNodeProvider.INSTANCE);
- } catch (WebApplicationException e) {
+ TestUtils.readInputToCnSn("/json-to-cnsn/wrong-top-level1.json", true, JsonToCompositeNodeProvider.INSTANCE);
+ } catch (RestconfDocumentedException e) {
cause1 = e;
}
assertNotNull(cause1);
- assertTrue(cause1
- .getCause()
- .getMessage()
- .contains(
- "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
+ assertTrue(cause1.getErrors().get( 0 ).getErrorMessage().contains(
+ "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
- Throwable cause2 = null;
+ RestconfDocumentedException cause2 = null;
try {
TestUtils
.readInputToCnSn("/json-to-cnsn/wrong-top-level2.json", true, JsonToCompositeNodeProvider.INSTANCE);
- } catch (WebApplicationException e) {
+ } catch (RestconfDocumentedException e) {
cause2 = e;
}
assertNotNull(cause2);
- assertTrue(cause2.getCause().getMessage().contains("Json Object should contain one element"));
+ assertTrue(cause2.getErrors().get( 0 ).getErrorMessage().contains(
+ "Json Object should contain one element"));
- Throwable cause3 = null;
+ RestconfDocumentedException cause3 = null;
try {
TestUtils
+
.readInputToCnSn("/json-to-cnsn/wrong-top-level3.json", true, JsonToCompositeNodeProvider.INSTANCE);
- } catch (WebApplicationException e) {
+ } catch (RestconfDocumentedException e) {
cause3 = e;
}
assertNotNull(cause3);
- assertTrue(cause3
- .getCause()
- .getMessage()
- .contains(
- "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
+ assertTrue(cause3.getErrors().get( 0 ).getErrorMessage().contains(
+ "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
}
assertEquals("cont", compositeNode.getNodeType().getLocalName());
assertTrue(compositeNode instanceof CompositeNode);
- List<Node<?>> children = ((CompositeNode) compositeNode).getChildren();
+ List<Node<?>> children = compositeNode.getValue();
assertEquals(1, children.size());
assertEquals("lflst2", children.get(0).getNodeType().getLocalName());
assertEquals("45", children.get(0).getValue());
String reason = null;
try {
TestUtils.readInputToCnSn("/json-to-cnsn/empty-data1.json", true, JsonToCompositeNodeProvider.INSTANCE);
- } catch (JsonSyntaxException e) {
- reason = e.getMessage();
+ } catch (RestconfDocumentedException e) {
+ reason = e.getErrors().get( 0 ).getErrorMessage();
}
assertTrue(reason.contains("Expected value at line"));
* Tests whether namespace <b>stay unchanged</b> if concrete values are
* present in composite or simple node and if the method for update is
* called.
- *
+ *
*/
@Test
public void notSupplyNamespaceIfAlreadySupplied() {
assertEquals("cont", compositeNode.getNodeType().getLocalName());
- List<Node<?>> childs = compositeNode.getChildren();
+ List<Node<?>> childs = compositeNode.getValue();
assertEquals(1, childs.size());
Node<?> nd = childs.iterator().next();
assertTrue(nd instanceof CompositeNode);
assertEquals("cont1", nd.getNodeType().getLocalName());
- childs = ((CompositeNode) nd).getChildren();
+ childs = ((CompositeNode) nd).getValue();
assertEquals(4, childs.size());
SimpleNode<?> lf11 = null;
SimpleNode<?> lf12 = null;
assertEquals("iden_local", ((QName) lf14.getValue()).getLocalName());
assertEquals("identity:module", ((QName) lf14.getValue()).getNamespace().toString());
}
-
+
@Ignore
@Test
public void loadDataAugmentedSchemaMoreEqualNamesTest() {
- boolean exceptionCaught = false;
- try {
- loadAndNormalizeData("/common/augment/json/dataa.json", "/common/augment/yang", "cont", "main");
- loadAndNormalizeData("/common/augment/json/datab.json", "/common/augment/yang", "cont", "main");
- } catch (ResponseException e) {
- exceptionCaught = true;
- }
-
- assertFalse(exceptionCaught);
+ loadAndNormalizeData("/common/augment/json/dataa.json", "/common/augment/yang", "cont", "main");
+ loadAndNormalizeData("/common/augment/json/datab.json", "/common/augment/yang", "cont", "main");
+
}
- private void simpleTest(String jsonPath, String yangPath, String topLevelElementName, String namespace,
- String moduleName) {
+ private void simpleTest(final String jsonPath, final String yangPath, final String topLevelElementName, final String namespace,
+ final String moduleName) {
CompositeNode compNode = loadAndNormalizeData(jsonPath, yangPath, topLevelElementName, moduleName);
verifyCompositeNode(compNode, namespace);
}
- private CompositeNode loadAndNormalizeData(String jsonPath, String yangPath, String topLevelElementName, String moduleName) {
+ private CompositeNode loadAndNormalizeData(final String jsonPath, final String yangPath, final String topLevelElementName, final String moduleName) {
CompositeNode compositeNode = TestUtils.readInputToCnSn(jsonPath, false, JsonToCompositeNodeProvider.INSTANCE);
assertNotNull(compositeNode);
return compNode;
}
- private void verityMultipleItemsInList(CompositeNode compositeNode) {
- List<Node<?>> childrenNodes = compositeNode.getChildren();
+ private void verityMultipleItemsInList(final CompositeNode compositeNode) {
+ List<Node<?>> childrenNodes = compositeNode.getValue();
assertEquals(4, childrenNodes.size());
boolean lf11Found = false;
boolean cont11Found = false;
assertEquals("lst1", lst1Item.getNodeType().getLocalName());
assertTrue(lst1Item instanceof CompositeNode);
- List<Node<?>> childrenLst1 = ((CompositeNode) lst1Item).getChildren();
+ List<Node<?>> childrenLst1 = ((CompositeNode) lst1Item).getValue();
assertEquals(1, childrenLst1.size());
String localName = childrenLst1.get(0).getNodeType().getLocalName();
if (localName.equals("lf11")) {
} else if (localName.equals("lst11")) {
lst11Found = true;
assertTrue(childrenLst1.get(0) instanceof CompositeNode);
- assertEquals(0, ((CompositeNode) childrenLst1.get(0)).getChildren().size());
+ assertEquals(0, ((CompositeNode) childrenLst1.get(0)).getValue().size());
}
}
assertTrue(lst11Found);
}
- private void verifyCompositeNode(CompositeNode compositeNode, String namespace) {
+ private void verifyCompositeNode(final CompositeNode compositeNode, final String namespace) {
boolean cont1Found = false;
boolean lst1Found = false;
boolean lflst1_1Found = false;
// assertEquals(namespace,
// compositeNode.getNodeType().getNamespace().toString());
- for (Node<?> node : compositeNode.getChildren()) {
+ for (Node<?> node : compositeNode.getValue()) {
if (node.getNodeType().getLocalName().equals("cont1")) {
if (node instanceof CompositeNode) {
cont1Found = true;
- assertEquals(0, ((CompositeNode) node).getChildren().size());
+ assertEquals(0, ((CompositeNode) node).getValue().size());
}
} else if (node.getNodeType().getLocalName().equals("lst1")) {
if (node instanceof CompositeNode) {
lst1Found = true;
- assertEquals(0, ((CompositeNode) node).getChildren().size());
+ assertEquals(0, ((CompositeNode) node).getValue().size());
}
} else if (node.getNodeType().getLocalName().equals("lflst1")) {
if (node instanceof SimpleNode) {
try {
TestUtils.readInputToCnSn("/json-to-cnsn/unsupported-json-format.json", true,
JsonToCompositeNodeProvider.INSTANCE);
- } catch (WebApplicationException e) {
- exceptionMessage = e.getCause().getMessage();
+ } catch (RestconfDocumentedException e) {
+ exceptionMessage = e.getErrors().get( 0 ).getErrorMessage();
}
assertTrue(exceptionMessage.contains("Root element of Json has to be Object"));
}
package org.opendaylight.controller.sal.restconf.impl.test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import java.util.Map;
import java.util.concurrent.Future;
-import javax.ws.rs.core.Response.Status;
-
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.controller.sal.streams.listeners.Notificator;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
assertSame( "readOperationalDataBehindMountPoint", dataNode, actualNode );
}
- @Test(expected=ResponseException.class)
+ @Test(expected=RestconfDocumentedException.class)
public void testReadOperationalDataWithNoDataBroker() {
brokerFacade.setDataService( null );
@SuppressWarnings("unchecked")
@Test
- public void testInvokeRpc() {
+ public void testInvokeRpc() throws Exception {
RpcResult<CompositeNode> expResult = mock( RpcResult.class );
Future<RpcResult<CompositeNode>> future = Futures.immediateFuture( expResult );
when( mockConsumerSession.rpc( qname, dataNode ) ).thenReturn( future );
- RpcResult<CompositeNode> actualResult = brokerFacade.invokeRpc( qname, dataNode );
+ Future<RpcResult<CompositeNode>> actualFuture = brokerFacade.invokeRpc( qname, dataNode );
+ assertNotNull( "Future is null", actualFuture );
+ RpcResult<CompositeNode> actualResult = actualFuture.get();
assertSame( "invokeRpc", expResult, actualResult );
}
- @Test(expected=ResponseException.class)
- public void testInvokeRpcWithException() {
- Exception mockEx = new Exception( "mock" );
- Future<RpcResult<CompositeNode>> future = Futures.immediateFailedFuture( mockEx );
- when( mockConsumerSession.rpc( qname, dataNode ) ).thenReturn( future );
-
- brokerFacade.invokeRpc( qname, dataNode );
- }
-
- @Test(expected=ResponseException.class)
+ @Test(expected=RestconfDocumentedException.class)
public void testInvokeRpcWithNoConsumerSession() {
brokerFacade.setContext( null );
inOrder.verify( mockTransaction ).commit();
}
- @Test(expected=ResponseException.class)
+ @Test(expected=RestconfDocumentedException.class)
public void testCommitConfigurationDataPostAlreadyExists() {
when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
mockTransaction.putConfigurationData( instanceID, dataNode );
.thenReturn( dataNode );
try {
brokerFacade.commitConfigurationDataPost( instanceID, dataNode );
- } catch (ResponseException e) {
- assertEquals("Unexpect Exception Status -> "
- + "http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48",
- (e.getResponse().getStatus()), Status.CONFLICT.getStatusCode());
+ }
+ catch (RestconfDocumentedException e) {
+ assertEquals("getErrorTag",
+ RestconfError.ErrorTag.DATA_EXISTS, e.getErrors().get( 0 ).getErrorTag());
throw e;
}
}
inOrder.verify( mockTransaction ).commit();
}
- @Test(expected=ResponseException.class)
+ @Test(expected=RestconfDocumentedException.class)
public void testCommitConfigurationDataPostBehindMountPointAlreadyExists() {
when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
try {
brokerFacade.commitConfigurationDataPostBehindMountPoint( mockMountInstance,
instanceID, dataNode );
- } catch (ResponseException e) {
- assertEquals("Unexpect Exception Status -> "
- + "http://tools.ietf.org/html/draft-bierman-netconf-restconf-03#page-48",
- e.getResponse().getStatus(), Status.CONFLICT.getStatusCode());
+ }
+ catch (RestconfDocumentedException e) {
+ assertEquals("getErrorTag",
+ RestconfError.ErrorTag.DATA_EXISTS, e.getErrors().get( 0 ).getErrorTag());
throw e;
}
}
@Ignore
@Test
public void saveCnSnWithLeafListInstIdentifierToXmlTest() throws WebApplicationException, IOException,
- URISyntaxException, XMLStreamException {
+ URISyntaxException, XMLStreamException {
CompositeNode cnSn = prepareCnSn(createInstanceIdentifierWithLeafList());
String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
StructuredDataToXmlProvider.INSTANCE);
@Test
public void saveCnSnWithLeafListInstIdentifierToJsonTest() throws WebApplicationException, IOException,
- URISyntaxException {
+ URISyntaxException {
CompositeNode cnSn = prepareCnSn(createInstanceIdentifierWithLeafList());
String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
StructuredDataToJsonProvider.INSTANCE);
assertTrue(strInOutput);
}
- private void validateXmlOutput(String xml) throws XMLStreamException {
+ private void validateXmlOutput(final String xml) throws XMLStreamException {
XMLInputFactory xmlInFactory = XMLInputFactory.newInstance();
XMLEventReader eventReader;
}
- private void validateXmlOutputWithLeafList(String xml) throws XMLStreamException {
+ private void validateXmlOutputWithLeafList(final String xml) throws XMLStreamException {
XMLInputFactory xmlInFactory = XMLInputFactory.newInstance();
XMLEventReader eventReader;
}
- private CompositeNode prepareCnSn(InstanceIdentifier instanceIdentifier) throws URISyntaxException {
+ private CompositeNode prepareCnSn(final InstanceIdentifier instanceIdentifier) throws URISyntaxException {
MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
TestUtils.buildQName("cont", "instance:identifier:module", "2014-01-17"), null, null,null,null);
MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(
lst11, instanceIdentifier,null,null);
- lst11.getChildren().add(lf111);
+ lst11.getValue().add(lf111);
lst11.init();
- cont1.getChildren().add(lst11);
+ cont1.getValue().add(lst11);
cont1.init();
- cont.getChildren().add(cont1);
+ cont.getValue().add(cont1);
cont.init();
return cont;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
resourceConfig = resourceConfig.registerInstances(restConf, StructuredDataToXmlProvider.INSTANCE,
StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
JsonToCompositeNodeProvider.INSTANCE);
+ resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
return resourceConfig;
}
/*
* 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.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
import java.util.Set;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.sal.common.util.RpcErrors;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+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.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
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.RpcError.ErrorSeverity;
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.base.Optional;
+import com.google.common.util.concurrent.Futures;
+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
- public RpcResult<CompositeNode> answer(InvocationOnMock invocation) throws Throwable {
- CompositeNode compNode = (CompositeNode) invocation.getArguments()[1];
- return new DummyRpcResult.Builder<CompositeNode>().result(compNode).isSuccessful(true).build();
- }
- }
@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) {
restconf.setBroker(mockedBrokerFacade);
restconf.setControllerContext(contContext);
- when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenAnswer(new AnswerImpl());
+ CompositeNode payload = preparePayload();
- StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", preparePayload());
+ when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class)))
+ .thenReturn( Futures.<RpcResult<CompositeNode>>immediateFuture(
+ Rpcs.<CompositeNode>getRpcResult( true ) ) );
- 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);
+ StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", payload);
+ assertTrue(structData == null);
}
TestUtils.buildQName("cont", "nmspc", "2013-12-04"), null, null, ModifyAction.CREATE, null);
MutableSimpleNode<?> lf = NodeFactory.createMutableSimpleNode(
TestUtils.buildQName("lf", "nmspc", "2013-12-04"), cont, "any value", ModifyAction.CREATE, null);
- cont.getChildren().add(lf);
+ cont.getValue().add(lf);
cont.init();
return cont;
}
+ @Test
+ public void testInvokeRpcWithNoPayloadRpc_FailNoErrors() {
+ RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( false );
+
+ 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( Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ) );
+
+ restconfImpl.setBroker(brokerFacade);
+
+ try {
+ restconfImpl.invokeRpc("toaster:cancel-toast", "");
+ fail("Expected an exception to be thrown.");
+ }
+ catch (RestconfDocumentedException e) {
+ verifyRestconfDocumentedException( e, 0, ErrorType.RPC, ErrorTag.OPERATION_FAILED,
+ Optional.<String>absent(), Optional.<String>absent() );
+ }
+ }
+
+ void verifyRestconfDocumentedException( final RestconfDocumentedException e, final int index,
+ final ErrorType expErrorType, final ErrorTag expErrorTag,
+ final Optional<String> expErrorMsg,
+ final Optional<String> expAppTag ) {
+ RestconfError actual = null;
+ try {
+ actual = e.getErrors().get( index );
+ }
+ catch( ArrayIndexOutOfBoundsException ex ) {
+ fail( "RestconfError not found at index " + index );
+ }
+
+ assertEquals( "getErrorType", expErrorType, actual.getErrorType() );
+ assertEquals( "getErrorTag", expErrorTag, actual.getErrorTag() );
+ assertNotNull( "getErrorMessage is null", actual.getErrorMessage() );
+
+ if( expErrorMsg.isPresent() ) {
+ assertEquals( "getErrorMessage", expErrorMsg.get(), actual.getErrorMessage() );
+ }
+
+ if( expAppTag.isPresent() ) {
+ assertEquals( "getErrorAppTag", expAppTag.get(), actual.getErrorAppTag() );
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNoPayloadRpc_FailWithRpcError() {
+ List<RpcError> rpcErrors = Arrays.asList(
+ RpcErrors.getRpcError( null, "bogusTag", null, ErrorSeverity.ERROR, "foo",
+ RpcError.ErrorType.TRANSPORT, null ),
+ RpcErrors.getRpcError( "app-tag", "in-use", null, ErrorSeverity.WARNING, "bar",
+ RpcError.ErrorType.RPC, null ));
+
+ RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( false, rpcErrors );
+
+ 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( Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ) );
+
+ restconfImpl.setBroker(brokerFacade);
+
+ try {
+ restconfImpl.invokeRpc("toaster:cancel-toast", "");
+ fail("Expected an exception to be thrown.");
+ }
+ catch (RestconfDocumentedException e) {
+ verifyRestconfDocumentedException( e, 0, ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED,
+ Optional.of( "foo" ), Optional.<String>absent() );
+ verifyRestconfDocumentedException( e, 1, ErrorType.RPC, ErrorTag.IN_USE,
+ Optional.of( "bar" ), Optional.of( "app-tag" ) );
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNoPayload_Success() {
+ RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( 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( Futures.<RpcResult<CompositeNode>>immediateFuture( 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 (RestconfDocumentedException e) {
+ verifyRestconfDocumentedException( e, 0, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
+ Optional.<String>absent(), Optional.<String>absent() );
+ }
+ }
+
+ @Test
+ public void testInvokeRpcMethodWithBadMethodName() {
+ try {
+ restconfImpl.invokeRpc("toaster:bad-method", "");
+ fail("Expected an exception");
+ }
+ catch (RestconfDocumentedException e) {
+ verifyRestconfDocumentedException( e, 0, ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT,
+ Optional.<String>absent(), Optional.<String>absent() );
+ }
+ }
+
+ @Test
+ public void testInvokeRpcMethodWithInput() {
+ RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( 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( Futures.<RpcResult<CompositeNode>>immediateFuture( 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 (RestconfDocumentedException e) {
+ verifyRestconfDocumentedException( e, 0, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
+ Optional.<String>absent(), Optional.<String>absent() );
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNoPayloadWithOutput_Success() {
+ CompositeNode compositeNode = mock( CompositeNode.class );
+ RpcResult<CompositeNode> rpcResult = Rpcs.<CompositeNode>getRpcResult( true, compositeNode,
+ Collections.<RpcError>emptyList() );
+
+ 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( Futures.<RpcResult<CompositeNode>>immediateFuture( 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 = Rpcs.<CompositeNode>getRpcResult( 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.
+ }
}
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
dataLoad("/normalize-node/yang/");
}
- @Test
+ @Test(expected=RestconfDocumentedException.class)
public void namespaceNotNullAndInvalidNamespaceAndNoModuleNameTest() {
- boolean exceptionReised = false;
- try {
- TestUtils.normalizeCompositeNode(prepareCnSn("wrongnamespace"), modules, schemaNodePath);
- } catch (ResponseException e) {
- exceptionReised = true;
- }
- assertTrue(exceptionReised);
+
+ TestUtils.normalizeCompositeNode(prepareCnSn("wrongnamespace"), modules, schemaNodePath);
}
@Test
public void namespaceNullTest() {
- String exceptionMessage = null;
- try {
- TestUtils.normalizeCompositeNode(prepareCnSn(null), modules, schemaNodePath);
- } catch (ResponseException e) {
- exceptionMessage = String.valueOf(e.getResponse().getEntity());
- }
- assertNull(exceptionMessage);
+
+ TestUtils.normalizeCompositeNode(prepareCnSn(null), modules, schemaNodePath);
}
@Test
public void namespaceValidNamespaceTest() {
- String exceptionMessage = null;
- try {
- TestUtils.normalizeCompositeNode(prepareCnSn("normalize:node:module"), modules, schemaNodePath);
- } catch (ResponseException e) {
- exceptionMessage = String.valueOf(e.getResponse().getEntity());
- }
- assertNull(exceptionMessage);
+
+ TestUtils.normalizeCompositeNode(prepareCnSn("normalize:node:module"), modules, schemaNodePath);
}
@Test
public void namespaceValidModuleNameTest() {
- String exceptionMessage = null;
- try {
- TestUtils.normalizeCompositeNode(prepareCnSn("normalize-node-module"), modules, schemaNodePath);
- } catch (ResponseException e) {
- exceptionMessage = String.valueOf(e.getResponse().getEntity());
- }
- assertNull(exceptionMessage);
+
+ TestUtils.normalizeCompositeNode(prepareCnSn("normalize-node-module"), modules, schemaNodePath);
}
private CompositeNode prepareCnSn(String namespace) {
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.FileNotFoundException;
import org.junit.rules.ExpectedException;
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.RestconfDocumentedException;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public class RestGetAugmentedElementWhenEqualNamesTest {
-
+
private static ControllerContext controllerContext = ControllerContext.getInstance();
-
+
@Rule
public ExpectedException exception = ExpectedException.none();
-
+
@BeforeClass
public static void init() throws FileNotFoundException {
SchemaContext schemaContextTestModule = TestUtils.loadSchemaContext("/common/augment/yang");
iiWithData = controllerContext.toInstanceIdentifier("main:cont/augment-main-b:cont1");
assertEquals("ns:augment:main:b", iiWithData.getSchemaNode().getQName().getNamespace().toString());
}
-
+
@Test
public void nodeWithoutNamespaceHasMoreAugments() {
- boolean exceptionCaught = false;
try {
controllerContext.toInstanceIdentifier("main:cont/cont1");
- } catch (ResponseException e) {
- assertTrue(((String) e.getResponse().getEntity()).contains("is added as augment from more than one module"));
- exceptionCaught = true;
+ fail( "Expected exception" );
+ } catch (RestconfDocumentedException e) {
+ assertTrue(e.getErrors().get( 0 ).getErrorMessage().contains(
+ "is added as augment from more than one module"));
}
- assertTrue(exceptionCaught);
}
-
}
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.core.api.mount.MountService;
import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
JsonToCompositeNodeProvider.INSTANCE);
+ resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
return resourceConfig;
}
/**
* MountPoint test. URI represents mount point.
- *
+ *
* Slashes in URI behind mount point. lst1 element with key
* GigabitEthernet0%2F0%2F0%2F0 (GigabitEthernet0/0/0/0) is requested via
* GET HTTP operation. It is tested whether %2F character is replaced with
* simple / in InstanceIdentifier parameter in method
* {@link BrokerFacade#readConfigurationDataBehindMountPoint(MountInstance, InstanceIdentifier)}
* which is called in method {@link RestconfImpl#readConfigurationData}
- *
- *
+ *
+ *
* @throws ParseException
*/
@Test
import org.opendaylight.controller.sal.core.api.mount.MountService;
import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import com.google.common.util.concurrent.Futures;
+
public class RestPostOperationTest extends JerseyTest {
private static String xmlDataAbsolutePath;
resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
JsonToCompositeNodeProvider.INSTANCE);
+ resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
return resourceConfig;
}
assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
uri = "/operations/test-module:rpc-wrongtest";
- assertEquals(404, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
+ assertEquals(400, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
}
@Test
private void mockInvokeRpc(CompositeNode result, boolean sucessful) {
RpcResult<CompositeNode> rpcResult = new DummyRpcResult.Builder<CompositeNode>().result(result)
.isSuccessful(sucessful).build();
- when(brokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenReturn(rpcResult);
+ when(brokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class)))
+ .thenReturn(Futures.<RpcResult<CompositeNode>>immediateFuture( rpcResult ));
}
private void mockCommitConfigurationDataPostMethod(TransactionStatus statusName) {
--- /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.impl.test;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.api.Draft02;
+import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.io.ByteStreams;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+
+/**
+ * Unit tests for RestconfDocumentedExceptionMapper.
+ *
+ * @author Thomas Pantelis
+ */
+public class RestconfDocumentedExceptionMapperTest extends JerseyTest {
+
+ interface ErrorInfoVerifier {
+ void verifyXML( Node errorInfoNode );
+ void verifyJson( JsonElement errorInfoElement );
+ }
+
+ static class ComplexErrorInfoVerifier implements ErrorInfoVerifier {
+
+ Map<String, String> expErrorInfo;
+
+ public ComplexErrorInfoVerifier( Map<String, String> expErrorInfo ) {
+ this.expErrorInfo = expErrorInfo;
+ }
+
+ @Override
+ public void verifyXML( Node errorInfoNode ) {
+
+ Map<String, String> mutableExpMap = Maps.newHashMap( expErrorInfo );
+ NodeList childNodes = errorInfoNode.getChildNodes();
+ for( int i = 0; i < childNodes.getLength(); i++ ) {
+ Node child = childNodes.item( i );
+ if( child instanceof Element ) {
+ String expValue = mutableExpMap.remove( child.getNodeName() );
+ assertNotNull( "Found unexpected \"error-info\" child node: " +
+ child.getNodeName(), expValue );
+ assertEquals( "Text content for \"error-info\" child node " +
+ child.getNodeName(), expValue, child.getTextContent() );
+ }
+ }
+
+ if( !mutableExpMap.isEmpty() ) {
+ fail( "Missing \"error-info\" child nodes: " + mutableExpMap );
+ }
+ }
+
+ @Override
+ public void verifyJson( JsonElement errorInfoElement ) {
+
+ assertTrue( "\"error-info\" Json element is not an Object",
+ errorInfoElement.isJsonObject() );
+
+ Map<String, String> actualErrorInfo = Maps.newHashMap();
+ for( Entry<String, JsonElement> entry: errorInfoElement.getAsJsonObject().entrySet() ) {
+ String leafName = entry.getKey();
+ JsonElement leafElement = entry.getValue();
+ actualErrorInfo.put( leafName, leafElement.getAsString() );
+ }
+
+ Map<String, String> mutableExpMap = Maps.newHashMap( expErrorInfo );
+ for( Entry<String,String> actual: actualErrorInfo.entrySet() ) {
+ String expValue = mutableExpMap.remove( actual.getKey() );
+ assertNotNull( "Found unexpected \"error-info\" child node: " +
+ actual.getKey(), expValue );
+ assertEquals( "Text content for \"error-info\" child node " +
+ actual.getKey(), expValue, actual.getValue() );
+ }
+
+ if( !mutableExpMap.isEmpty() ) {
+ fail( "Missing \"error-info\" child nodes: " + mutableExpMap );
+ }
+ }
+ }
+
+ static class SimpleErrorInfoVerifier implements ErrorInfoVerifier {
+
+ String expTextContent;
+
+ public SimpleErrorInfoVerifier( String expErrorInfo ) {
+ this.expTextContent = expErrorInfo;
+ }
+
+ void verifyContent( String actualContent ) {
+ assertNotNull( "Actual \"error-info\" text content is null", actualContent );
+ assertTrue( "", actualContent.contains( expTextContent ) );
+ }
+
+ @Override
+ public void verifyXML( Node errorInfoNode ) {
+ verifyContent( errorInfoNode.getTextContent() );
+ }
+
+ @Override
+ public void verifyJson( JsonElement errorInfoElement ) {
+ verifyContent( errorInfoElement.getAsString() );
+ }
+ }
+
+ static RestconfService mockRestConf = mock( RestconfService.class );
+
+ static XPath XPATH = XPathFactory.newInstance().newXPath();
+ static XPathExpression ERROR_LIST;
+ static XPathExpression ERROR_TYPE;
+ static XPathExpression ERROR_TAG;
+ static XPathExpression ERROR_MESSAGE;
+ static XPathExpression ERROR_APP_TAG;
+ static XPathExpression ERROR_INFO;
+
+ @BeforeClass
+ public static void init() throws Exception {
+ ControllerContext.getInstance().setGlobalSchema( TestUtils.loadSchemaContext("/modules") );
+
+ NamespaceContext nsContext = new NamespaceContext() {
+ @Override
+ public Iterator getPrefixes( String namespaceURI ) {
+ return null;
+ }
+
+ @Override
+ public String getPrefix( String namespaceURI ) {
+ return null;
+ }
+
+ @Override
+ public String getNamespaceURI( String prefix ) {
+ return "ietf-restconf".equals( prefix ) ? Draft02.RestConfModule.NAMESPACE : null;
+ }
+ };
+
+ XPATH.setNamespaceContext( nsContext );
+ ERROR_LIST = XPATH.compile( "ietf-restconf:errors/ietf-restconf:error" );
+ ERROR_TYPE = XPATH.compile( "ietf-restconf:error-type" );
+ ERROR_TAG = XPATH.compile( "ietf-restconf:error-tag" );
+ ERROR_MESSAGE = XPATH.compile( "ietf-restconf:error-message" );
+ ERROR_APP_TAG = XPATH.compile( "ietf-restconf:error-app-tag" );
+ ERROR_INFO = XPATH.compile( "ietf-restconf:error-info" );
+ }
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ reset( mockRestConf );
+ super.setUp();
+ }
+
+ @Override
+ protected Application configure() {
+ ResourceConfig resourceConfig = new ResourceConfig();
+ resourceConfig = resourceConfig.registerInstances( mockRestConf, StructuredDataToXmlProvider.INSTANCE,
+ StructuredDataToJsonProvider.INSTANCE );
+ resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
+ return resourceConfig;
+ }
+
+ void stageMockEx( RestconfDocumentedException ex ) {
+ reset( mockRestConf );
+ when( mockRestConf.readOperationalData( any( String.class ) ) ).thenThrow( ex );
+ }
+
+ void testJsonResponse( RestconfDocumentedException ex, Status expStatus, ErrorType expErrorType,
+ ErrorTag expErrorTag, String expErrorMessage, String expErrorAppTag,
+ ErrorInfoVerifier errorInfoVerifier ) throws Exception {
+
+ stageMockEx( ex );
+
+ Response resp = target("/operational/foo").request( MediaType.APPLICATION_JSON ).get();
+
+ InputStream stream = verifyResponse( resp, MediaType.APPLICATION_JSON, expStatus );
+
+ verifyJsonResponseBody( stream, expErrorType, expErrorTag, expErrorMessage,
+ expErrorAppTag, errorInfoVerifier );
+ }
+
+ @Test
+ public void testToJsonResponseWithMessageOnly() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error" ), Status.INTERNAL_SERVER_ERROR,
+ ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, "mock error", null, null );
+
+ // To test verification code
+// String json =
+// "{ errors: {" +
+// " error: [{" +
+// " error-tag : \"operation-failed\"" +
+// " ,error-type : \"application\"" +
+// " ,error-message : \"An error occurred\"" +
+// " ,error-info : {" +
+// " session-id: \"123\"" +
+// " ,address: \"1.2.3.4\"" +
+// " }" +
+// " }]" +
+// " }" +
+// "}";
+//
+// verifyJsonResponseBody( new java.io.StringBufferInputStream(json ), ErrorType.APPLICATION,
+// ErrorTag.OPERATION_FAILED, "An error occurred", null,
+// com.google.common.collect.ImmutableMap.of( "session-id", "123", "address", "1.2.3.4" ) );
+ }
+
+ @Test
+ public void testToJsonResponseWithInUseErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.IN_USE ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.IN_USE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithInvalidValueErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.RPC,
+ ErrorTag.INVALID_VALUE ),
+ Status.BAD_REQUEST, ErrorType.RPC,
+ ErrorTag.INVALID_VALUE, "mock error", null, null );
+
+ }
+
+ @Test
+ public void testToJsonResponseWithTooBigErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.TRANSPORT,
+ ErrorTag.TOO_BIG ),
+ Status.REQUEST_ENTITY_TOO_LARGE, ErrorType.TRANSPORT,
+ ErrorTag.TOO_BIG, "mock error", null, null );
+
+ }
+
+ @Test
+ public void testToJsonResponseWithMissingAttributeErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.MISSING_ATTRIBUTE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.MISSING_ATTRIBUTE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithBadAttributeErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.BAD_ATTRIBUTE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.BAD_ATTRIBUTE, "mock error", null, null );
+ }
+ @Test
+ public void testToJsonResponseWithUnknownAttributeErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_ATTRIBUTE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_ATTRIBUTE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithBadElementErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.BAD_ELEMENT ),
+ Status.BAD_REQUEST,
+ ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithUnknownElementErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_ELEMENT ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_ELEMENT, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithUnknownNamespaceErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_NAMESPACE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_NAMESPACE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithMalformedMessageErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.MALFORMED_MESSAGE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.MALFORMED_MESSAGE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithAccessDeniedErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.ACCESS_DENIED ),
+ Status.FORBIDDEN, ErrorType.PROTOCOL,
+ ErrorTag.ACCESS_DENIED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithLockDeniedErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.LOCK_DENIED ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.LOCK_DENIED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithResourceDeniedErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.RESOURCE_DENIED ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.RESOURCE_DENIED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithRollbackFailedErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.ROLLBACK_FAILED ),
+ Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+ ErrorTag.ROLLBACK_FAILED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithDataExistsErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.DATA_EXISTS ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.DATA_EXISTS, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithDataMissingErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.DATA_MISSING ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.DATA_MISSING, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithOperationNotSupportedErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.OPERATION_NOT_SUPPORTED ),
+ Status.NOT_IMPLEMENTED, ErrorType.PROTOCOL,
+ ErrorTag.OPERATION_NOT_SUPPORTED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithOperationFailedErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.OPERATION_FAILED ),
+ Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+ ErrorTag.OPERATION_FAILED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithPartialOperationErrorTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.PARTIAL_OPERATION ),
+ Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+ ErrorTag.PARTIAL_OPERATION, "mock error", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithErrorAppTag() throws Exception {
+
+ testJsonResponse( new RestconfDocumentedException( new RestconfError(
+ ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+ "mock error", "mock-app-tag" ) ),
+ Status.BAD_REQUEST, ErrorType.APPLICATION,
+ ErrorTag.INVALID_VALUE, "mock error", "mock-app-tag", null );
+ }
+
+ @Test
+ public void testToJsonResponseWithMultipleErrors() throws Exception {
+
+ List<RestconfError> errorList = Arrays.asList(
+ new RestconfError( ErrorType.APPLICATION, ErrorTag.LOCK_DENIED, "mock error1" ),
+ new RestconfError( ErrorType.RPC, ErrorTag.ROLLBACK_FAILED, "mock error2" ) );
+ stageMockEx( new RestconfDocumentedException( errorList ) );
+
+ Response resp = target("/operational/foo").request( MediaType.APPLICATION_JSON ).get();
+
+ InputStream stream = verifyResponse( resp, MediaType.APPLICATION_JSON, Status.CONFLICT );
+
+ JsonArray arrayElement = parseJsonErrorArrayElement( stream );
+
+ assertEquals( "\"error\" Json array element length", 2, arrayElement.size() );
+
+ verifyJsonErrorNode( arrayElement.get( 0 ), ErrorType.APPLICATION, ErrorTag.LOCK_DENIED,
+ "mock error1", null, null );
+
+ verifyJsonErrorNode( arrayElement.get( 1 ), ErrorType.RPC, ErrorTag.ROLLBACK_FAILED,
+ "mock error2", null, null );
+ }
+
+ @Test
+ public void testToJsonResponseWithErrorInfo() throws Exception {
+
+ String errorInfo = "<address>1.2.3.4</address> <session-id>123</session-id>";
+ testJsonResponse( new RestconfDocumentedException( new RestconfError(
+ ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+ "mock error", "mock-app-tag", errorInfo ) ),
+ Status.BAD_REQUEST, ErrorType.APPLICATION,
+ ErrorTag.INVALID_VALUE, "mock error", "mock-app-tag",
+ new ComplexErrorInfoVerifier( ImmutableMap.of(
+ "session-id", "123", "address", "1.2.3.4" ) ) );
+ }
+
+ @Test
+ public void testToJsonResponseWithExceptionCause() throws Exception {
+
+ Exception cause = new Exception( "mock exception cause" );
+ testJsonResponse( new RestconfDocumentedException( "mock error", cause ),
+ Status.INTERNAL_SERVER_ERROR, ErrorType.APPLICATION,
+ ErrorTag.OPERATION_FAILED, "mock error", null,
+ new SimpleErrorInfoVerifier( cause.getMessage() ) );
+ }
+
+ void testXMLResponse( RestconfDocumentedException ex, Status expStatus, ErrorType expErrorType,
+ ErrorTag expErrorTag, String expErrorMessage,
+ String expErrorAppTag, ErrorInfoVerifier errorInfoVerifier ) throws Exception
+ {
+ stageMockEx( ex );
+
+ Response resp = target("/operational/foo").request( MediaType.APPLICATION_XML ).get();
+
+ InputStream stream = verifyResponse( resp, MediaType.APPLICATION_XML, expStatus );
+
+ verifyXMLResponseBody( stream, expErrorType, expErrorTag, expErrorMessage,
+ expErrorAppTag, errorInfoVerifier );
+ }
+
+ @Test
+ public void testToXMLResponseWithMessageOnly() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error" ), Status.INTERNAL_SERVER_ERROR,
+ ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, "mock error", null, null );
+
+ // To test verification code
+// String xml =
+// "<errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\">"+
+// " <error>" +
+// " <error-type>application</error-type>"+
+// " <error-tag>operation-failed</error-tag>"+
+// " <error-message>An error occurred</error-message>"+
+// " <error-info>" +
+// " <session-id>123</session-id>" +
+// " <address>1.2.3.4</address>" +
+// " </error-info>" +
+// " </error>" +
+// "</errors>";
+//
+// verifyXMLResponseBody( new java.io.StringBufferInputStream(xml), ErrorType.APPLICATION,
+// ErrorTag.OPERATION_FAILED, "An error occurred", null,
+// com.google.common.collect.ImmutableMap.of( "session-id", "123", "address", "1.2.3.4" ) );
+ }
+
+ @Test
+ public void testToXMLResponseWithInUseErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.IN_USE ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.IN_USE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithInvalidValueErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.RPC,
+ ErrorTag.INVALID_VALUE ),
+ Status.BAD_REQUEST, ErrorType.RPC,
+ ErrorTag.INVALID_VALUE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithTooBigErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.TRANSPORT,
+ ErrorTag.TOO_BIG ),
+ Status.REQUEST_ENTITY_TOO_LARGE, ErrorType.TRANSPORT,
+ ErrorTag.TOO_BIG, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithMissingAttributeErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.MISSING_ATTRIBUTE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.MISSING_ATTRIBUTE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithBadAttributeErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.BAD_ATTRIBUTE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.BAD_ATTRIBUTE, "mock error", null, null );
+ }
+ @Test
+ public void testToXMLResponseWithUnknownAttributeErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_ATTRIBUTE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_ATTRIBUTE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithBadElementErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.BAD_ELEMENT ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.BAD_ELEMENT, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithUnknownElementErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_ELEMENT ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_ELEMENT, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithUnknownNamespaceErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_NAMESPACE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.UNKNOWN_NAMESPACE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithMalformedMessageErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.MALFORMED_MESSAGE ),
+ Status.BAD_REQUEST, ErrorType.PROTOCOL,
+ ErrorTag.MALFORMED_MESSAGE, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithAccessDeniedErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.ACCESS_DENIED ),
+ Status.FORBIDDEN, ErrorType.PROTOCOL,
+ ErrorTag.ACCESS_DENIED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithLockDeniedErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.LOCK_DENIED ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.LOCK_DENIED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithResourceDeniedErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.RESOURCE_DENIED ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.RESOURCE_DENIED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithRollbackFailedErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.ROLLBACK_FAILED ),
+ Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+ ErrorTag.ROLLBACK_FAILED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithDataExistsErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.DATA_EXISTS ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.DATA_EXISTS, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithDataMissingErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.DATA_MISSING ),
+ Status.CONFLICT, ErrorType.PROTOCOL,
+ ErrorTag.DATA_MISSING, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithOperationNotSupportedErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.OPERATION_NOT_SUPPORTED ),
+ Status.NOT_IMPLEMENTED, ErrorType.PROTOCOL,
+ ErrorTag.OPERATION_NOT_SUPPORTED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithOperationFailedErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.OPERATION_FAILED ),
+ Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+ ErrorTag.OPERATION_FAILED, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithPartialOperationErrorTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( "mock error", ErrorType.PROTOCOL,
+ ErrorTag.PARTIAL_OPERATION ),
+ Status.INTERNAL_SERVER_ERROR, ErrorType.PROTOCOL,
+ ErrorTag.PARTIAL_OPERATION, "mock error", null, null );
+ }
+
+ @Test
+ public void testToXMLResponseWithErrorAppTag() throws Exception {
+
+ testXMLResponse( new RestconfDocumentedException( new RestconfError(
+ ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+ "mock error", "mock-app-tag" ) ),
+ Status.BAD_REQUEST, ErrorType.APPLICATION,
+ ErrorTag.INVALID_VALUE, "mock error", "mock-app-tag", null );
+ }
+
+ @Test
+ public void testToXMLResponseWithErrorInfo() throws Exception {
+
+ String errorInfo = "<address>1.2.3.4</address> <session-id>123</session-id>";
+ testXMLResponse( new RestconfDocumentedException( new RestconfError(
+ ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
+ "mock error", "mock-app-tag", errorInfo ) ),
+ Status.BAD_REQUEST, ErrorType.APPLICATION,
+ ErrorTag.INVALID_VALUE, "mock error", "mock-app-tag",
+ new ComplexErrorInfoVerifier( ImmutableMap.of(
+ "session-id", "123", "address", "1.2.3.4" ) ) );
+ }
+
+ @Test
+ public void testToXMLResponseWithExceptionCause() throws Exception {
+
+ Exception cause = new Exception( "mock exception cause" );
+ testXMLResponse( new RestconfDocumentedException( "mock error", cause ),
+ Status.INTERNAL_SERVER_ERROR, ErrorType.APPLICATION,
+ ErrorTag.OPERATION_FAILED, "mock error", null,
+ new SimpleErrorInfoVerifier( cause.getMessage() ) );
+ }
+
+ @Test
+ public void testToXMLResponseWithMultipleErrors() throws Exception {
+
+ List<RestconfError> errorList = Arrays.asList(
+ new RestconfError( ErrorType.APPLICATION, ErrorTag.LOCK_DENIED, "mock error1" ),
+ new RestconfError( ErrorType.RPC, ErrorTag.ROLLBACK_FAILED, "mock error2" ) );
+ stageMockEx( new RestconfDocumentedException( errorList ) );
+
+ Response resp = target("/operational/foo").request( MediaType.APPLICATION_XML ).get();
+
+ InputStream stream = verifyResponse( resp, MediaType.APPLICATION_XML, Status.CONFLICT );
+
+ Document doc = parseXMLDocument( stream );
+
+ NodeList children = getXMLErrorList( doc, 2 );
+
+ verifyXMLErrorNode( children.item( 0 ), ErrorType.APPLICATION, ErrorTag.LOCK_DENIED,
+ "mock error1", null, null );
+
+ verifyXMLErrorNode( children.item( 1 ), ErrorType.RPC, ErrorTag.ROLLBACK_FAILED,
+ "mock error2", null, null );
+ }
+
+ @Test
+ public void testToResponseWithAcceptHeader() throws Exception {
+
+ stageMockEx( new RestconfDocumentedException( "mock error" ) );
+
+ Response resp = target("/operational/foo")
+ .request().header( "Accept", MediaType.APPLICATION_JSON ).get();
+
+ InputStream stream = verifyResponse( resp, MediaType.APPLICATION_JSON,
+ Status.INTERNAL_SERVER_ERROR );
+
+ verifyJsonResponseBody( stream, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, "mock error",
+ null, null );
+ }
+
+ @Test
+ public void testToResponseWithStatusOnly() throws Exception {
+
+ // The StructuredDataToJsonProvider should throw a RestconfDocumentedException with no data
+
+ when( mockRestConf.readOperationalData( any( String.class ) ) )
+ .thenReturn( new StructuredData( null, null, null ) );
+
+ Response resp = target("/operational/foo").request( MediaType.APPLICATION_JSON ).get();
+
+ verifyResponse( resp, MediaType.TEXT_PLAIN, Status.NOT_FOUND );
+ }
+
+ InputStream verifyResponse( Response resp, String expMediaType, Status expStatus ) {
+ assertEquals( "getMediaType", MediaType.valueOf( expMediaType ), resp.getMediaType() );
+ assertEquals( "getStatus", expStatus.getStatusCode(), resp.getStatus() );
+
+ Object entity = resp.getEntity();
+ assertEquals( "Response entity", true, entity instanceof InputStream );
+ InputStream stream = (InputStream)entity;
+ return stream;
+ }
+
+ void verifyJsonResponseBody( InputStream stream, ErrorType expErrorType, ErrorTag expErrorTag,
+ String expErrorMessage, String expErrorAppTag,
+ ErrorInfoVerifier errorInfoVerifier ) throws Exception {
+
+ JsonArray arrayElement = parseJsonErrorArrayElement( stream );
+
+ assertEquals( "\"error\" Json array element length", 1, arrayElement.size() );
+
+ verifyJsonErrorNode( arrayElement.get( 0 ), expErrorType, expErrorTag, expErrorMessage,
+ expErrorAppTag, errorInfoVerifier );
+ }
+
+ private JsonArray parseJsonErrorArrayElement( InputStream stream ) throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ByteStreams.copy( stream, bos );
+
+ System.out.println("JSON: "+bos.toString());
+
+ JsonParser parser = new JsonParser();
+ JsonElement rootElement;
+
+ try {
+ rootElement = parser.parse(
+ new InputStreamReader( new ByteArrayInputStream( bos.toByteArray() ) ) );
+ }
+ catch( Exception e ) {
+ throw new IllegalArgumentException( "Invalid JSON response:\n" + bos.toString(), e );
+ }
+
+ assertTrue( "Root element of Json is not an Object", rootElement.isJsonObject() );
+
+ Set<Entry<String, JsonElement>> errorsEntrySet = rootElement.getAsJsonObject().entrySet();
+ assertEquals( "Json Object element set count", 1, errorsEntrySet.size() );
+
+ Entry<String, JsonElement> errorsEntry = errorsEntrySet.iterator().next();
+ JsonElement errorsElement = errorsEntry.getValue();
+ assertEquals( "First Json element name", "errors", errorsEntry.getKey() );
+ assertTrue( "\"errors\" Json element is not an Object", errorsElement.isJsonObject() );
+
+ Set<Entry<String, JsonElement>> errorListEntrySet = errorsElement.getAsJsonObject().entrySet();
+ assertEquals( "Root \"errors\" element child count", 1, errorListEntrySet.size() );
+
+ JsonElement errorListElement = errorListEntrySet.iterator().next().getValue();
+ assertEquals( "\"errors\" child Json element name", "error",
+ errorListEntrySet.iterator().next().getKey() );
+ assertTrue( "\"error\" Json element is not an Array", errorListElement.isJsonArray() );
+
+ return errorListElement.getAsJsonArray();
+ }
+
+ void verifyJsonErrorNode( JsonElement errorEntryElement, ErrorType expErrorType, ErrorTag expErrorTag,
+ String expErrorMessage, String expErrorAppTag,
+ ErrorInfoVerifier errorInfoVerifier ) {
+
+ JsonElement errorInfoElement = null;
+ Map<String, String> actualErrorInfo = null;
+ Map<String, String> leafMap = Maps.newHashMap();
+ for( Entry<String, JsonElement> entry: errorEntryElement.getAsJsonObject().entrySet() ) {
+ String leafName = entry.getKey();
+ JsonElement leafElement = entry.getValue();
+
+ if( "error-info".equals( leafName ) ) {
+ assertNotNull( "Found unexpected \"error-info\" element", errorInfoVerifier );
+ errorInfoElement = leafElement;
+ }
+ else {
+ assertTrue( "\"error\" leaf Json element " + leafName +
+ " is not a Primitive", leafElement.isJsonPrimitive() );
+
+ leafMap.put( leafName, leafElement.getAsString() );
+ }
+ }
+
+ assertEquals( "error-type", expErrorType.getErrorTypeTag(), leafMap.remove( "error-type" ) );
+ assertEquals( "error-tag", expErrorTag.getTagValue(), leafMap.remove( "error-tag" ) );
+
+ verifyOptionalJsonLeaf( leafMap.remove( "error-message" ), expErrorMessage, "error-message" );
+ verifyOptionalJsonLeaf( leafMap.remove( "error-app-tag" ), expErrorAppTag, "error-app-tag" );
+
+ if( !leafMap.isEmpty() ) {
+ fail( "Found unexpected Json leaf elements for \"error\" element: " + leafMap );
+ }
+
+ if( errorInfoVerifier != null ) {
+ assertNotNull( "Missing \"error-info\" element", errorInfoElement );
+ errorInfoVerifier.verifyJson( errorInfoElement );
+ }
+ }
+
+ void verifyOptionalJsonLeaf( String actualValue, String expValue, String tagName ) {
+ if( expValue != null ) {
+ assertEquals( tagName, expValue, actualValue );
+ }
+ else {
+ assertNull( "Found unexpected \"error\" leaf entry for: " + tagName, actualValue );
+ }
+ }
+
+ void verifyXMLResponseBody( InputStream stream, ErrorType expErrorType, ErrorTag expErrorTag,
+ String expErrorMessage, String expErrorAppTag,
+ ErrorInfoVerifier errorInfoVerifier )
+ throws Exception {
+
+ Document doc = parseXMLDocument( stream );
+
+ NodeList children = getXMLErrorList( doc, 1 );
+
+ verifyXMLErrorNode( children.item( 0 ), expErrorType, expErrorTag, expErrorMessage,
+ expErrorAppTag, errorInfoVerifier );
+ }
+
+ private Document parseXMLDocument( InputStream stream ) throws IOException {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setCoalescing(true);
+ factory.setIgnoringElementContentWhitespace(true);
+ factory.setIgnoringComments(true);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ByteStreams.copy( stream, bos );
+
+ System.out.println("XML: "+bos.toString());
+
+ Document doc = null;
+ try {
+ doc = factory.newDocumentBuilder().parse( new ByteArrayInputStream( bos.toByteArray() ) );
+ }
+ catch( Exception e ) {
+ throw new IllegalArgumentException( "Invalid XML response:\n" + bos.toString(), e );
+ }
+ return doc;
+ }
+
+ void verifyXMLErrorNode( Node errorNode, ErrorType expErrorType, ErrorTag expErrorTag,
+ String expErrorMessage, String expErrorAppTag,
+ ErrorInfoVerifier errorInfoVerifier ) throws Exception {
+
+ String errorType = (String)ERROR_TYPE.evaluate( errorNode, XPathConstants.STRING );
+ assertEquals( "error-type", expErrorType.getErrorTypeTag(), errorType );
+
+ String errorTag = (String)ERROR_TAG.evaluate( errorNode, XPathConstants.STRING );
+ assertEquals( "error-tag", expErrorTag.getTagValue(), errorTag );
+
+ verifyOptionalXMLLeaf( errorNode, ERROR_MESSAGE, expErrorMessage, "error-message" );
+ verifyOptionalXMLLeaf( errorNode, ERROR_APP_TAG, expErrorAppTag, "error-app-tag" );
+
+ Node errorInfoNode = (Node)ERROR_INFO.evaluate( errorNode, XPathConstants.NODE );
+ if( errorInfoVerifier != null ) {
+ assertNotNull( "Missing \"error-info\" node", errorInfoNode );
+
+ errorInfoVerifier.verifyXML( errorInfoNode );
+ }
+ else {
+ assertNull( "Found unexpected \"error-info\" node", errorInfoNode );
+ }
+ }
+
+ void verifyOptionalXMLLeaf( Node fromNode, XPathExpression xpath, String expValue,
+ String tagName ) throws Exception {
+ if( expValue != null ) {
+ String actual = (String)xpath.evaluate( fromNode, XPathConstants.STRING );
+ assertEquals( tagName, expValue, actual );
+ }
+ else {
+ assertNull( "Found unexpected \"error\" leaf entry for: " + tagName,
+ xpath.evaluate( fromNode, XPathConstants.NODE ) );
+ }
+ }
+
+ NodeList getXMLErrorList( Node fromNode, int count ) throws Exception {
+ NodeList errorList = (NodeList)ERROR_LIST.evaluate( fromNode, XPathConstants.NODESET );
+ assertNotNull( "Root errors node is empty", errorList );
+ assertEquals( "Root errors node child count", count, errorList.getLength() );
+ return errorList;
+ }
+}
--- /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.impl.test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.opendaylight.controller.sal.common.util.RpcErrors.getRpcError;
+
+import org.opendaylight.controller.sal.restconf.impl.RestconfError;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcError;
+
+/**
+ * Unit tests for RestconfError.
+ *
+ * @author Devin Avery
+ * @author Thomas Pantelis
+ *
+ */
+public class RestconfErrorTest {
+
+ static class Contains extends BaseMatcher<String> {
+
+ private final String text;
+
+ public Contains( String text ) {
+ this.text = text;
+ }
+
+ @Override
+ public void describeTo( Description desc ) {
+ desc.appendText( "contains " ).appendValue( text );
+ }
+
+ @Override
+ public boolean matches( Object arg ) {
+ return arg != null && arg.toString().contains( text );
+ }
+ }
+
+ @Test
+ public void testErrorTagValueOf()
+ {
+ assertEquals( ErrorTag.IN_USE,
+ ErrorTag.valueOfCaseInsensitive( ErrorTag.IN_USE.getTagValue() ) );
+ }
+
+ @Test
+ public void testErrorTagValueOfIsLowercase()
+ {
+ assertEquals( "in-use",
+ ErrorTag.IN_USE.getTagValue() );
+ }
+
+ @Test
+ public void testErrorTypeGetErrorTypeTagIsLowerCase()
+ {
+ assertEquals( ErrorType.APPLICATION.name().toLowerCase(),
+ ErrorType.APPLICATION.getErrorTypeTag() );
+ }
+
+ @Test
+ public void testErrorTypeValueOf()
+ {
+ assertEquals( ErrorType.APPLICATION,
+ ErrorType.valueOfCaseInsensitive( ErrorType.APPLICATION.getErrorTypeTag() ) );
+ }
+
+ @Test
+ public void testErrorTagStatusCodes()
+ {
+ Map<String,Status> lookUpMap = new HashMap<String,Status>();
+
+ lookUpMap.put( "in-use", Status.fromStatusCode(409));
+ lookUpMap.put( "invalid-value", Status.fromStatusCode(400));
+ lookUpMap.put( "too-big", Status.fromStatusCode(413));
+ lookUpMap.put( "missing-attribute", Status.fromStatusCode(400));
+ lookUpMap.put( "bad-attribute", Status.fromStatusCode(400));
+ lookUpMap.put( "unknown-attribute", Status.fromStatusCode(400));
+ lookUpMap.put( "bad-element", Status.fromStatusCode(400));
+ lookUpMap.put( "unknown-element", Status.fromStatusCode(400));
+ lookUpMap.put( "unknown-namespace", Status.fromStatusCode(400));
+ lookUpMap.put( "access-denied", Status.fromStatusCode(403));
+ lookUpMap.put( "lock-denied", Status.fromStatusCode(409));
+ lookUpMap.put( "resource-denied", Status.fromStatusCode(409));
+ lookUpMap.put( "rollback-failed", Status.fromStatusCode(500));
+ lookUpMap.put( "data-exists", Status.fromStatusCode(409));
+ lookUpMap.put( "data-missing", Status.fromStatusCode(409));
+ lookUpMap.put( "operation-not-supported", Status.fromStatusCode(501));
+ lookUpMap.put( "operation-failed", Status.fromStatusCode(500));
+ lookUpMap.put( "partial-operation", Status.fromStatusCode(500));
+ lookUpMap.put( "malformed-message", Status.fromStatusCode(400));
+
+ for( ErrorTag tag : ErrorTag.values() )
+ {
+ Status expectedStatusCode = lookUpMap.get( tag.getTagValue() );
+ assertNotNull( "Failed to find " + tag.getTagValue(), expectedStatusCode );
+ assertEquals( "Status Code does not match", expectedStatusCode, tag.getStatusCode() );
+ }
+ }
+
+ @Test
+ public void testRestConfDocumentedException_NoCause()
+ {
+ String expectedMessage = "Message";
+ ErrorType expectedErrorType = ErrorType.RPC;
+ ErrorTag expectedErrorTag = ErrorTag.IN_USE;
+ RestconfError e =
+ new RestconfError( expectedErrorType,
+ expectedErrorTag, expectedMessage );
+
+ validateRestConfError(expectedMessage, expectedErrorType, expectedErrorTag,
+ null, (String)null, e);
+ }
+
+ @Test
+ public void testRestConfDocumentedException_WithAppTag()
+ {
+ String expectedMessage = "Message";
+ ErrorType expectedErrorType = ErrorType.RPC;
+ ErrorTag expectedErrorTag = ErrorTag.IN_USE;
+ String expectedErrorAppTag = "application.tag";
+
+ RestconfError e =
+ new RestconfError( expectedErrorType,
+ expectedErrorTag, expectedMessage, expectedErrorAppTag );
+
+ validateRestConfError(expectedMessage, expectedErrorType, expectedErrorTag,
+ expectedErrorAppTag, (String)null, e);
+ }
+
+ @Test
+ public void testRestConfDocumentedException_WithAppTagErrorInfo()
+ {
+ String expectedMessage = "Message";
+ ErrorType expectedErrorType = ErrorType.RPC;
+ ErrorTag expectedErrorTag = ErrorTag.IN_USE;
+ String expectedErrorAppTag = "application.tag";
+ String errorInfo = "<extra><sessionid>session.id</sessionid></extra>";
+
+ RestconfError e = new RestconfError( expectedErrorType,
+ expectedErrorTag,
+ expectedMessage,
+ expectedErrorAppTag,
+ errorInfo );
+
+ validateRestConfError(expectedMessage, expectedErrorType, expectedErrorTag,
+ expectedErrorAppTag, errorInfo, e);
+ }
+
+ @Test
+ public void testRestConfErrorWithRpcError() {
+
+ // All fields set
+ RpcError rpcError = getRpcError( "mock app-tag", ErrorTag.BAD_ATTRIBUTE.getTagValue(),
+ "mock error-info", RpcError.ErrorSeverity.ERROR,
+ "mock error-message", RpcError.ErrorType.PROTOCOL,
+ new Exception( "mock cause" ) );
+
+ validateRestConfError( "mock error-message", ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE,
+ "mock app-tag", "mock error-info",
+ new RestconfError( rpcError ) );
+
+ // All fields set except 'info' - expect error-info set to 'cause'
+ rpcError = getRpcError( "mock app-tag", ErrorTag.BAD_ATTRIBUTE.getTagValue(),
+ null, RpcError.ErrorSeverity.ERROR,
+ "mock error-message", RpcError.ErrorType.PROTOCOL,
+ new Exception( "mock cause" ) );
+
+ validateRestConfError( "mock error-message", ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE,
+ "mock app-tag", new Contains( "mock cause" ),
+ new RestconfError( rpcError ) );
+
+ // Some fields set - expect error-info set to ErrorSeverity
+ rpcError = getRpcError( null, ErrorTag.ACCESS_DENIED.getTagValue(),
+ null, RpcError.ErrorSeverity.ERROR,
+ null, RpcError.ErrorType.RPC, null );
+
+ validateRestConfError( null, ErrorType.RPC, ErrorTag.ACCESS_DENIED,
+ null, "<severity>error</severity>",
+ new RestconfError( rpcError ) );
+
+ // 'tag' field not mapped to ErrorTag - expect error-tag set to OPERATION_FAILED
+ rpcError = getRpcError( null, "not mapped",
+ null, RpcError.ErrorSeverity.WARNING,
+ null, RpcError.ErrorType.TRANSPORT, null );
+
+ validateRestConfError( null, ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED,
+ null, "<severity>warning</severity>",
+ new RestconfError( rpcError ) );
+
+ // No fields set - edge case
+ rpcError = getRpcError( null, null, null, null, null, null, null );
+
+ validateRestConfError( null, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED,
+ null, (String)null, new RestconfError( rpcError ) );
+ }
+
+ private void validateRestConfError(String expectedMessage, ErrorType expectedErrorType,
+ ErrorTag expectedErrorTag, String expectedErrorAppTag, String errorInfo, RestconfError e) {
+
+ validateRestConfError( expectedMessage, expectedErrorType, expectedErrorTag,
+ expectedErrorAppTag, equalTo( errorInfo ), e );
+ }
+
+ private void validateRestConfError(String expectedMessage, ErrorType expectedErrorType,
+ ErrorTag expectedErrorTag, String expectedErrorAppTag,
+ Matcher<String> errorInfoMatcher, RestconfError e) {
+
+ assertEquals( "getErrorMessage", expectedMessage, e.getErrorMessage() );
+ assertEquals( "getErrorType", expectedErrorType, e.getErrorType() );
+ assertEquals( "getErrorTag", expectedErrorTag, e.getErrorTag() );
+ assertEquals( "getErrorAppTag", expectedErrorAppTag, e.getErrorAppTag() );
+ assertThat( "getErrorInfo", e.getErrorInfo(), errorInfoMatcher );
+ e.toString(); // really just checking for NPE etc. Don't care about contents.
+ }
+}
*/
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));
}
+
}
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.RestconfDocumentedException;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@Test
public void testToInstanceIdentifierListWithNullKey() {
- exception.expect(ResponseException.class);
- exception.expectMessage("HTTP 400 Bad Request");
+ exception.expect(RestconfDocumentedException.class);
controllerContext.toInstanceIdentifier("simple-nodes:user/null/boo");
}
@Test
public void testToInstanceIdentifierListWithMissingKey() {
- exception.expect(ResponseException.class);
- exception.expectMessage("HTTP 400 Bad Request");
+ exception.expect(RestconfDocumentedException.class);
controllerContext.toInstanceIdentifier("simple-nodes:user/foo");
}
@Test
public void testToInstanceIdentifierChoiceException() {
- exception.expect(ResponseException.class);
- exception.expectMessage("HTTP 400 Bad Request");
+ exception.expect(RestconfDocumentedException.class);
controllerContext.toInstanceIdentifier("simple-nodes:food/snack");
}
@Test
public void testToInstanceIdentifierCaseException() {
- exception.expect(ResponseException.class);
- exception.expectMessage("HTTP 400 Bad Request");
+ exception.expect(RestconfDocumentedException.class);
controllerContext.toInstanceIdentifier("simple-nodes:food/sports-arena");
}
@Test
public void testToInstanceIdentifierChoiceCaseException() {
- exception.expect(ResponseException.class);
- exception.expectMessage("HTTP 400 Bad Request");
+ exception.expect(RestconfDocumentedException.class);
controllerContext.toInstanceIdentifier("simple-nodes:food/snack/sports-arena");
}
-
+
@Test
public void testToInstanceIdentifierWithoutNode() {
- exception.expect(ResponseException.class);
- exception.expectMessage("HTTP 400 Bad Request");
+ exception.expect(RestconfDocumentedException.class);
controllerContext.toInstanceIdentifier("simple-nodes");
}
@Test
public void testMountPointWithoutMountService() throws FileNotFoundException {
- exception.expect(ResponseException.class);
- exception.expectMessage("HTTP 503 Service Unavailable");
-
+ exception.expect(RestconfDocumentedException.class);
+
controllerContext.setMountService(null);
InstanceIdWithSchemaNode instanceIdentifier = controllerContext
.toInstanceIdentifier("simple-nodes:users/yang-ext:mount/test-interface2:class/student/name");
}
-
+
@Test
public void testMountPointWithoutMountPointSchema() {
initMountService(false);
- exception.expect(ResponseException.class);
- exception.expectMessage("HTTP 400 Bad Request");
-
+ exception.expect(RestconfDocumentedException.class);
+
InstanceIdWithSchemaNode instanceIdentifier = controllerContext
.toInstanceIdentifier("simple-nodes:users/yang-ext:mount/test-interface2:class");
}
-
+
public void initMountService(boolean withSchema) {
MountService mountService = mock(MountService.class);
controllerContext.setMountService(mountService);
verifyCommonPartAOfXml(compNode, "", nameSpace);
}
- private void verifyNullAndEmptyStringSingleNode(CompositeNode compNode, String nameSpace) {
+ private void verifyNullAndEmptyStringSingleNode(final CompositeNode compNode, final String nameSpace) {
assertEquals("cont", compNode.getNodeType().getLocalName());
SimpleNode<?> lf2 = null;
SimpleNode<?> lf3 = null;
int found = 0;
- for (Node<?> child : compNode.getChildren()) {
+ for (Node<?> child : compNode.getValue()) {
if (found == 0x3)
break;
if (child instanceof SimpleNode<?>) {
String nameSpaceCont = "data:container:yang";
assertEquals(nameSpaceCont, compNode.getNodeType().getNamespace().toString());
assertEquals("cont", compNode.getNodeType().getLocalName());
- assertEquals(3, compNode.getChildren().size());
+ assertEquals(3, compNode.getValue().size());
CompositeNode lst1_1 = null;
CompositeNode lst1_2 = null;
int loopCount = 0;
- for (Node<?> node : compNode.getChildren()) {
+ for (Node<?> node : compNode.getValue()) {
if (node.getNodeType().getLocalName().equals("lf1")) {
assertEquals(nameSpaceList, node.getNodeType().getNamespace().toString());
assertTrue(node instanceof SimpleNode<?>);
// lst1_2
SimpleNode<?> lflst11 = null;
CompositeNode cont11 = null;
- for (Node<?> node : lst1_2.getChildren()) {
+ for (Node<?> node : lst1_2.getValue()) {
String nodeName = node.getNodeType().getLocalName();
if (nodeName.equals("lflst11")) {
assertTrue(node instanceof SimpleNode<?>);
}
assertEquals("221", lflst11.getValue());
- assertEquals(1, cont11.getChildren().size());
- assertTrue(cont11.getChildren().get(0) instanceof SimpleNode<?>);
- SimpleNode<?> cont11_lf111 = (SimpleNode<?>) cont11.getChildren().get(0);
+ assertEquals(1, cont11.getValue().size());
+ assertTrue(cont11.getValue().get(0) instanceof SimpleNode<?>);
+ SimpleNode<?> cont11_lf111 = (SimpleNode<?>) cont11.getValue().get(0);
assertEquals(nameSpaceCont, cont11_lf111.getNodeType().getNamespace().toString());
assertEquals("lf111", cont11_lf111.getNodeType().getLocalName());
assertEquals((short) 100, cont11_lf111.getValue());
SimpleNode<?> lflst1_2 = null;
CompositeNode lst1 = null;
int lflst1Count = 0;
- for (Node<?> node : compNode.getChildren()) {
+ for (Node<?> node : compNode.getValue()) {
if (node.getNodeType().getLocalName().equals("lf1")) {
assertTrue(node instanceof SimpleNode<?>);
lf1 = (SimpleNode<?>) node;
assertEquals("", lf1.getValue());
assertEquals("", lflst1_1.getValue());
assertEquals("", lflst1_2.getValue());
- assertEquals(1, lst1.getChildren().size());
- assertEquals("lf11", lst1.getChildren().get(0).getNodeType().getLocalName());
+ assertEquals(1, lst1.getValue().size());
+ assertEquals("lf11", lst1.getValue().get(0).getNodeType().getLocalName());
- assertTrue(lst1.getChildren().get(0) instanceof SimpleNode<?>);
- assertEquals("", lst1.getChildren().get(0).getValue());
+ assertTrue(lst1.getValue().get(0) instanceof SimpleNode<?>);
+ assertEquals("", lst1.getValue().get(0).getValue());
}
}
/**
- *
+ *
* Test case like <lf11 xmlns="namespace1"
* xmlns:x="namespace">identity</lf11>
*/
}
/**
- *
+ *
* Test case like <cont1 xmlns="namespace1"> <lf11
* xmlns:x="namespace">identity</lf11> </cont1>
*/
}
/**
- *
+ *
* Test case like <cont1 xmlns="namespace1" xmlns:x="namespace">
* <lf11>x:identity</lf11> </cont1>
*/
}
/**
- *
+ *
* Test case like (without namespace in xml) <cont1> <lf11>x:identity</lf11>
* </cont1>
*/
}
/**
- *
+ *
* Test case like (without namespace in xml) <cont1> <lf11>identity</lf11>
* </cont1>
*/
"/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "identityref:module");
}
- private void verifyCommonPartAOfXml(CompositeNode compNode, String suf, String nameSpace) {
+ private void verifyCommonPartAOfXml(final CompositeNode compNode, final String suf, final String nameSpace) {
SimpleNode<?> lf1suf = null;
SimpleNode<?> lflst1suf_1 = null;
SimpleNode<?> lflst1suf_2 = null;
int lflstCount = 0;
- for (Node<?> node : compNode.getChildren()) {
+ for (Node<?> node : compNode.getValue()) {
String localName = node.getNodeType().getLocalName();
if (localName.equals("lf1" + suf)) {
assertTrue(node instanceof SimpleNode<?>);
assertEquals("131", lflst1suf_2.getValue());
assertEquals("str1", lflst1suf_3.getValue());
- assertEquals(1, lst1suf.getChildren().size());
+ assertEquals(1, lst1suf.getValue().size());
- assertTrue(lst1suf.getChildren().get(0) instanceof SimpleNode<?>);
- SimpleNode<?> lst11_lf11 = (SimpleNode<?>) lst1suf.getChildren().get(0);
+ assertTrue(lst1suf.getValue().get(0) instanceof SimpleNode<?>);
+ SimpleNode<?> lst11_lf11 = (SimpleNode<?>) lst1suf.getValue().get(0);
assertEquals(nameSpace, lst11_lf11.getNodeType().getNamespace().toString());
assertEquals("lf11" + suf, lst11_lf11.getNodeType().getLocalName());
assertEquals("str2", lst11_lf11.getValue());
- assertTrue(cont1suf.getChildren().get(0) instanceof SimpleNode<?>);
- SimpleNode<?> cont1_lf11 = (SimpleNode<?>) cont1suf.getChildren().get(0);
+ assertTrue(cont1suf.getValue().get(0) instanceof SimpleNode<?>);
+ SimpleNode<?> cont1_lf11 = (SimpleNode<?>) cont1suf.getValue().get(0);
assertEquals(nameSpace, cont1_lf11.getNodeType().getNamespace().toString());
assertEquals("lf11" + suf, cont1_lf11.getNodeType().getLocalName());
assertEquals((short) 100, cont1_lf11.getValue());
}
- private void testIdentityrefToCnSn(String xmlPath, String yangPath, String moduleName, String schemaName,
- int moduleCount, String resultLocalName, String resultNamespace) {
+ private void testIdentityrefToCnSn(final String xmlPath, final String yangPath, final String moduleName, final String schemaName,
+ final int moduleCount, final String resultLocalName, final String resultNamespace) {
CompositeNode compositeNode = TestUtils.readInputToCnSn(xmlPath, false, XmlToCompositeNodeProvider.INSTANCE);
assertNotNull(compositeNode);
assertEquals(resultNamespace, qName.getNamespace().toString());
}
- private SimpleNode<?> getLf11(CompositeNode compositeNode) {
+ private SimpleNode<?> getLf11(final CompositeNode compositeNode) {
assertEquals("cont", compositeNode.getNodeType().getLocalName());
- List<Node<?>> childs = compositeNode.getChildren();
+ List<Node<?>> childs = compositeNode.getValue();
assertEquals(1, childs.size());
Node<?> nd = childs.iterator().next();
assertTrue(nd instanceof CompositeNode);
assertEquals("cont1", nd.getNodeType().getLocalName());
- childs = ((CompositeNode) nd).getChildren();
+ childs = ((CompositeNode) nd).getValue();
SimpleNode<?> lf11 = null;
for (Node<?> child : childs) {
assertTrue(child instanceof SimpleNode);
*/
package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader {
assertEquals("cont", compositeNode.getNodeType().getLocalName());
SimpleNode<?> lf2 = null;
- for (Node<?> childNode : compositeNode.getChildren()) {
+ for (Node<?> childNode : compositeNode.getValue()) {
if (childNode instanceof SimpleNode) {
if (childNode.getNodeType().getLocalName().equals("lf2")) {
lf2 = (SimpleNode<?>) childNode;
assertNotNull(lf2);
assertTrue(lf2.getValue() instanceof String);
- assertEquals("121", (String) lf2.getValue());
+ assertEquals("121", lf2.getValue());
}
}
--- /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
<version>1.1-SNAPSHOT</version>
</parent>
- <groupId>org.opendaylight.controller</groupId>
<artifactId>sal-rest-docgen</artifactId>
<packaging>bundle</packaging>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>2.4.0</version>
<extensions>true</extensions>
<configuration>
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
/**
* InventoryService provides functions related to Nodes & NodeConnectors.
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.NetUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.address.tracker.rev140402.l2.addresses.L2Address;
/* InstanceIdentifierUtils provides utility functions related to InstanceIdentifiers.
*/
-public class InstanceIdentifierUtils {
-
- /**
- * Creates an Instance Identifier (path) for node with specified id
- *
- * @param nodeId
- * @return
- */
- public static final InstanceIdentifier<Node> createNodePath(NodeId nodeId) {
- return InstanceIdentifier.builder(Nodes.class) //
- .child(Node.class, new NodeKey(nodeId)) //
- .build();
- }
-
- /**
- * Shorten's node child path to node path.
- *
- * @param nodeChild child of node, from which we want node path.
- * @return
- */
- public static final InstanceIdentifier<Node> getNodePath(InstanceIdentifier<?> nodeChild) {
- return nodeChild.firstIdentifierOf(Node.class);
- }
-
-
- /**
- * Creates a table path by appending table specific location to node path
- *
- * @param nodePath
- * @param tableKey
- * @return
- */
- public static final InstanceIdentifier<Table> createTablePath(InstanceIdentifier<Node> nodePath, TableKey tableKey) {
- return InstanceIdentifier.builder(nodePath)
- .augmentation(FlowCapableNode.class)
- .child(Table.class, tableKey)
- .build();
- }
-
- /**
- * Creates a path for particular flow, by appending flow-specific information
- * to table path.
- *
- * @param table
- * @param flowKey
- * @return
- */
- public static InstanceIdentifier<Flow> createFlowPath(InstanceIdentifier<Table> table, FlowKey flowKey) {
- return InstanceIdentifier.builder(table)
- .child(Flow.class, flowKey)
- .build();
- }
-
- /**
- * Extract table id from table path.
- *
- * @param tablePath
- * @return
- */
- public static Short getTableId(InstanceIdentifier<Table> tablePath) {
- return tablePath.firstKeyOf(Table.class, TableKey.class).getId();
- }
-
- /**
- * Extracts NodeConnectorKey from node connector path.
- */
- public static NodeConnectorKey getNodeConnectorKey(InstanceIdentifier<?> nodeConnectorPath) {
- return nodeConnectorPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
- }
-
- /**
- * Extracts NodeKey from node path.
- */
- public static NodeKey getNodeKey(InstanceIdentifier<?> nodePath) {
- return nodePath.firstKeyOf(Node.class, NodeKey.class);
- }
-
-
- //
- public static final InstanceIdentifier<NodeConnector> createNodeConnectorIdentifier(String nodeIdValue,
- String nodeConnectorIdValue) {
- return InstanceIdentifier.builder(createNodePath(new NodeId(nodeIdValue))) //
- .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorIdValue))) //
- .build();
- }
-
- /**
- * @param nodeConnectorRef
- * @return
- */
- public static InstanceIdentifier<Node> generateNodeInstanceIdentifier(NodeConnectorRef nodeConnectorRef) {
- return nodeConnectorRef.getValue().firstIdentifierOf(Node.class);
- }
-
- /**
- * @param nodeConnectorRef
- * @param flowTableKey
- * @return
- */
- public static InstanceIdentifier<Table> generateFlowTableInstanceIdentifier(NodeConnectorRef nodeConnectorRef, TableKey flowTableKey) {
- return InstanceIdentifier.builder(generateNodeInstanceIdentifier(nodeConnectorRef))
- .augmentation(FlowCapableNode.class)
- .child(Table.class, flowTableKey)
- .build();
- }
-
- /**
- * @param nodeConnectorRef
- * @param flowTableKey
- * @param flowKey
- * @return
- */
- public static InstanceIdentifier<Flow> generateFlowInstanceIdentifier(NodeConnectorRef nodeConnectorRef,
- TableKey flowTableKey,
- FlowKey flowKey) {
- return InstanceIdentifier.builder(generateFlowTableInstanceIdentifier(nodeConnectorRef, flowTableKey))
- .child(Flow.class, flowKey)
- .build();
- }
-
- public static InstanceIdentifier<Topology> generateTopologyInstanceIdentifier(String topologyId) {
- return InstanceIdentifier.builder(NetworkTopology.class)
- .child(Topology.class, new TopologyKey(new TopologyId(topologyId)))
- .build();
- }
+public final class InstanceIdentifierUtils {
+
+ private InstanceIdentifierUtils() {
+ throw new UnsupportedOperationException("Utility class should never be instantiated");
+ }
+
+ /**
+ * Creates an Instance Identifier (path) for node with specified id
+ *
+ * @param nodeId
+ * @return
+ */
+ public static final InstanceIdentifier<Node> createNodePath(final NodeId nodeId) {
+ return InstanceIdentifier.builder(Nodes.class) //
+ .child(Node.class, new NodeKey(nodeId)) //
+ .build();
+ }
+
+ /**
+ * Shorten's node child path to node path.
+ *
+ * @param nodeChild child of node, from which we want node path.
+ * @return
+ */
+ public static final InstanceIdentifier<Node> getNodePath(final InstanceIdentifier<?> nodeChild) {
+ return nodeChild.firstIdentifierOf(Node.class);
+ }
+
+
+ /**
+ * Creates a table path by appending table specific location to node path
+ *
+ * @param nodePath
+ * @param tableKey
+ * @return
+ */
+ public static final InstanceIdentifier<Table> createTablePath(final InstanceIdentifier<Node> nodePath, final TableKey tableKey) {
+ return nodePath.builder()
+ .augmentation(FlowCapableNode.class)
+ .child(Table.class, tableKey)
+ .build();
+ }
+
+ /**
+ * Creates a path for particular flow, by appending flow-specific information
+ * to table path.
+ *
+ * @param table
+ * @param flowKey
+ * @return
+ */
+ public static InstanceIdentifier<Flow> createFlowPath(final InstanceIdentifier<Table> table, final FlowKey flowKey) {
+ return table.child(Flow.class, flowKey);
+ }
+
+ /**
+ * Extract table id from table path.
+ *
+ * @param tablePath
+ * @return
+ */
+ public static Short getTableId(final InstanceIdentifier<Table> tablePath) {
+ return tablePath.firstKeyOf(Table.class, TableKey.class).getId();
+ }
+
+ /**
+ * Extracts NodeConnectorKey from node connector path.
+ */
+ public static NodeConnectorKey getNodeConnectorKey(final InstanceIdentifier<?> nodeConnectorPath) {
+ return nodeConnectorPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class);
+ }
+
+ /**
+ * Extracts NodeKey from node path.
+ */
+ public static NodeKey getNodeKey(final InstanceIdentifier<?> nodePath) {
+ return nodePath.firstKeyOf(Node.class, NodeKey.class);
+ }
+
+
+ //
+ public static final InstanceIdentifier<NodeConnector> createNodeConnectorIdentifier(final String nodeIdValue,
+ final String nodeConnectorIdValue) {
+ return createNodePath(new NodeId(nodeIdValue))
+ .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorIdValue)));
+ }
+
+ /**
+ * @param nodeConnectorRef
+ * @return
+ */
+ public static InstanceIdentifier<Node> generateNodeInstanceIdentifier(final NodeConnectorRef nodeConnectorRef) {
+ return nodeConnectorRef.getValue().firstIdentifierOf(Node.class);
+ }
+
+ /**
+ * @param nodeConnectorRef
+ * @param flowTableKey
+ * @return
+ */
+ public static InstanceIdentifier<Table> generateFlowTableInstanceIdentifier(final NodeConnectorRef nodeConnectorRef, final TableKey flowTableKey) {
+ return generateNodeInstanceIdentifier(nodeConnectorRef).builder()
+ .augmentation(FlowCapableNode.class)
+ .child(Table.class, flowTableKey)
+ .build();
+ }
+
+ /**
+ * @param nodeConnectorRef
+ * @param flowTableKey
+ * @param flowKey
+ * @return
+ */
+ public static InstanceIdentifier<Flow> generateFlowInstanceIdentifier(final NodeConnectorRef nodeConnectorRef,
+ final TableKey flowTableKey,
+ final FlowKey flowKey) {
+ return generateFlowTableInstanceIdentifier(nodeConnectorRef, flowTableKey).child(Flow.class, flowKey);
+ }
+
+ public static InstanceIdentifier<Topology> generateTopologyInstanceIdentifier(final String topologyId) {
+ return InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId(topologyId)))
+ .build();
+ }
}
*/
package org.opendaylight.controller.sample.l2switch.md.flow;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import org.junit.Before;
import org.junit.Test;
-import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService;
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
/**
*/
public class FlowWriterServiceImplTest {
- private DataBrokerService dataBrokerService;
- private NodeConnectorRef srcNodeConnectorRef;
- private NodeConnectorRef destNodeConnectorRef;
- private MacAddress destMacAddress;
- private MacAddress srcMacAddress;
- private DataModificationTransaction dataModificationTransaction;
- private NetworkGraphService networkGraphService;
+ private DataBrokerService dataBrokerService;
+ private NodeConnectorRef srcNodeConnectorRef;
+ private NodeConnectorRef destNodeConnectorRef;
+ private MacAddress destMacAddress;
+ private MacAddress srcMacAddress;
+ private DataModificationTransaction dataModificationTransaction;
+ private NetworkGraphService networkGraphService;
- @Before
- public void init() {
- dataBrokerService = mock(DataBrokerService.class);
- networkGraphService = mock(NetworkGraphService.class);
- //build source node connector ref
- InstanceIdentifier<Nodes> srcNodesInstanceIdentifier
- = InstanceIdentifier.builder(Nodes.class)
- .build();
- InstanceIdentifier<Node> srcNodeInstanceIdentifier
- = InstanceIdentifier.builder(srcNodesInstanceIdentifier)
- .child(Node.class, new NodeKey(new NodeId("openflow:1")))
- .build();
- InstanceIdentifier<NodeConnector> srcNodeConnectorInstanceIdentifier
- = InstanceIdentifier.builder(srcNodeInstanceIdentifier)
- .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:1:2")))
- .build();
- srcNodeConnectorRef = new NodeConnectorRef(srcNodeConnectorInstanceIdentifier);
+ @Before
+ public void init() {
+ dataBrokerService = mock(DataBrokerService.class);
+ networkGraphService = mock(NetworkGraphService.class);
+ //build source node connector ref
+ InstanceIdentifier<Nodes> srcNodesInstanceIdentifier = InstanceIdentifier.create(Nodes.class);
+ InstanceIdentifier<Node> srcNodeInstanceIdentifier = srcNodesInstanceIdentifier
+ .child(Node.class, new NodeKey(new NodeId("openflow:1")));
+ InstanceIdentifier<NodeConnector> srcNodeConnectorInstanceIdentifier = srcNodeInstanceIdentifier
+ .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:1:2")));
+ srcNodeConnectorRef = new NodeConnectorRef(srcNodeConnectorInstanceIdentifier);
- //build dest node connector ref
- InstanceIdentifier<Nodes> nodesInstanceIdentifier
+ //build dest node connector ref
+ InstanceIdentifier<Nodes> nodesInstanceIdentifier
= InstanceIdentifier.builder(Nodes.class)
.build();
- InstanceIdentifier<Node> nodeInstanceIdentifier
- = InstanceIdentifier.builder(nodesInstanceIdentifier)
- .child(Node.class, new NodeKey(new NodeId("openflow:2")))
- .build();
- InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier
- = InstanceIdentifier.builder(nodeInstanceIdentifier)
- .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:2:2")))
- .build();
- destNodeConnectorRef = new NodeConnectorRef(nodeConnectorInstanceIdentifier);
- destMacAddress = new MacAddress("00:0a:95:9d:68:16");
- srcMacAddress = new MacAddress("00:0a:95:8c:97:24");
- dataModificationTransaction = mock(DataModificationTransaction.class);
- when(dataBrokerService.beginTransaction()).thenReturn(dataModificationTransaction);
- }
+ InstanceIdentifier<Node> nodeInstanceIdentifier =
+ nodesInstanceIdentifier.child(Node.class, new NodeKey(new NodeId("openflow:2")));
+ InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier =
+ nodeInstanceIdentifier.child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:2:2")));
+ destNodeConnectorRef = new NodeConnectorRef(nodeConnectorInstanceIdentifier);
+ destMacAddress = new MacAddress("00:0a:95:9d:68:16");
+ srcMacAddress = new MacAddress("00:0a:95:8c:97:24");
+ dataModificationTransaction = mock(DataModificationTransaction.class);
+ when(dataBrokerService.beginTransaction()).thenReturn(dataModificationTransaction);
+ }
- @Test
- public void testFlowWriterServiceImpl_NPEWhenDataBrokerServiceIsNull() throws Exception {
- try {
- new FlowWriterServiceImpl(null, networkGraphService);
- fail("Expected null pointer exception.");
- } catch(NullPointerException npe) {
- assertEquals("dataBrokerService should not be null.", npe.getMessage());
+ @Test
+ public void testFlowWriterServiceImpl_NPEWhenDataBrokerServiceIsNull() throws Exception {
+ try {
+ new FlowWriterServiceImpl(null, networkGraphService);
+ fail("Expected null pointer exception.");
+ } catch(NullPointerException npe) {
+ assertEquals("dataBrokerService should not be null.", npe.getMessage());
+ }
}
- }
- @Test
- public void testAddMacToMacFlow_NPEWhenNullSourceMacDestMacAndNodeConnectorRef() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- try {
- flowWriterService.addMacToMacFlow(null, null, null);
- fail("Expected null pointer exception.");
- } catch(NullPointerException npe) {
- assertEquals("Destination mac address should not be null.", npe.getMessage());
+ @Test
+ public void testAddMacToMacFlow_NPEWhenNullSourceMacDestMacAndNodeConnectorRef() throws Exception {
+ FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+ try {
+ flowWriterService.addMacToMacFlow(null, null, null);
+ fail("Expected null pointer exception.");
+ } catch(NullPointerException npe) {
+ assertEquals("Destination mac address should not be null.", npe.getMessage());
+ }
}
- }
- @Test
- public void testAddMacToMacFlow_NPEWhenSourceMacNullMac() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- try {
- flowWriterService.addMacToMacFlow(null, null, destNodeConnectorRef);
- fail("Expected null pointer exception.");
- } catch(NullPointerException npe) {
- assertEquals("Destination mac address should not be null.", npe.getMessage());
+ @Test
+ public void testAddMacToMacFlow_NPEWhenSourceMacNullMac() throws Exception {
+ FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+ try {
+ flowWriterService.addMacToMacFlow(null, null, destNodeConnectorRef);
+ fail("Expected null pointer exception.");
+ } catch(NullPointerException npe) {
+ assertEquals("Destination mac address should not be null.", npe.getMessage());
+ }
}
- }
- @Test
- public void testAddMacToMacFlow_NPEWhenNullSourceMacNodeConnectorRef() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- try {
- flowWriterService.addMacToMacFlow(null, destMacAddress, null);
- fail("Expected null pointer exception.");
- } catch(NullPointerException npe) {
- assertEquals("Destination port should not be null.", npe.getMessage());
+ @Test
+ public void testAddMacToMacFlow_NPEWhenNullSourceMacNodeConnectorRef() throws Exception {
+ FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+ try {
+ flowWriterService.addMacToMacFlow(null, destMacAddress, null);
+ fail("Expected null pointer exception.");
+ } catch(NullPointerException npe) {
+ assertEquals("Destination port should not be null.", npe.getMessage());
+ }
}
- }
- @Test
- public void testAddMacToMacFlow_WhenNullSourceMac() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- flowWriterService.addMacToMacFlow(null, destMacAddress, destNodeConnectorRef);
- verify(dataBrokerService, times(1)).beginTransaction();
- verify(dataModificationTransaction, times(1)).commit();
- }
+ @Test
+ public void testAddMacToMacFlow_WhenNullSourceMac() throws Exception {
+ FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+ flowWriterService.addMacToMacFlow(null, destMacAddress, destNodeConnectorRef);
+ verify(dataBrokerService, times(1)).beginTransaction();
+ verify(dataModificationTransaction, times(1)).commit();
+ }
- @Test
- public void testAddMacToMacFlow_WhenSrcAndDestMacAreSame() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- flowWriterService.addMacToMacFlow(new MacAddress(destMacAddress.getValue()), destMacAddress, destNodeConnectorRef);
- verify(dataBrokerService, never()).beginTransaction();
- verify(dataModificationTransaction, never()).commit();
+ @Test
+ public void testAddMacToMacFlow_WhenSrcAndDestMacAreSame() throws Exception {
+ FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+ flowWriterService.addMacToMacFlow(new MacAddress(destMacAddress.getValue()), destMacAddress, destNodeConnectorRef);
+ verify(dataBrokerService, never()).beginTransaction();
+ verify(dataModificationTransaction, never()).commit();
- }
+ }
- @Test
- public void testAddMacToMacFlow_SunnyDay() throws Exception {
- FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
- flowWriterService.addMacToMacFlow(srcMacAddress, destMacAddress, destNodeConnectorRef);
- verify(dataBrokerService, times(1)).beginTransaction();
- verify(dataModificationTransaction, times(1)).commit();
- }
+ @Test
+ public void testAddMacToMacFlow_SunnyDay() throws Exception {
+ FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService);
+ flowWriterService.addMacToMacFlow(srcMacAddress, destMacAddress, destNodeConnectorRef);
+ verify(dataBrokerService, times(1)).beginTransaction();
+ verify(dataModificationTransaction, times(1)).commit();
+ }
}
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
LOG.info( "Toaster is already making toast" );
RpcResult<Void> result = Rpcs.<Void> getRpcResult(false, null, Arrays.asList(
- RpcErrors.getRpcError( null, null, null, null,
- "Toaster is busy", null, null ) ) );
+ RpcErrors.getRpcError( "", "in-use", null, ErrorSeverity.WARNING,
+ "Toaster is busy", ErrorType.APPLICATION, null ) ) );
return Futures.immediateFuture(result);
}
else if( outOfBread() ) {
RpcResult<Void> result = Rpcs.<Void> getRpcResult(false, null, Arrays.asList(
- RpcErrors.getRpcError( null, null, null, null,
- "Toaster is out of bread", null, null ) ) );
+ RpcErrors.getRpcError( "out-of-stock", "resource-denied", null, null,
+ "Toaster is out of bread",
+ ErrorType.APPLICATION, null ) ) );
return Futures.immediateFuture(result);
}
else {
+++ /dev/null
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <artifactId>sal-test-parent</artifactId>
- <groupId>org.opendaylight.controller.tests</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>sal-rest-connector-it</artifactId>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
- </scm>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>maven-paxexam-plugin</artifactId>
- <version>1.2.4</version>
- <executions>
- <execution>
- <id>generate-config</id>
- <goals>
- <goal>generate-depends-file</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- <pluginManagement>
- <plugins>
- <!--This plugin's configuration is used to store Eclipse
- m2e settings only. It has no influence on the Maven build itself. -->
- <plugin>
- <groupId>org.eclipse.m2e</groupId>
- <artifactId>lifecycle-mapping</artifactId>
- <version>1.0.0</version>
- <configuration>
- <lifecycleMappingMetadata>
- <pluginExecutions>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>
- org.ops4j.pax.exam
- </groupId>
- <artifactId>
- maven-paxexam-plugin
- </artifactId>
- <versionRange>
- [1.2.4,)
- </versionRange>
- <goals>
- <goal>
- generate-depends-file
- </goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <ignore></ignore>
- </action>
- </pluginExecution>
- </pluginExecutions>
- </lifecycleMappingMetadata>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>logging.bridge</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>xtend-lib-osgi</artifactId>
- <version>2.4.3</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>bundlescanner.implementation</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-broker-impl</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-rest-connector</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-netconf-connector</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-it</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-container-native</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-junit4</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-all</artifactId>
- <version>${netty.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-link-mvn</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.osgi</artifactId>
- <version>3.8.1.v20120830-144521</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- <version>1.7.2</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- <version>1.0.9</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <version>1.0.9</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-api</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-core-api</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-service</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-manager</artifactId>
- <version>0.2.2-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>antlr4-runtime-osgi-nohead</artifactId>
- <version>4.0</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.northbound</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <version>1.7.2</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
-
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- <version>1.7.2</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- <version>1.0.9</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <version>1.0.9</version>
- </dependency>
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- <version>1.7</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>javax.servlet</artifactId>
- <version>3.0.0.v201112011016</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>javax.servlet.jsp</artifactId>
- <version>2.2.0.v201112011158</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.equinox.ds</artifactId>
- <version>1.4.0.v20120522-1841</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.equinox.util</artifactId>
- <version>1.0.400.v20120522-2049</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.osgi.services</artifactId>
- <version>3.3.100.v20120522-1822</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.osgi</artifactId>
- <version>3.8.1.v20120830-144521</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.apache.felix.gogo.command</artifactId>
- <version>0.8.0.v201108120515</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.apache.felix.gogo.runtime</artifactId>
- <version>0.8.0.v201108120515</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.apache.felix.gogo.shell</artifactId>
- <version>0.8.0.v201110170705</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.equinox.cm</artifactId>
- <version>1.0.400.v20120522-1841</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.equinox.console</artifactId>
- <version>1.0.0.v20120522-1841</version>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.eclipse.equinox.launcher</artifactId>
- <version>1.3.0.v20120522-1813</version>
- </dependency>
- <!-- Gemini Web -->
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.gemini.web.core</artifactId>
- <version>${geminiweb.version}</version>
- </dependency>
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.gemini.web.extender</artifactId>
- <version>${geminiweb.version}</version>
- </dependency>
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.gemini.web.tomcat</artifactId>
- <version>${geminiweb.version}</version>
- </dependency>
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.virgo.kernel.equinox.extensions</artifactId>
- <version>${virgo.version}</version>
- </dependency>
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.virgo.util.common</artifactId>
- <version>${virgo.version}</version>
- </dependency>
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.virgo.util.io</artifactId>
- <version>${virgo.version}</version>
- </dependency>
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.virgo.util.math</artifactId>
- <version>${virgo.version}</version>
- </dependency>
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.virgo.util.osgi</artifactId>
- <version>${virgo.version}</version>
- </dependency>
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.virgo.util.osgi.manifest</artifactId>
- <version>${virgo.version}</version>
- </dependency>
- <dependency>
- <groupId>geminiweb</groupId>
- <artifactId>org.eclipse.virgo.util.parser.manifest</artifactId>
- <version>${virgo.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.dependencymanager</artifactId>
- <version>3.1.0</version>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
- <version>3.0.1</version>
- </dependency>
- <dependency>
- <groupId>org.jboss.spec.javax.transaction</groupId>
- <artifactId>jboss-transaction-api_1.1_spec</artifactId>
- <version>1.0.1.Final</version>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.fileinstall</artifactId>
- <version>3.1.6</version>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.1</version>
- </dependency>
- <dependency>
- <groupId>virgomirror</groupId>
- <artifactId>org.eclipse.jdt.core.compiler.batch</artifactId>
- <version>3.8.0.I20120518-2145</version>
- </dependency>
- <dependency>
- <groupId>eclipselink</groupId>
- <artifactId>javax.persistence</artifactId>
- <version>2.0.4.v201112161009</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>javax.activation</artifactId>
- <version>1.1.0.v201211130549</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>javax.annotation</artifactId>
- <version>1.1.0.v201209060031</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>javax.ejb</artifactId>
- <version>3.1.1.v201204261316</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>javax.el</artifactId>
- <version>2.2.0.v201108011116</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>javax.mail.glassfish</artifactId>
- <version>1.4.1.v201108011116</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>javax.xml.rpc</artifactId>
- <version>1.1.0.v201005080400</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>org.apache.catalina</artifactId>
- <version>7.0.32.v201211201336</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>org.apache.catalina.ha</artifactId>
- <version>7.0.32.v201211201952</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>org.apache.catalina.tribes</artifactId>
- <version>7.0.32.v201211201952</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>org.apache.coyote</artifactId>
- <version>7.0.32.v201211201952</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>org.apache.el</artifactId>
- <version>7.0.32.v201211081135</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>org.apache.jasper</artifactId>
- <version>7.0.32.v201211201952</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>org.apache.juli.extras</artifactId>
- <version>7.0.32.v201211081135</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>org.apache.tomcat.api</artifactId>
- <version>7.0.32.v201211081135</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>org.apache.tomcat.util</artifactId>
- <version>7.0.32.v201211201952</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>javax.servlet.jsp.jstl</artifactId>
- <version>1.2.0.v201105211821</version>
- </dependency>
- <dependency>
- <groupId>orbit</groupId>
- <artifactId>javax.servlet.jsp.jstl.impl</artifactId>
- <version>1.2.0.v201210211230</version>
- </dependency>
- <!-- Add Pax Exam -->
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-container-native</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-junit4</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.exam</groupId>
- <artifactId>pax-exam-link-mvn</artifactId>
- <version>${exam.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.url</groupId>
- <artifactId>pax-url-aether</artifactId>
- <version>${url.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ow2.asm</groupId>
- <artifactId>asm-all</artifactId>
- <version>4.1</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.asm</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.aop</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.context</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.context.support</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.core</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.beans</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.expression</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.web</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.aopalliance</groupId>
- <artifactId>com.springsource.org.aopalliance</artifactId>
- <version>1.0.0</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.web.servlet</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <!-- Spring security -->
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-config</artifactId>
- <version>${spring-security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-core</artifactId>
- <version>${spring-security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-web</artifactId>
- <version>${spring-security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-taglibs</artifactId>
- <version>${spring-security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.transaction</artifactId>
- <version>${spring-security.version}</version>
- </dependency>
- <!-- Visual VM hook -->
- <dependency>
- <groupId>org.ow2.chameleon.management</groupId>
- <artifactId>chameleon-mbeans</artifactId>
- <version>1.0.0</version>
- </dependency>
- <!-- Jersey for JAXRS -->
- <dependency>
- <groupId>com.sun.jersey</groupId>
- <artifactId>jersey-core</artifactId>
- <version>${jersey.version}</version>
- </dependency>
- <!-- <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-servlet</artifactId>
- <version>${jersey.version}</version> </dependency> -->
- <dependency>
- <groupId>com.sun.jersey</groupId>
- <artifactId>jersey-server</artifactId>
- <version>${jersey.version}</version>
- </dependency>
- <dependency>
- <groupId>com.sun.jersey</groupId>
- <artifactId>jersey-client</artifactId>
- <version>${jersey.version}</version>
- </dependency>
-
- <dependency>
- <groupId>eclipselink</groupId>
- <artifactId>javax.resource</artifactId>
- <version>1.5.0.v200906010428</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.thirdparty</groupId>
- <artifactId>com.sun.jersey.jersey-servlet</artifactId>
- <version>1.17</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.thirdparty</groupId>
- <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
- <version>7.0.42</version>
- </dependency>
-
-
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-manager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>logback-config</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-persister-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-persister-file-xml-adapter</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-impl</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-mapping-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-netconf-connector</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-persister-impl</artifactId>
- </dependency>
- </dependencies>
-</project>
+++ /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.test.restconf.it;
-
-import static junit.framework.Assert.assertEquals;
-import static org.junit.Assert.*;
-import static org.ops4j.pax.exam.CoreOptions.junitBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.CoreOptions.systemPackages;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-import static org.ops4j.pax.exam.CoreOptions.maven;
-
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
-import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.opendaylight.controller.test.sal.binding.it.TestHelper;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.CoreOptions;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.util.PathUtils;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.*;
-
-@RunWith(PaxExam.class)
-public class ServiceProviderController {
-
- public static final String ODL = "org.opendaylight.controller";
- public static final String YANG = "org.opendaylight.yangtools";
- public static final String SAMPLE = "org.opendaylight.controller.samples";
-
- private static QName CONFIG_MODULES = new QName(
- URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
- private static QName CONFIG_SERVICES = new QName(
- URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
- @Inject
- BundleContext context;
-
- @Inject
- MountProvisionService mountService;
-
- @Inject
- DataBrokerService dataBroker;
-
- @Test
- public void properInitialized() throws Exception {
-
- Map<QName, String> arg = Collections.singletonMap(InventoryUtils.INVENTORY_ID, "foo");
-
- InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
- .nodeWithKey(InventoryUtils.INVENTORY_NODE, InventoryUtils.INVENTORY_ID, "foo").toInstance();
-
-
- InstanceIdentifier mountPointPath = path;
-
- /** We retrive a mountpoint **/
- MountProvisionInstance mountPoint = mountService.getMountPoint(mountPointPath);
- CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
- .toInstance());
- assertNotNull(data);
- assertEquals(CONFIG_MODULES, data.getNodeType());
-
- CompositeNode data2 = mountPoint.readOperationalData(InstanceIdentifier.builder().toInstance());
- assertNotNull(data2);
-
- InstanceIdentifier fullPath = InstanceIdentifier.builder(mountPointPath).node(CONFIG_MODULES).toInstance();
-
- CompositeNode data3 = dataBroker.readOperationalData(fullPath);
- assertNotNull(data3);
- assertEquals(CONFIG_MODULES, data.getNodeType());
-
- //Thread.sleep(30 * 60 * 1000); // Waiting for services to get wired.
- //assertTrue(true);
- // assertTrue(consumer.createToast(WhiteBread.class, 5));
- }
-
- @Configuration
- public Option[] config() {
- return options(
- mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
- mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
- mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
- mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
-
- mdSalCoreBundles(),
- baseModelBundles(),
- flowCapableModelBundles(),
- configMinumumBundles(),
-
- // mavenBundle(ODL,
- // "sal-binding-broker-impl").versionAsInProject().update(), //
- mavenBundle(ODL, "sal-common").versionAsInProject(), //
- mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
- mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
- mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
-
- mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
- mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
- mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
-
- mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
- // mavenBundle(SAMPLE,
- // "zeromq-test-provider").versionAsInProject(), //
- mavenBundle(ODL, "sal-rest-connector").versionAsInProject(), //
- mavenBundle(ODL, "sal-netconf-connector").versionAsInProject(), //
-
- mavenBundle(YANG, "concepts").versionAsInProject(),
- mavenBundle(YANG, "yang-binding").versionAsInProject(), //
- mavenBundle(YANG, "yang-common").versionAsInProject(), //
- mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
- mavenBundle(YANG, "yang-data-impl").versionAsInProject(), //
- mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
- mavenBundle(YANG, "yang-model-util").versionAsInProject(), //
- mavenBundle(YANG, "yang-parser-api").versionAsInProject(),
- mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
-
- mavenBundle(YANG + ".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
- mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
- mavenBundle("com.google.guava", "guava").versionAsInProject(), //
-
- // systemProperty("logback.configurationFile").value(
- // "file:" + PathUtils.getBaseDir() +
- // "/src/test/resources/logback.xml"),
- // To start OSGi console for inspection remotely
- systemProperty("osgi.console").value("2401"),
- systemProperty("org.eclipse.gemini.web.tomcat.config.path").value(
- PathUtils.getBaseDir() + "/src/test/resources/tomcat-server.xml"),
-
- // setting default level. Jersey bundles will need to be started
- // earlier.
- systemProperty("osgi.bundles.defaultStartLevel").value("4"),
-
- systemProperty("netconf.tcp.address").value("127.0.0.1"),
- systemProperty("netconf.tcp.port").value("8383"),
-
- systemProperty("netconf.tcp.client.address").value("127.0.0.1"),
- systemProperty("netconf.tcp.client.port").value("8383"),
-
- // Set the systemPackages (used by clustering)
- systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
-
- mavenBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.xerces", "2.11.0_1"),
- mavenBundle("org.eclipse.birt.runtime.3_7_1", "org.apache.xml.resolver", "1.2.0"),
-
- mavenBundle("org.slf4j", "jcl-over-slf4j").versionAsInProject(),
- mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
- mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
- mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(),
- mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(),
- mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
- mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "clustering.services").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "containermanager").versionAsInProject(),
- // List all the opendaylight modules
- mavenBundle("org.opendaylight.controller", "configuration").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "sal").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "switchmanager").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "usermanager").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "logging.bridge").versionAsInProject(),
- // mavenBundle("org.opendaylight.controller",
- // "clustering.test").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "bundlescanner").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "bundlescanner.implementation").versionAsInProject(),
-
- // Northbound bundles
- mavenBundle("org.opendaylight.controller", "commons.northbound").versionAsInProject(),
-
- mavenBundle("com.fasterxml.jackson.core", "jackson-annotations").versionAsInProject(),
- mavenBundle("com.fasterxml.jackson.core", "jackson-core").versionAsInProject(),
- mavenBundle("com.fasterxml.jackson.core", "jackson-databind").versionAsInProject(),
- mavenBundle("com.fasterxml.jackson.jaxrs", "jackson-jaxrs-json-provider").versionAsInProject(),
- mavenBundle("com.fasterxml.jackson.module", "jackson-module-jaxb-annotations").versionAsInProject(),
-
- mavenBundle("org.codehaus.jettison", "jettison").versionAsInProject(),
-
- mavenBundle("commons-io", "commons-io").versionAsInProject(),
-
- // mavenBundle("commons-fileupload",
- // "commons-fileupload").versionAsInProject(),
-
- mavenBundle("io.netty", "netty-handler").versionAsInProject(),
- mavenBundle("io.netty", "netty-codec").versionAsInProject(),
- mavenBundle("io.netty", "netty-buffer").versionAsInProject(),
- mavenBundle("io.netty", "netty-transport").versionAsInProject(),
- mavenBundle("io.netty", "netty-common").versionAsInProject(),
-
- mavenBundle(ODL, "config-api").versionAsInProject(),
- mavenBundle(ODL, "config-manager").versionAsInProject(),
- mavenBundle(ODL, "config-util").versionAsInProject(),
- mavenBundle(ODL, "yang-jmx-generator").versionAsInProject(),
- mavenBundle(ODL, "logback-config").versionAsInProject(),
- mavenBundle(ODL, "config-persister-api").versionAsInProject(),
- // mavenBundle(ODL,"config-persister-file-xml-adapter").versionAsInProject(),
- mavenBundle(ODL, "protocol-framework").versionAsInProject(),
- mavenBundle(ODL, "netconf-api").versionAsInProject(),
- mavenBundle(ODL, "netconf-impl").versionAsInProject(),
- mavenBundle(ODL, "netconf-client").versionAsInProject(),
- mavenBundle(ODL, "netconf-util").versionAsInProject(),
- mavenBundle(ODL + ".thirdparty", "ganymed").versionAsInProject(),
- mavenBundle(ODL, "netconf-mapping-api").versionAsInProject(),
- mavenBundle(ODL, "config-netconf-connector").versionAsInProject(),
- mavenBundle(ODL, "config-persister-impl").versionAsInProject(),
-
- mavenBundle(YANG, "binding-generator-spi").versionAsInProject(), //
- mavenBundle(YANG, "binding-model-api").versionAsInProject(), //
- mavenBundle(YANG, "binding-generator-util").versionAsInProject(),
- mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
- mavenBundle(YANG, "binding-type-provider").versionAsInProject(),
-
- mavenBundle("equinoxSDK381", "javax.servlet").versionAsInProject(),
- mavenBundle("equinoxSDK381", "javax.servlet.jsp").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds").versionAsInProject(),
- mavenBundle("orbit", "javax.xml.rpc").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.eclipse.osgi.services").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.eclipse.equinox.cm").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
- mavenBundle("equinoxSDK381", "org.eclipse.equinox.launcher").versionAsInProject(),
-
- mavenBundle("geminiweb", "org.eclipse.gemini.web.core").versionAsInProject(),
- mavenBundle("geminiweb", "org.eclipse.gemini.web.extender").versionAsInProject(),
- mavenBundle("geminiweb", "org.eclipse.gemini.web.tomcat").versionAsInProject(),
- mavenBundle("geminiweb", "org.eclipse.virgo.kernel.equinox.extensions").versionAsInProject().noStart(),
- mavenBundle("geminiweb", "org.eclipse.virgo.util.common").versionAsInProject(),
- mavenBundle("geminiweb", "org.eclipse.virgo.util.io").versionAsInProject(),
- mavenBundle("geminiweb", "org.eclipse.virgo.util.math").versionAsInProject(),
- mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi").versionAsInProject(),
- mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi.manifest").versionAsInProject(),
- mavenBundle("geminiweb", "org.eclipse.virgo.util.parser.manifest").versionAsInProject(),
-
- mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
- mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager.shell").versionAsInProject(),
-
- mavenBundle("com.google.code.gson", "gson").versionAsInProject(),
- mavenBundle("org.jboss.spec.javax.transaction", "jboss-transaction-api_1.1_spec").versionAsInProject(),
- mavenBundle("org.apache.felix", "org.apache.felix.fileinstall").versionAsInProject(),
- mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
- mavenBundle("commons-codec", "commons-codec").versionAsInProject(),
- mavenBundle("virgomirror", "org.eclipse.jdt.core.compiler.batch").versionAsInProject(),
- mavenBundle("eclipselink", "javax.persistence").versionAsInProject(),
- mavenBundle("eclipselink", "javax.resource").versionAsInProject(),
-
- mavenBundle("orbit", "javax.activation").versionAsInProject(),
- mavenBundle("orbit", "javax.annotation").versionAsInProject(),
- mavenBundle("orbit", "javax.ejb").versionAsInProject(),
- mavenBundle("orbit", "javax.el").versionAsInProject(),
- mavenBundle("orbit", "javax.mail.glassfish").versionAsInProject(),
- mavenBundle("orbit", "javax.xml.rpc").versionAsInProject(),
- mavenBundle("orbit", "org.apache.catalina").versionAsInProject(),
- // these are bundle fragments that can't be started on its own
- mavenBundle("orbit", "org.apache.catalina.ha").versionAsInProject().noStart(),
- mavenBundle("orbit", "org.apache.catalina.tribes").versionAsInProject().noStart(),
- mavenBundle("orbit", "org.apache.coyote").versionAsInProject().noStart(),
- mavenBundle("orbit", "org.apache.jasper").versionAsInProject().noStart(),
-
- mavenBundle("orbit", "org.apache.el").versionAsInProject(),
- mavenBundle("orbit", "org.apache.juli.extras").versionAsInProject(),
- mavenBundle("orbit", "org.apache.tomcat.api").versionAsInProject(),
- mavenBundle("orbit", "org.apache.tomcat.util").versionAsInProject().noStart(),
- mavenBundle("orbit", "javax.servlet.jsp.jstl").versionAsInProject(),
- mavenBundle("orbit", "javax.servlet.jsp.jstl.impl").versionAsInProject(),
-
- mavenBundle("org.ops4j.pax.exam", "pax-exam-container-native").versionAsInProject(),
- mavenBundle("org.ops4j.pax.exam", "pax-exam-junit4").versionAsInProject(),
- mavenBundle("org.ops4j.pax.exam", "pax-exam-link-mvn").versionAsInProject(),
- mavenBundle("org.ops4j.pax.url", "pax-url-aether").versionAsInProject(),
-
- mavenBundle("org.ow2.asm", "asm-all").versionAsInProject(),
-
- mavenBundle("org.springframework", "org.springframework.asm").versionAsInProject(),
- mavenBundle("org.springframework", "org.springframework.aop").versionAsInProject(),
- mavenBundle("org.springframework", "org.springframework.context").versionAsInProject(),
- mavenBundle("org.springframework", "org.springframework.context.support").versionAsInProject(),
- mavenBundle("org.springframework", "org.springframework.core").versionAsInProject(),
- mavenBundle("org.springframework", "org.springframework.beans").versionAsInProject(),
- mavenBundle("org.springframework", "org.springframework.expression").versionAsInProject(),
- mavenBundle("org.springframework", "org.springframework.web").versionAsInProject(),
-
- mavenBundle("org.aopalliance", "com.springsource.org.aopalliance").versionAsInProject(),
- mavenBundle("org.springframework", "org.springframework.web.servlet").versionAsInProject(),
- mavenBundle("org.springframework.security", "spring-security-config").versionAsInProject(),
- mavenBundle("org.springframework.security", "spring-security-core").versionAsInProject(),
- mavenBundle("org.springframework.security", "spring-security-web").versionAsInProject(),
- mavenBundle("org.springframework.security", "spring-security-taglibs").versionAsInProject(),
- mavenBundle("org.springframework", "org.springframework.transaction").versionAsInProject(),
-
- mavenBundle("org.ow2.chameleon.management", "chameleon-mbeans").versionAsInProject(),
- mavenBundle("org.opendaylight.controller.thirdparty", "com.sun.jersey.jersey-servlet")
- .versionAsInProject().startLevel(2),
- mavenBundle("org.opendaylight.controller.thirdparty", "org.apache.catalina.filters.CorsFilter")
- .versionAsInProject().noStart(),
-
- // Jersey needs to be started before the northbound application
- // bundles, using a lower start level
- mavenBundle("com.sun.jersey", "jersey-client").versionAsInProject(),
- mavenBundle("com.sun.jersey", "jersey-server").versionAsInProject().startLevel(2),
- mavenBundle("com.sun.jersey", "jersey-core").versionAsInProject().startLevel(2),
- junitBundles());
- }
-
-}
+++ /dev/null
-#pax.exam.system = default
-pax.exam.logging = none
-pax.exam.service.timeout = 5000
-
+++ /dev/null
-<configuration scan="true">
-
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
- </pattern>
- </encoder>
- </appender>
-
- <root level="error">
- <appender-ref ref="STDOUT" />
- </root>
-</configuration>
+++ /dev/null
-<?xml version='1.0' encoding='utf-8'?>
-<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
- license agreements. See the NOTICE file distributed with this work for additional
- information regarding copyright ownership. The ASF licenses this file to
- You under the Apache License, Version 2.0 (the "License"); you may not use
- this file except in compliance with the License. You may obtain a copy of
- the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
- by applicable law or agreed to in writing, software distributed under the
- License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
- OF ANY KIND, either express or implied. See the License for the specific
- language governing permissions and limitations under the License. -->
-<Server>
- <!--APR library loader. Documentation at /docs/apr.html -->
- <Listener className="org.apache.catalina.core.AprLifecycleListener"
- SSLEngine="on" />
- <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
- <Listener className="org.apache.catalina.core.JasperListener" />
- <!-- Prevent memory leaks due to use of particular java/javax APIs -->
- <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
- <Listener
- className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
- <Listener
- className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
-
- <Service name="Catalina">
- <Connector port="8080" protocol="HTTP/1.1"
- connectionTimeout="20000" redirectPort="8443" />
-
- <!-- Please remove the comments around the following Connector tag
- to enable HTTPS Authentication support. Remember to add a valid keystore
- in the configuration folder. More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration -->
-
- <!-- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
- maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS"
- keystoreFile="configuration/keystore" keystorePass="changeit"/> -->
-
- <Engine name="Catalina" defaultHost="localhost">
- <Host name="localhost" appBase="" unpackWARs="false"
- autoDeploy="false" deployOnStartup="false" createDirs="false">
- <!-- Realm
- className="org.opendaylight.controller.security.ControllerCustomRealm" /> -->
- <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-
- <Valve className="org.apache.catalina.valves.AccessLogValve"
- directory="logs" prefix="web_access_log_" suffix=".txt"
- resolveHosts="false" rotatable="true"
- fileDateFormat="yyyy-MM"
- pattern="%{yyyy-MM-dd HH:mm:ss.SSS z}t - [%a] - %r" />
-
- </Host>
- </Engine>
- </Service>
-</Server>
@Override
AttributeConfigElement readElementHook(List<XmlElement> configNodes) throws NetconfDocumentedException {
List<Object> innerList = Lists.newArrayList();
- for (int i = 0; i < configNodes.size(); i++) {
- innerList.add(innerStrategy.readElement(Lists.newArrayList(configNodes.get(i))).getValue());
+ for (XmlElement configNode : configNodes) {
+ innerList.add(innerStrategy.readElement(Lists.newArrayList(configNode)).getValue());
}
return AttributeConfigElement.create(getNullableDefault(), innerList);
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
import com.google.common.base.Preconditions;
+import java.util.List;
+import java.util.Map;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Map;
public class ObjectNameAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
private static final Object PREFIX_SEPARATOR = ":";
- private static final Logger logger = LoggerFactory.getLogger(ObjectNameAttributeReadingStrategy.class);
public ObjectNameAttributeReadingStrategy(String nullableDefault) {
super(nullableDefault);
}
private ObjectNameAttributeMappingStrategy.MappedDependency resolve(XmlElement firstChild) throws NetconfDocumentedException{
- XmlElement typeElement = null;
- typeElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+ XmlElement typeElement = firstChild.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
Map.Entry<String, String> prefixNamespace = typeElement.findNamespaceOfTextContent();
String serviceName = checkPrefixAndExtractServiceName(typeElement, prefixNamespace);
public static String checkPrefixAndExtractServiceName(XmlElement typeElement, Map.Entry<String, String> prefixNamespace) throws NetconfDocumentedException {
String serviceName = typeElement.getTextContent();
-
+ // FIXME: comparing Entry with String:
Preconditions.checkState(!prefixNamespace.equals(""), "Service %s value not prefixed with namespace",
XmlNetconfConstants.TYPE_KEY);
String prefix = prefixNamespace.getKey() + PREFIX_SEPARATOR;
import java.util.List;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
public class SimpleAttributeReadingStrategy extends AbstractAttributeReadingStrategy {
- private static final Logger logger = LoggerFactory.getLogger(SimpleAttributeReadingStrategy.class);
-
-
public SimpleAttributeReadingStrategy(String nullableDefault) {
super(nullableDefault);
}
Preconditions.checkState(configNodes.size() == 1, "This element should be present only once " + xmlElement
+ " but was " + configNodes.size());
- String textContent = "";
- try{
- textContent = readElementContent(xmlElement);
- }catch(IllegalStateException | NullPointerException e) {
- // yuma sends <attribute /> for empty value instead of <attribute></attribute>
- logger.warn("Ignoring exception caused by failure to read text element", e);
- }
-
- if (null == textContent){
- throw new NetconfDocumentedException(String.format("This element should contain text %s", xmlElement),
- NetconfDocumentedException.ErrorType.application,
- NetconfDocumentedException.ErrorTag.invalid_value,
- NetconfDocumentedException.ErrorSeverity.error);
- }
+ String textContent = readElementContent(xmlElement);
return AttributeConfigElement.create(postprocessNullableDefault(getNullableDefault()),
postprocessParsedValue(textContent));
}
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
-
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import java.util.Map;
-import java.util.Map.Entry;
public class ObjectMapper extends AttributeIfcSwitchStatement<AttributeMappingStrategy<?, ? extends OpenType<?>>> {
- private final ServiceRegistryWrapper dependencyTracker;
-
- public ObjectMapper(ServiceRegistryWrapper depTracker) {
- this.dependencyTracker = depTracker;
- }
public Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> prepareMapping(
Map<String, AttributeIfc> configDefinition) {
@Override
protected Object parseObject(Class<?> type, String value) {
- return new Character(value.charAt(0));
+ return value.charAt(0);
}
}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
-
-public abstract class AbstractAttributeWritingStrategy {
- protected Object preprocess(Object value) {
- return value;
- }
-}
String refName = ((ObjectNameAttributeMappingStrategy.MappedDependency) value).getRefName();
String namespaceForType = ((ObjectNameAttributeMappingStrategy.MappedDependency) value).getNamespace();
- Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(XmlNetconfConstants.PREFIX, XmlNetconfConstants.TYPE_KEY), XmlNetconfConstants.PREFIX,
- moduleName, Optional.<String>of(namespaceForType));
+ Element typeElement = XmlUtil.createTextElementWithNamespacedContent(document, XmlNetconfConstants.TYPE_KEY, XmlNetconfConstants.PREFIX,
+ namespaceForType, moduleName);
+
innerNode.appendChild(typeElement);
final Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, refName, Optional.<String>absent());
Util.checkType(runtimeBeanInstanceMappingEntry.getValue(), Map.class);
Map<?, ?> innerMap = (Map<?, ?>) runtimeBeanInstanceMappingEntry.getValue();
Element runtimeInstanceNode = XmlUtil.createElement(getDocument(), "_"
- + (String) runtimeBeanInstanceMappingEntry.getKey(), Optional.<String>absent());
+ + runtimeBeanInstanceMappingEntry.getKey(), Optional.<String>absent());
innerNode.appendChild(runtimeInstanceNode);
for (Entry<?, ?> innerObjectEntry : innerMap.entrySet()) {
@Override
protected Element createElement(Document doc, String key, String value, Optional<String> namespace) {
QName qName = QName.create(value);
- String identity = qName.getLocalName();
+ String identityValue = qName.getLocalName();
String identityNamespace = qName.getNamespace().toString();
- Element element = XmlUtil.createPrefixedTextElement(doc, XmlUtil.createPrefixedValue(PREFIX, key), PREFIX, identity, Optional.<String>of(identityNamespace));
- return element;
+ return XmlUtil.createTextElementWithNamespacedContent(doc, key, PREFIX, identityNamespace, identityValue);
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import static com.google.common.base.Preconditions.checkState;
public class Config {
Map<String, Map<String, Collection<ObjectName>>> moduleToInstances = getMappedInstances(instancesToMap,
moduleConfigs);
- Element root = dataElement;
if (maybeNamespace.isPresent()) {
- root.setAttributeNS(maybeNamespace.get(), dataElement.getNodeName(), "xmlns");
+ dataElement.setAttributeNS(maybeNamespace.get(), dataElement.getNodeName(), "xmlns");
}
Element modulesElement = XmlUtil.createElement(document, XmlNetconfConstants.MODULES_KEY, Optional.of(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG));
- root.appendChild(modulesElement);
+ dataElement.appendChild(modulesElement);
for (String moduleNamespace : moduleToInstances.keySet()) {
for (Entry<String, Collection<ObjectName>> moduleMappingEntry : moduleToInstances.get(moduleNamespace)
.entrySet()) {
}
for (ObjectName objectName : moduleMappingEntry.getValue()) {
- modulesElement.appendChild(mapping.toXml(objectName, serviceTracker, document, moduleNamespace));
+ modulesElement.appendChild(mapping.toXml(objectName, document, moduleNamespace));
}
}
}
- root.appendChild(Services.toXml(serviceTracker, document));
+ dataElement.appendChild(Services.toXml(serviceTracker, document));
- return root;
+ return dataElement;
}
// TODO refactor, replace string representing namespace with namespace class
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.management.ObjectName;
+import javax.management.openmbean.OpenType;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
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.w3c.dom.Element;
-import javax.management.ObjectName;
-import javax.management.openmbean.OpenType;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
public final class InstanceConfig {
private static final Logger logger = LoggerFactory.getLogger(InstanceConfig.class);
private final Map<String, AttributeIfc> yangToAttrConfig;
+ private final String nullableDummyContainerName;
private final Map<String, AttributeIfc> jmxToAttrConfig;
private final ConfigRegistryClient configRegistryClient;
- public InstanceConfig(ConfigRegistryClient configRegistryClient, Map<String, AttributeIfc> yangNamesToAttributes) {
+ public InstanceConfig(ConfigRegistryClient configRegistryClient, Map<String, AttributeIfc> yangNamesToAttributes,
+ String nullableDummyContainerName) {
+
this.yangToAttrConfig = yangNamesToAttributes;
+ this.nullableDummyContainerName = nullableDummyContainerName;
this.jmxToAttrConfig = reverseMap(yangNamesToAttributes);
this.configRegistryClient = configRegistryClient;
}
- private Map<String, Object> getMappedConfiguration(ObjectName on, ServiceRegistryWrapper depTracker) {
+ private Map<String, Object> getMappedConfiguration(ObjectName on) {
// TODO make field, mappingStrategies can be instantiated only once
- Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> mappingStrategies = new ObjectMapper(depTracker)
+ Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> mappingStrategies = new ObjectMapper()
.prepareMapping(jmxToAttrConfig);
Map<String, Object> toXml = Maps.newHashMap();
return toXml;
}
- public Element toXml(ObjectName on, ServiceRegistryWrapper depTracker, String namespace, Document document, Element rootElement) {
-
- Element cfgElement = rootElement;
-
+ public Element toXml(ObjectName on, String namespace, Document document, Element rootElement) {
Map<String, AttributeWritingStrategy> strats = new ObjectXmlWriter().prepareWriting(yangToAttrConfig, document);
-
- Map<String, Object> mappedConfig = getMappedConfiguration(on, depTracker);
-
+ Map<String, Object> mappedConfig = getMappedConfiguration(on);
+ Element parentElement;
+ if (nullableDummyContainerName != null) {
+ Element dummyElement = XmlUtil.createElement(document, nullableDummyContainerName, Optional.of(namespace));
+ rootElement.appendChild(dummyElement);
+ parentElement = dummyElement;
+ } else {
+ parentElement = rootElement;
+ }
for (Entry<String, ?> mappingEntry : mappedConfig.entrySet()) {
try {
- strats.get(mappingEntry.getKey()).writeElement(cfgElement, namespace, mappingEntry.getValue());
+ strats.get(mappingEntry.getKey()).writeElement(parentElement, namespace, mappingEntry.getValue());
} catch (Exception e) {
throw new IllegalStateException("Unable to write value " + mappingEntry.getValue() + " for attribute "
+ mappingEntry.getValue(), e);
}
}
-
- return cfgElement;
+ return rootElement;
}
private void resolveConfiguration(InstanceConfigElementResolved mappedConfig, ServiceRegistryWrapper depTracker) {
}
public InstanceConfigElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper services, String moduleNamespace,
- EditStrategyType defaultStrategy, Multimap<String, String> providedServices, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) throws NetconfDocumentedException {
+ EditStrategyType defaultStrategy,
+ Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) throws NetconfDocumentedException {
Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig, identityMap);
List<XmlElement> recognisedChildren = Lists.newArrayList();
- XmlElement type = null;
- XmlElement name = null;
- type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
- name = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
- List<XmlElement> typeAndName = Lists.newArrayList(type, name);
+ XmlElement typeElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
+ XmlElement nameElement = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.NAME_KEY);
+ List<XmlElement> typeAndNameElements = Lists.newArrayList(typeElement, nameElement);
+
+ // if dummy container was defined in yang, set moduleElement to its content
+ if (nullableDummyContainerName != null) {
+ int size = moduleElement.getChildElements().size();
+ int expectedChildNodes = 1 + typeAndNameElements.size();
+ if (size > expectedChildNodes) {
+ throw new NetconfDocumentedException("Error reading module " + typeElement.getTextContent() + " : " +
+ nameElement.getTextContent() + " - Expected " + expectedChildNodes +" child nodes, " +
+ "one of them with name " + nullableDummyContainerName +
+ ", got " + size + " elements.");
+ }
+ if (size == expectedChildNodes) {
+ try {
+ moduleElement = moduleElement.getOnlyChildElement(nullableDummyContainerName, moduleNamespace);
+ } catch (NetconfDocumentedException e) {
+ throw new NetconfDocumentedException("Error reading module " + typeElement.getTextContent() + " : " +
+ nameElement.getTextContent() + " - Expected child node with name " + nullableDummyContainerName +
+ "." + e.getMessage());
+ }
+ } // else 2 elements, no need to descend
+ }
for (Entry<String, AttributeReadingStrategy> readStratEntry : strats.entrySet()) {
List<XmlElement> configNodes = getConfigNodes(moduleElement, moduleNamespace, readStratEntry.getKey(),
- recognisedChildren, typeAndName);
+ recognisedChildren, typeAndNameElements);
AttributeConfigElement readElement = readStratEntry.getValue().readElement(configNodes);
retVal.put(readStratEntry.getKey(), readElement);
}
- recognisedChildren.addAll(typeAndName);
- moduleElement.checkUnrecognisedElements(recognisedChildren);
-
+ recognisedChildren.addAll(typeAndNameElements);
+ try {
+ moduleElement.checkUnrecognisedElements(recognisedChildren);
+ } catch (NetconfDocumentedException e) {
+ throw new NetconfDocumentedException("Error reading module " + typeElement.getTextContent() + " : " +
+ nameElement.getTextContent() + " - " +
+ e.getMessage(), e.getErrorType(), e.getErrorTag(),e.getErrorSeverity(),e.getErrorInfo());
+ }
// TODO: add check for conflicts between global and local edit strategy
String perInstanceEditStrategy = moduleElement.getAttribute(XmlNetconfConstants.OPERATION_ATTR_KEY,
XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
InstanceConfigElementResolved instanceConfigElementResolved = perInstanceEditStrategy.equals("") ? new InstanceConfigElementResolved(
- retVal, defaultStrategy, providedServices) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal, defaultStrategy, providedServices);
+ retVal, defaultStrategy) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal, defaultStrategy);
resolveConfiguration(instanceConfigElementResolved, services);
return instanceConfigElementResolved;
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
-import com.google.common.collect.Multimap;
import java.util.Map;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
private final EditStrategyType editStrategy;
private final Map<String, AttributeConfigElement> configuration;
- private final Multimap<String, String> providedServices;
- public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) throws NetconfDocumentedException {
- EditStrategyType valueOf = null;
- valueOf = parseStrategy(currentStrategy, defaultStrategy);
- this.editStrategy = valueOf;
+ public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration,
+ EditStrategyType defaultStrategy)
+ throws NetconfDocumentedException {
+ this.editStrategy = parseStrategy(currentStrategy, defaultStrategy);
this.configuration = configuration;
- this.providedServices = providedServices;
}
- public InstanceConfigElementResolved(Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
+ public InstanceConfigElementResolved(Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy) {
editStrategy = defaultStrategy;
this.configuration = configuration;
- this.providedServices = providedServices;
}
public EditConfigStrategy getEditStrategy() {
- return editStrategy.getFittingStrategy(providedServices);
+ return editStrategy.getFittingStrategy();
}
public Map<String, AttributeConfigElement> getConfiguration() {
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
import com.google.common.base.Optional;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import java.util.Date;
+import java.util.Map;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
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.opendaylight.yangtools.yang.common.QName;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import javax.management.ObjectName;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Map;
-
public class ModuleConfig {
private final String moduleName;
private final InstanceConfig instanceConfig;
- private final Multimap<String, String> providedServices;
- public ModuleConfig(String moduleName, InstanceConfig mbeanMapping, Collection<QName> providedServices) {
+ public ModuleConfig(String moduleName, InstanceConfig mbeanMapping) {
this.moduleName = moduleName;
this.instanceConfig = mbeanMapping;
- this.providedServices = mapServices(providedServices);
}
- private Multimap<String, String> mapServices(Collection<QName> providedServices) {
- Multimap<String, String> mapped = HashMultimap.create();
-
- for (QName providedService : providedServices) {
- String key = providedService.getNamespace().toString();
- mapped.put(key, providedService.getLocalName());
- }
-
- return mapped;
- }
-
- public InstanceConfig getMbeanMapping() {
- return instanceConfig;
- }
+ public Element toXml(ObjectName instanceON, Document document, String namespace) {
+ Element root = XmlUtil.createElement(document, XmlNetconfConstants.MODULE_KEY, Optional.<String>absent());
- public Multimap<String, String> getProvidedServices() {
- return providedServices;
- }
+ // type belongs to config.yang namespace, but needs to be <type prefix:moduleNS>prefix:moduleName</type>
- public Element toXml(ObjectName instanceON, ServiceRegistryWrapper depTracker, Document document, String namespace) {
- Element root = XmlUtil.createElement(document, XmlNetconfConstants.MODULE_KEY, Optional.<String>absent());
- // Xml.addNamespaceAttr(document, root, namespace);
+ Element typeElement = XmlUtil.createTextElementWithNamespacedContent(document, XmlNetconfConstants.TYPE_KEY,
+ XmlNetconfConstants.PREFIX, namespace, moduleName);
- final String prefix = getPrefix();
- Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(prefix, XmlNetconfConstants.TYPE_KEY), prefix,
- moduleName, Optional.<String>of(namespace));
- // Xml.addNamespaceAttr(document, typeElement,
- // XMLUtil.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
root.appendChild(typeElement);
+ // name belongs to config.yang namespace
+ String instanceName = ObjectNameUtil.getInstanceName(instanceON);
+ Element nameElement = XmlUtil.createTextElement(document, XmlNetconfConstants.NAME_KEY, instanceName, Optional.<String>absent());
- Element nameElement = XmlUtil.createTextElement(document, XmlUtil.createPrefixedValue(prefix, XmlNetconfConstants.NAME_KEY),
- ObjectNameUtil.getInstanceName(instanceON), Optional.<String>of(namespace));
- // Xml.addNamespaceAttr(document, nameElement,
- // XMLUtil.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
root.appendChild(nameElement);
- root = instanceConfig.toXml(instanceON, depTracker, namespace, document, root);
+ root = instanceConfig.toXml(instanceON, namespace, document, root);
return root;
}
- private String getPrefix() {
- return XmlNetconfConstants.PREFIX;
- }
-
public ModuleElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper depTracker, String instanceName,
String moduleNamespace, EditStrategyType defaultStrategy, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) throws NetconfDocumentedException {
- InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices, identityMap);
+ InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, identityMap);
return new ModuleElementResolved(instanceName, ice);
}
return instanceName;
}
- public EditStrategyType getEditStrategyType() {
- return editStrategy;
- }
-
public EditConfigStrategy getEditStrategy() {
switch (editStrategy) {
case delete :
*/
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
-import org.opendaylight.yangtools.yang.common.QName;
-
+import java.util.Map;
import javax.management.InstanceNotFoundException;
import javax.management.ObjectName;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+import org.opendaylight.yangtools.yang.common.QName;
public class ServiceRegistryWrapper {
private ServiceReferenceReadableRegistry configServiceRefRegistry;
- private long suffix = 1;
-
public ServiceRegistryWrapper(ServiceReferenceReadableRegistry configServiceRefRegistry) {
this.configServiceRefRegistry = configServiceRefRegistry;
}
- public boolean hasRefName(String namespace, String serviceName, ObjectName on) {
- String qname = configServiceRefRegistry.getServiceInterfaceName(namespace, serviceName);
- Map<String, ObjectName> forQName = configServiceRefRegistry.getServiceMapping().get(qname);
- if(forQName==null){
- return false;
- }
- return forQName.values().contains(on);
- }
-
public ObjectName getByServiceAndRefName(String namespace, String serviceName, String refName) {
Map<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
- Preconditions.checkArgument(serviceNameToRefNameToInstance != null, "No serviceInstances mapped to " + namespace);
+ Preconditions.checkNotNull(serviceNameToRefNameToInstance, "No serviceInstances mapped to " + namespace);
Map<String, String> refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
- Preconditions.checkArgument(refNameToInstance != null, "No serviceInstances mapped to " + serviceName + " , "
+ Preconditions.checkNotNull(refNameToInstance, "No serviceInstances mapped to " + serviceName + " , "
+ serviceNameToRefNameToInstance.keySet());
String instanceId = refNameToInstance.get(refName);
return retVal;
}
-
- @VisibleForTesting
- public String getNewDefaultRefName(String namespace, String serviceName, String moduleName, String instanceName) {
- String refName;
- refName = "ref_" + instanceName;
-
- Map<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
-
- Map<String, String> refNameToInstance;
- if(serviceNameToRefNameToInstance == null || !serviceNameToRefNameToInstance.containsKey(serviceName)) {
- refNameToInstance = Collections.emptyMap();
- } else {
- refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
- }
-
- final Set<String> refNamesAsSet = toSet(refNameToInstance.keySet());
- if (refNamesAsSet.contains(refName)) {
- refName = findAvailableRefName(refName, refNamesAsSet);
- }
-
- return refName;
- }
-
-
- private Set<String> toSet(Collection<String> values) {
- Set<String> refNamesAsSet = Sets.newHashSet();
-
- for (String refName : values) {
- boolean resultAdd = refNamesAsSet.add(refName);
- Preconditions.checkState(resultAdd,
- "Error occurred building services element, reference name {} was present twice", refName);
- }
-
- return refNamesAsSet;
- }
-
- private String findAvailableRefName(String refName, Set<String> refNamesAsSet) {
- String availableRefName = "";
-
- while (true) {
- availableRefName = refName + "_" + suffix++;
- if (!refNamesAsSet.contains(availableRefName)){
- return availableRefName;
- }
- }
- }
}
for (String namespace : mappedServices.keySet()) {
for (Entry<String, Map<String, String>> serviceEntry : mappedServices.get(namespace).entrySet()) {
+ // service belongs to config.yang namespace
Element serviceElement = XmlUtil.createElement(document, SERVICE_KEY, Optional.<String>absent());
root.appendChild(serviceElement);
- Element typeElement = XmlUtil.createPrefixedTextElement(document, XmlUtil.createPrefixedValue(XmlNetconfConstants.PREFIX, TYPE_KEY), XmlNetconfConstants.PREFIX,
- serviceEntry.getKey(), Optional.of(namespace));
+ // type belongs to config.yang namespace
+ String serviceType = serviceEntry.getKey();
+ Element typeElement = XmlUtil.createTextElementWithNamespacedContent(document, XmlNetconfConstants.TYPE_KEY,
+ XmlNetconfConstants.PREFIX, namespace, serviceType);
+
serviceElement.appendChild(typeElement);
for (Entry<String, String> instanceEntry : serviceEntry.getValue().entrySet()) {
return rpc;
}
- public Map<String, String> getYangToJavaNames() {
- return yangToJavaNames;
- }
-
- public Map<String, Map<String, InstanceRuntimeRpc>> getRpcMapping() {
- return rpcMapping;
- }
}
if (on.getKeyPropertyList().size() != keyListSize + 1){
return false;
}
- if (!on.getKeyPropertyList().containsKey(string)){
- return false;
- }
- return true;
+ return on.getKeyPropertyList().containsKey(string);
}
}));
}
public Element toXml(ObjectName rootOn, Set<ObjectName> childRbeOns, Document document, String instanceIndex,
Element parentElement, String namespace) {
- Element xml = instanceMapping.toXml(rootOn, null, namespace, document, parentElement);
+ Element xml = instanceMapping.toXml(rootOn, namespace, document, parentElement);
if (instanceIndex != null) {
xml.setAttribute(KEY_ATTRIBUTE_KEY, instanceIndex);
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime;
import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Set;
+import javax.management.ObjectName;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import javax.management.ObjectName;
-import java.util.Collection;
-import java.util.Set;
-
public class ModuleRuntime {
private final InstanceRuntime instanceRuntime;
- public ModuleRuntime(String moduleName, InstanceRuntime instanceRuntime) {
+ public ModuleRuntime(InstanceRuntime instanceRuntime) {
this.instanceRuntime = instanceRuntime;
}
- public InstanceRuntime getMbeanMapping() {
- return instanceRuntime;
- }
-
private ObjectName findRoot(Collection<ObjectName> runtimeBeanOns) {
for (ObjectName objectName : runtimeBeanOns) {
if (objectName.getKeyPropertyList().size() == 3){
}
public Element toXml(String namespace, Collection<ObjectName> runtimeBeanOns,
- Document document, ModuleConfig moduleConfig, ObjectName configBeanON, ServiceRegistryWrapper serviceTracker) {
+ Document document, ModuleConfig moduleConfig, ObjectName configBeanON) {
- Element moduleElement = moduleConfig.toXml(configBeanON, serviceTracker, document, namespace);
+ Element moduleElement = moduleConfig.toXml(configBeanON, document, namespace);
ObjectName rootName = findRoot(runtimeBeanOns);
Set<ObjectName> childrenRuntimeBeans = Sets.newHashSet(runtimeBeanOns);
childrenRuntimeBeans.remove(rootName);
+ // FIXME: why is this called and not used?
instanceRuntime.toXml(rootName, childrenRuntimeBeans, document, moduleElement, namespace);
return moduleElement;
package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime;
+import com.google.common.base.Optional;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
-
import javax.management.ObjectName;
-
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Optional;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-
public class Runtime {
private final Map<String, Map<String, ModuleRuntime>> moduleRuntimes;
return retVal;
}
- public Element toXml(Set<ObjectName> instancesToMap, Set<ObjectName> configBeans, Document document, ServiceRegistryWrapper serviceRegistry) {
+ public Element toXml(Set<ObjectName> instancesToMap, Set<ObjectName> configBeans, Document document) {
Element root = XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
Element modulesElement = XmlUtil.createElement(document, XmlNetconfConstants.MODULES_KEY, Optional.of(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG));
Element runtimeXml;
ModuleConfig moduleConfig = moduleConfigs.get(localNamespace).get(moduleName);
if(instanceToRbe==null || !instanceToRbe.containsKey(instanceName)) {
- runtimeXml = moduleConfig.toXml(instanceON, serviceRegistry, document, localNamespace);
+ runtimeXml = moduleConfig.toXml(instanceON, document, localNamespace);
} else {
ModuleRuntime moduleRuntime = moduleRuntimes.get(localNamespace).get(moduleName);
runtimeXml = moduleRuntime.toXml(localNamespace, instanceToRbe.get(instanceName), document,
- moduleConfig, instanceON, serviceRegistry);
+ moduleConfig, instanceON);
}
modulesElement.appendChild(runtimeXml);
}
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
-import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
public class EditConfig extends AbstractConfigNetconfOperation {
private static final Logger logger = LoggerFactory.getLogger(EditConfig.class);
@VisibleForTesting
Element getResponseInternal(final Document document,
- final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException, NetconfConfigHandlingException {
+ final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
if (editConfigExecution.shouldTest()) {
executeTests(getConfigRegistryClient(), editConfigExecution);
return identityNameToSchemaNode.containsKey(idName);
}
- // FIXME method never used
- public IdentitySchemaNode getIdentitySchemaNode(String idName) {
- Preconditions.checkState(identityNameToSchemaNode.containsKey(idName), "No identity under name %s", idName);
- return identityNameToSchemaNode.get(idName);
- }
}
private static Map<String, Map<Date, IdentityMapping>> transformIdentities(Set<Module> modules) {
String moduleName = moduleNameToMbe.getKey();
ModuleMXBeanEntry moduleMXBeanEntry = moduleNameToMbe.getValue();
- ModuleConfig moduleConfig = new ModuleConfig(moduleName, new InstanceConfig(configRegistryClient,
- moduleMXBeanEntry.getAttributes()), moduleMXBeanEntry
- .getProvidedServices().values());
+ ModuleConfig moduleConfig = new ModuleConfig(moduleName,
+ new InstanceConfig(configRegistryClient,moduleMXBeanEntry.getAttributes(), moduleMXBeanEntry.getNullableDummyContainerName()));
Map<String, ModuleConfig> moduleNameToModuleConfig = namespaceToModuleNameToModuleConfig.get(namespace);
if(moduleNameToModuleConfig == null) {
EditConfigXmlParser.EditConfigExecution editConfigExecution;
Config cfg = getConfigMapping(getConfigRegistryClient(), yangStoreSnapshot);
- editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, getConfigRegistryClient());
+ editConfigExecution = editConfigXmlParser.fromXml(xml, cfg);
Element responseInternal;
responseInternal = getResponseInternal(document, editConfigExecution);
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.collect.Multimap;
+import java.util.Arrays;
+import java.util.Map;
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
-import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementDefinition;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
-import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Arrays;
-import java.util.Map;
-
public class EditConfigXmlParser {
private static final Logger logger = LoggerFactory.getLogger(EditConfigXmlParser.class);
public EditConfigXmlParser() {
}
- EditConfigXmlParser.EditConfigExecution fromXml(final XmlElement xml, final Config cfgMapping,
- TransactionProvider transactionProvider, ConfigRegistryClient configRegistryClient)
+ EditConfigXmlParser.EditConfigExecution fromXml(final XmlElement xml, final Config cfgMapping)
throws NetconfDocumentedException {
//TODO remove transactionProvider and CfgRegistry from parameters, accept only service ref store
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
-import com.google.common.collect.Multimap;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
-
import java.util.EnumSet;
import java.util.Set;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.confignetconfconnector.exception.OperationNotPermittedException;
public enum EditStrategyType {
// can be default
}
}
- public EditConfigStrategy getFittingStrategy(Multimap<String, String> providedServices) {
+ public EditConfigStrategy getFittingStrategy() {
switch (this) {
case merge:
- return new MergeEditConfigStrategy(providedServices);
+ return new MergeEditConfigStrategy();
case replace:
- return new ReplaceEditConfigStrategy(providedServices);
+ return new ReplaceEditConfigStrategy();
case delete:
return new DeleteEditConfigStrategy();
case remove:
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.management.Attribute;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.management.Attribute;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Map;
-import java.util.Map.Entry;
-
public class MergeEditConfigStrategy extends AbstractEditConfigStrategy {
private static final Logger logger = LoggerFactory.getLogger(MergeEditConfigStrategy.class);
- private final Multimap<String, String> providedServices;
public MergeEditConfigStrategy() {
- this.providedServices = HashMultimap.create();
- }
- public MergeEditConfigStrategy(Multimap<String, String> providedServices) {
- this.providedServices = providedServices;
}
@Override
NetconfDocumentedException.ErrorTag.operation_failed,
NetconfDocumentedException.ErrorSeverity.error);
}
-
- private void addRefNames(ServiceRegistryWrapper services, Multimap<String, String> providedServices, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
- for (Entry<String, String> namespaceToService : providedServices.entries()) {
-
- if(services.hasRefName(namespaceToService.getKey(),
- namespaceToService.getValue(), on)){
- continue;
- }
-
- String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
- ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on));
- ta.saveServiceReference(
- ta.getServiceInterfaceName(namespaceToService.getKey(), namespaceToService.getValue()), refName, on);
- }
- }
-
@Override
void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
- try {
- addRefNames(services, providedServices, ta, on);
- } catch (InstanceNotFoundException e) {
- throw new NetconfConfigHandlingException(String.format("Unable to save default ref name for instance %s. Instance was not found.",e),
- NetconfDocumentedException.ErrorType.application,
- NetconfDocumentedException.ErrorTag.operation_failed,
- NetconfDocumentedException.ErrorSeverity.error);
- }
for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
try {
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
- ObjectName on = null;
try {
- on = ta.createModule(module, instance);
+ ObjectName on = ta.createModule(module, instance);
logger.trace("New instance for {} {} created under name {}", module, instance, on);
} catch (InstanceAlreadyExistsException e1) {
throw new NetconfConfigHandlingException(String.format("Unable to create instance for %s : %s.", module, instance),
@Override
void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
ObjectName objectName, ServiceRegistryWrapper services) {
- return;
}
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.management.Attribute;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.exception.NetconfConfigHandlingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.management.Attribute;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Map;
-import java.util.Map.Entry;
-
public class ReplaceEditConfigStrategy extends AbstractEditConfigStrategy {
private static final Logger logger = LoggerFactory.getLogger(ReplaceEditConfigStrategy.class);
- private final Multimap<String, String> providedServices;
-
- public ReplaceEditConfigStrategy() {
- this.providedServices = HashMultimap.create();
- }
-
- public ReplaceEditConfigStrategy(Multimap<String, String> providedServices) {
- this.providedServices = providedServices;
- }
-
@Override
void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
String module, String instance, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
NetconfDocumentedException.ErrorSeverity.error);
}
- private void addRefNames(ServiceRegistryWrapper services, Multimap<String, String> providedServices, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
- for (Entry<String, String> namespaceToService : providedServices.entries()) {
-
- if(services.hasRefName(namespaceToService.getKey(),
- namespaceToService.getValue(), on)){
- continue;
- }
-
- String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
- ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on));
- ta.saveServiceReference(
- ta.getServiceInterfaceName(namespaceToService.getKey(), namespaceToService.getValue()), refName, on);
- }
- }
-
@Override
void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, ServiceRegistryWrapper services) throws NetconfConfigHandlingException {
- try {
- addRefNames(services, providedServices, ta, on);
- } catch (InstanceNotFoundException e) {
- throw new NetconfConfigHandlingException(String.format("Unable to save default ref name for instance %s. Instance not found. ",on),
- NetconfDocumentedException.ErrorType.application,
- NetconfDocumentedException.ErrorTag.operation_failed,
- NetconfDocumentedException.ErrorSeverity.error);
- }
-
for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
try {
AttributeConfigElement ace = configAttributeEntry.getValue();
package org.opendaylight.controller.netconf.confignetconfconnector.operations.get;
import com.google.common.collect.Maps;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
-import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime.InstanceRuntime;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime.ModuleRuntime;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtime.Runtime;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
-import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import javax.management.ObjectName;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
public class Get extends AbstractConfigNetconfOperation {
private final YangStoreSnapshot yangStoreSnapshot;
private static final Logger logger = LoggerFactory.getLogger(Get.class);
- private final TransactionProvider transactionProvider;
public Get(YangStoreSnapshot yangStoreSnapshot, ConfigRegistryClient configRegistryClient,
- String netconfSessionIdForReporting, TransactionProvider transactionProvider) {
+ String netconfSessionIdForReporting) {
super(configRegistryClient, netconfSessionIdForReporting);
this.yangStoreSnapshot = yangStoreSnapshot;
- this.transactionProvider = transactionProvider;
}
private Map<String, Map<String, ModuleRuntime>> createModuleRuntimes(ConfigRegistryClient configRegistryClient,
Map<RuntimeBeanEntry, InstanceConfig> cache = Maps.newHashMap();
RuntimeBeanEntry root = null;
for (RuntimeBeanEntry rbe : mbe.getRuntimeBeans()) {
- cache.put(rbe, new InstanceConfig(configRegistryClient, rbe.getYangPropertiesToTypesMap()));
+ cache.put(rbe, new InstanceConfig(configRegistryClient, rbe.getYangPropertiesToTypesMap(), mbe.getNullableDummyContainerName()));
if (rbe.isRoot()){
root = rbe;
}
}
InstanceRuntime rootInstanceRuntime = createInstanceRuntime(root, cache);
- ModuleRuntime moduleRuntime = new ModuleRuntime(module, rootInstanceRuntime);
+ ModuleRuntime moduleRuntime = new ModuleRuntime(rootInstanceRuntime);
innerMap.put(module, moduleRuntime);
}
final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs);
- ObjectName txOn = transactionProvider.getOrCreateTransaction();
- ConfigTransactionClient ta = getConfigRegistryClient().getConfigTransactionClient(txOn);
- final Element element = runtime.toXml(runtimeBeans, configBeans, document, new ServiceRegistryWrapper(ta));
+ final Element element = runtime.toXml(runtimeBeans, configBeans, document);
logger.trace("{} operation successful", XmlNetconfConstants.GET);
}
private Element getResponseInternal(final Document document, final ConfigRegistryClient configRegistryClient,
- final Datastore source) throws NetconfDocumentedException {
+ final Datastore source) {
Element dataElement = XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
final Set<ObjectName> instances = Datastore.getInstanceQueryStrategy(source, this.transactionProvider)
.queryInstances(configRegistryClient);
}
private Element toXml(Document doc, Object result, AttributeIfc returnType, String namespace, String elementName) throws NetconfDocumentedException {
- AttributeMappingStrategy<?, ? extends OpenType<?>> mappingStrategy = new ObjectMapper(null).prepareStrategy(returnType);
+ AttributeMappingStrategy<?, ? extends OpenType<?>> mappingStrategy = new ObjectMapper().prepareStrategy(returnType);
Optional<?> mappedAttributeOpt = mappingStrategy.mapAttribute(result);
Preconditions.checkState(mappedAttributeOpt.isPresent(), "Unable to map return value %s as %s", result, returnType.getOpenType());
ops.add(new EditConfig(yangStoreSnapshot, transactionProvider, configRegistryClient,
netconfSessionIdForReporting));
ops.add(new Commit(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
- ops.add(new Get(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting, transactionProvider));
+ ops.add(new Get(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting));
ops.add(new DiscardChanges(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
ops.add(new Validate(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
ops.add(new RuntimeRpc(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting));
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();
}
}
}
public void wipeTestTransaction(ObjectName taON) {
- wipeInternal(taON, true, null);
+ wipeInternal(taON, true);
}
/**
* Wiping means removing all module instances keeping the transaction open + service references.
*/
- synchronized void wipeInternal(ObjectName taON, boolean isTest, String moduleName) {
+ synchronized void wipeInternal(ObjectName taON, boolean isTest) {
ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON);
- Set<ObjectName> lookupConfigBeans = moduleName == null ? transactionClient.lookupConfigBeans()
- : transactionClient.lookupConfigBeans(moduleName);
+ Set<ObjectName> lookupConfigBeans = transactionClient.lookupConfigBeans();
int i = lookupConfigBeans.size();
for (ObjectName instance : lookupConfigBeans) {
try {
public void wipeTransaction() {
Optional<ObjectName> taON = getTransaction();
Preconditions.checkState(taON.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting);
- wipeInternal(taON.get(), false, null);
+ wipeInternal(taON.get(), false);
}
}
package org.opendaylight.controller.netconf.confignetconfconnector;
+import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement;
+import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
+import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement;
+
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
import org.custommonkey.xmlunit.AbstractNodeTester;
import org.custommonkey.xmlunit.NodeTest;
import org.custommonkey.xmlunit.NodeTestException;
import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean;
import org.opendaylight.controller.config.yang.test.impl.Peers;
+import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.Commit;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
-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.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1;
import org.w3c.dom.traversal.DocumentTraversal;
import org.xml.sax.SAXException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElement;
-import static org.opendaylight.controller.netconf.util.test.XmlUnitUtil.assertContainsElementWithText;
-import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElement;
-
public class NetconfMappingTest extends AbstractConfigTest {
private static final Logger logger = LoggerFactory.getLogger(NetconfMappingTest.class);
private NetconfTestImplModuleFactory factory;
private DepTestImplModuleFactory factory2;
private IdentityTestModuleFactory factory3;
+ private TestImplModuleFactory factory4;
@Mock
YangStoreSnapshot yangStoreSnapshot;
this.factory = new NetconfTestImplModuleFactory();
this.factory2 = new DepTestImplModuleFactory();
this.factory3 = new IdentityTestModuleFactory();
+ factory4 = new TestImplModuleFactory();
super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, this.factory, this.factory2,
- this.factory3));
+ this.factory3, factory4));
transactionProvider = new TransactionProvider(this.configRegistryClient, NETCONF_SESSION_ID);
}
edit("netconfMessages/editConfig.xml");
Document config = getConfigCandidate();
- assertCorrectServiceNames(config, Sets.newHashSet("ref_test2", "user_to_instance_from_code", "ref_dep_user",
+ assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user",
"ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
"ref_from_code_to_instance-from-code_1"));
edit("netconfMessages/editConfig_addServiceName.xml");
config = getConfigCandidate();
- assertCorrectServiceNames(config, Sets.newHashSet("ref_test2", "user_to_instance_from_code", "ref_dep_user",
+ assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user",
"ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
"ref_from_code_to_instance-from-code_1", "ref_dep_user_another"));
edit("netconfMessages/editConfig_addServiceNameOnTest.xml");
config = getConfigCandidate();
- assertCorrectServiceNames(config, Sets.newHashSet("ref_test2", "user_to_instance_from_code", "ref_dep_user",
+ assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user",
"ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
"ref_from_code_to_instance-from-code_1", "ref_dep_user_another"));
commit();
config = getConfigRunning();
assertCorrectRefNamesForDependencies(config);
- assertCorrectServiceNames(config, Sets.newHashSet("ref_test2", "user_to_instance_from_code", "ref_dep_user",
+ assertCorrectServiceNames(config, Sets.newHashSet("user_to_instance_from_code", "ref_dep_user",
"ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
"ref_from_code_to_instance-from-code_1", "ref_dep_user_another"));
edit("netconfMessages/editConfig_replace_default.xml");
config = getConfigCandidate();
- assertCorrectServiceNames(config, Sets.newHashSet("ref_dep", "ref_dep2"));
+ assertCorrectServiceNames(config, Collections.<String>emptySet());
edit("netconfMessages/editConfig_remove.xml");
config = getConfigCandidate();
nt.performTest(tester, Node.TEXT_NODE);
}
- private void assertCorrectServiceNames(Document configCandidate, final Set<String> refNames) throws NodeTestException {
-
+ private void assertCorrectServiceNames(Document configCandidate, Set<String> refNames) throws NodeTestException {
+ final Set<String> refNames2 = new HashSet<>(refNames);
NodeList servicesNodes = configCandidate.getElementsByTagName("services");
assertEquals(1, servicesNodes.getLength());
if(element.getNodeName() != null) {
if(element.getNodeName().equals("name")) {
String elmText = element.getTextContent();
- if(refNames.contains(elmText)) {
- refNames.remove(elmText);
- return;
+ if(refNames2.contains(elmText)) {
+ refNames2.remove(elmText);
} else {
throw new NodeTestException("Unexpected services defined: " + elmText);
}
@Override
public void noMoreNodes(NodeTest forTest) throws NodeTestException {
- assertTrue(refNames.isEmpty());
+ assertEquals(Collections.<String>emptySet(), refNames2);
+ assertTrue(refNames2.toString(), refNames2.isEmpty());
}
};
nt.performTest(tester, Node.ELEMENT_NODE);
assertEquals(2, afterReplace);
}
- @Test(expected = NetconfDocumentedException.class)
+ @Test
public void testSameAttrDifferentNamespaces() throws Exception {
try {
edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespaces.xml");
+ fail();
} catch (NetconfDocumentedException e) {
String message = e.getMessage();
- assertContainsString(message, "Element simple-long-2 present multiple times with different namespaces");
+ assertContainsString(message, "Element simpleInt present multiple times with different namespaces");
assertContainsString(message, TEST_NAMESPACE);
assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
- throw e;
}
}
- @Test(expected = NetconfDocumentedException.class)
+ @Test
public void testDifferentNamespaceInTO() throws Exception {
try {
edit("netconfMessages/namespaces/editConfig_differentNamespaceTO.xml");
+ fail();
} catch (NetconfDocumentedException e) {
String message = e.getMessage();
assertContainsString(message, "Unrecognised elements");
assertContainsString(message, "simple-int2");
assertContainsString(message, "dto_d");
- throw e;
}
}
- @Test(expected = NetconfDocumentedException.class)
+ @Test
public void testSameAttrDifferentNamespacesList() throws Exception {
try {
edit("netconfMessages/namespaces/editConfig_sameAttrDifferentNamespacesList.xml");
+ fail();
} catch (NetconfDocumentedException e) {
String message = e.getMessage();
- assertContainsString(message, "Element binaryLeaf present multiple times with different namespaces");
+ assertContainsString(message, "Element allow-user present multiple times with different namespaces");
assertContainsString(message, TEST_NAMESPACE);
assertContainsString(message, XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
- throw e;
}
}
for (int i = 0; i < TESTS_COUNT; i++) {
String file = String.format(format, i + 1);
+ logger.info("Reading {}", file);
try {
edit(file);
} catch (NetconfDocumentedException e) {
assertThat(string, JUnitMatchers.containsString(substring));
}
- private void checkEnum(final Document response) throws NetconfDocumentedException {
- XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data")
- .getOnlyChildElement("modules");
+ private void checkEnum(final Document response) throws Exception {
- String enumName = "extended-enum";
- String enumContent = "TWO";
+ String expectedEnumContent = "TWO";
- for (XmlElement moduleElement : modulesElement.getChildElements("module")) {
- String name = moduleElement.getOnlyChildElement("prefix:name").getTextContent();
- if(name.equals(INSTANCE_NAME)) {
- XmlElement enumAttr = moduleElement.getOnlyChildElement(enumName);
- assertEquals(enumContent, enumAttr.getTextContent());
- return;
- }
- }
-
- fail("Enum attribute " + enumName + ":" + enumContent + " not present in " + XmlUtil.toString(response));
+ XMLAssert.assertXpathEvaluatesTo(expectedEnumContent,
+ getXpathForNetconfImplSubnode(INSTANCE_NAME,"extended-enum"),
+ response);
}
private void checkTestingDeps(Document response) {
assertEquals(2, testingDepsSize);
}
- private void checkTypeConfigAttribute(Document response) throws NetconfDocumentedException {
-
- XmlElement modulesElement = XmlElement.fromDomElement(response.getDocumentElement()).getOnlyChildElement("data")
- .getOnlyChildElement("modules");
-
- List<String> expectedValues = Lists.newArrayList("default-string", "configAttributeType");
- Set<String> configAttributeType = Sets.newHashSet();
+ private String getXpathForNetconfImplSubnode(String instanceName, String subnode) {
+ return "/urn:ietf:params:xml:ns:netconf:base:1.0:rpc-reply" +
+ "/urn:ietf:params:xml:ns:netconf:base:1.0:data" +
+ "/urn:opendaylight:params:xml:ns:yang:controller:config:modules" +
+ "/module[name='"+instanceName+"']" +
+ "/urn:opendaylight:params:xml:ns:yang:controller:test:impl:impl-netconf" +
+ "/urn:opendaylight:params:xml:ns:yang:controller:test:impl:"+subnode;
+ }
- for (XmlElement moduleElement : modulesElement.getChildElements("module")) {
- for (XmlElement type : moduleElement.getChildElements("type")) {
- if (type.getNamespace() != null) {
- configAttributeType.add(type.getTextContent());
- }
- }
- }
+ private void checkTypeConfigAttribute(Document response) throws Exception {
- for (String expectedValue : expectedValues) {
- assertTrue(configAttributeType.contains(expectedValue));
+ Map<String,String> namesToTypeValues = ImmutableMap.of("instance-from-code", "configAttributeType",
+ "test2", "default-string");
+ for (Entry<String, String> nameToExpectedValue : namesToTypeValues.entrySet()) {
+ XMLAssert.assertXpathEvaluatesTo(nameToExpectedValue.getValue(),
+ getXpathForNetconfImplSubnode(nameToExpectedValue.getKey(),"type"),
+ response);
}
}
}
private Document get() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException {
- Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID, transactionProvider);
+ Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID);
return executeOp(getOp, "netconfMessages/get.xml");
}
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();
}
});
private final ErrorSeverity errorSeverity;
private final Map<String, String> errorInfo;
+ public NetconfDocumentedException(String message) {
+ this(message,
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error
+ );
+ }
+
public NetconfDocumentedException(final String message, final ErrorType errorType, final ErrorTag errorTag,
final ErrorSeverity errorSeverity) {
this(message, errorType, errorTag, errorSeverity, Collections.<String, String> emptyMap());
* 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> {
*/
package org.opendaylight.controller.netconf.impl.osgi;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.HashedWheelTimer;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.TimeUnit;
+
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.concurrent.TimeUnit;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
public class NetconfImplActivator implements BundleActivator {
private ServiceRegistration<NetconfMonitoringService> regMonitoring;
@Override
- public void start(final BundleContext context) {
- InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
- "TCP is not configured, netconf not available.", false);
-
- NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+ public void start(final BundleContext context) {
+ final InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfServerAddress(context,
+ NetconfConfigUtil.DEFAULT_NETCONF_TCP_ADDRESS);
+ final NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
startOperationServiceFactoryTracker(context, factoriesListener);
- SessionIdProvider idProvider = new SessionIdProvider();
+ final SessionIdProvider idProvider = new SessionIdProvider();
timer = new HashedWheelTimer();
- long connectionTimeoutMillis = NetconfConfigUtil.extractTimeoutMillis(context);
+ long connectionTimeoutMillis = NetconfConfigUtil.extractTimeoutMillis(context);
commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
serverNegotiatorFactory);
- NetconfServerDispatcher dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup);
+
+ NetconfServerDispatcher dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup,
+ eventLoopGroup);
logger.info("Starting TCP netconf server at {}", address);
dispatch.createServer(address);
context.registerService(NetconfOperationProvider.class, factoriesListener, null);
-
}
- private void startOperationServiceFactoryTracker(BundleContext context, NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+ private void startOperationServiceFactoryTracker(final BundleContext context, final NetconfOperationServiceFactoryListenerImpl factoriesListener) {
factoriesTracker = new NetconfOperationServiceFactoryTracker(context, factoriesListener);
factoriesTracker.open();
}
- private NetconfMonitoringServiceImpl startMonitoringService(BundleContext context, NetconfOperationServiceFactoryListenerImpl factoriesListener) {
- NetconfMonitoringServiceImpl netconfMonitoringServiceImpl = new NetconfMonitoringServiceImpl(factoriesListener);
- Dictionary<String, ?> dic = new Hashtable<>();
+ private NetconfMonitoringServiceImpl startMonitoringService(final BundleContext context, final NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+ final NetconfMonitoringServiceImpl netconfMonitoringServiceImpl = new NetconfMonitoringServiceImpl(factoriesListener);
+ final Dictionary<String, ?> dic = new Hashtable<>();
regMonitoring = context.registerService(NetconfMonitoringService.class, netconfMonitoringServiceImpl, dic);
return netconfMonitoringServiceImpl;
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>
notificationVerifier.assertNotificationCount(2);
notificationVerifier.assertNotificationContent(0, 0, 0, 9);
- notificationVerifier.assertNotificationContent(1, 4, 4, 9);
+ notificationVerifier.assertNotificationContent(1, 4, 3, 9);
mockedAggregator.assertSnapshotCount(2);
// Capabilities are stripped for persister
mockedAggregator.assertSnapshotContent(0, 0, 0, 1);
- mockedAggregator.assertSnapshotContent(1, 4, 4, 3);
+ mockedAggregator.assertSnapshotContent(1, 4, 3, 3);
}
private VerifyingPersister mockAggregator() throws IOException {
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);
NetconfMessage response = netconfClient.sendMessage(getConfig);
- assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:afi>"));
- assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:afi>"));
- assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:safi>"));
- assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:safi>"));
+ assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</afi>"));
+ assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</afi>"));
+ assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</safi>"));
+ assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</safi>"));
} catch (Exception e) {
fail(Throwables.getStackTraceAsString(e));
--- /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
private static final AtomicLong sesssionId = new AtomicLong();
private final InetSocketAddress clientAddress;
private final AuthProvider authProvider;
- private boolean up = false;
+ private volatile boolean up = false;
private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress, AuthProvider authProvider) throws IllegalStateException, IOException {
while (up) {
logger.trace("Starting new socket thread.");
try {
- SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(), authProvider);
- } catch (IOException e) {
- logger.error("Exception occurred during socket thread initialization {}", e);
+ SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(), authProvider);
+ }
+ catch (IOException e) {
+ if( up ) {
+ logger.error("Exception occurred during socket thread initialization", e);
+ }
+ else {
+ // We're shutting down so an exception is expected as the socket's been closed.
+ // Log to debug.
+ logger.debug("Shutting down - got expected exception: " + e);
+ }
}
}
}
package org.opendaylight.controller.netconf.ssh.authentication;
+import java.security.NoSuchAlgorithmException;
import org.apache.commons.io.FileUtils;
import org.bouncycastle.openssl.PEMWriter;
import org.slf4j.Logger;
private static final Logger logger = LoggerFactory.getLogger(PEMGenerator.class);
private static final int KEY_SIZE = 4096;
- public static String generateTo(File privateFile) throws Exception {
+ public static String generateTo(File privateFile) throws IOException, NoSuchAlgorithmException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom sr = new SecureRandom();
keyGen.initialize(KEY_SIZE, sr);
*/
package org.opendaylight.controller.netconf.ssh.osgi;
-import com.google.common.base.Optional;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.List;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
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.osgi.NetconfConfigUtil;
-import org.opendaylight.controller.sal.authorization.UserLevel;
import org.opendaylight.controller.usermanager.IUserManager;
-import org.opendaylight.controller.usermanager.UserConfig;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static com.google.common.base.Preconditions.checkNotNull;
/**
* Activator for netconf SSH bundle which creates SSH bridge between netconf client and netconf server. Activator
private NetconfSSHServer server;
private static final Logger logger = LoggerFactory.getLogger(NetconfSSHActivator.class);
- private static final String EXCEPTION_MESSAGE = "Netconf ssh bridge is not available.";
private IUserManager iUserManager;
private BundleContext context = null;
- private Optional<String> defaultPassword;
- private Optional<String> defaultUser;
private ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
@Override
- public IUserManager addingService(ServiceReference<IUserManager> reference) {
+ public IUserManager addingService(final ServiceReference<IUserManager> reference) {
logger.trace("Service {} added, let there be SSH bridge.", reference);
iUserManager = context.getService(reference);
try {
onUserManagerFound(iUserManager);
- } catch (Exception e) {
+ } catch (final Exception e) {
logger.trace("Can't start SSH server due to {}",e);
}
return iUserManager;
}
@Override
- public void modifiedService(ServiceReference<IUserManager> reference, IUserManager service) {
+ public void modifiedService(final ServiceReference<IUserManager> reference, final IUserManager service) {
logger.trace("Replacing modified service {} in netconf SSH.", reference);
server.addUserManagerService(service);
}
@Override
- public void removedService(ServiceReference<IUserManager> reference, IUserManager service) {
+ public void removedService(final ServiceReference<IUserManager> reference, final IUserManager service) {
logger.trace("Removing service {} from netconf SSH. " +
"SSH won't authenticate users until IUserManager service will be started.", reference);
removeUserManagerService();
@Override
- public void start(BundleContext context) {
+ public void start(final BundleContext context) {
this.context = context;
listenForManagerService();
}
@Override
public void stop(BundleContext context) throws IOException {
- if (this.defaultUser.isPresent()){
- this.iUserManager.removeLocalUser(this.defaultUser.get());
- }
if (server != null){
server.stop();
logger.trace("Netconf SSH bridge is down ...");
}
}
- private void startSSHServer() throws IllegalStateException, IOException {
+ private void startSSHServer() throws IOException {
checkNotNull(this.iUserManager, "No user manager service available.");
logger.trace("Starting netconf SSH bridge.");
- Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE);
- InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
- EXCEPTION_MESSAGE, true);
+ final InetSocketAddress sshSocketAddress = NetconfConfigUtil.extractSSHNetconfAddress(context,
+ NetconfConfigUtil.DEFAULT_NETCONF_SSH_ADDRESS);
+ final InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfClientAddress(context,
+ NetconfConfigUtil.DEFAULT_NETCONF_TCP_ADDRESS);
- if (sshSocketAddressOptional.isPresent()){
- String path = FilenameUtils.separatorsToSystem(NetconfConfigUtil.getPrivateKeyPath(context));
- if (path.equals("")){
- throw new IllegalStateException("Missing netconf.ssh.pk.path key in configuration file.");
- }
+ String path = FilenameUtils.separatorsToSystem(NetconfConfigUtil.getPrivateKeyPath(context));
- File privateKeyFile = new File(path);
- String privateKeyPEMString = null;
- if (privateKeyFile.exists() == false) {
- try {
- privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
- } catch (Exception e) {
- logger.error("Exception occurred while generating PEM string {}",e);
- }
- } else {
- // read from file
- try (FileInputStream fis = new FileInputStream(path)) {
- privateKeyPEMString = IOUtils.toString(fis);
- } catch (IOException e) {
- logger.error("Error reading RSA key from file '{}'", path);
- throw new IllegalStateException("Error reading RSA key from file " + path);
- }
- }
- AuthProvider authProvider = null;
+ if (path.isEmpty()) {
+ throw new IllegalStateException("Missing netconf.ssh.pk.path key in configuration file.");
+ }
+
+ final File privateKeyFile = new File(path);
+ final String privateKeyPEMString;
+ if (privateKeyFile.exists() == false) {
+ // generate & save to file
try {
- this.defaultPassword = NetconfConfigUtil.getSSHDefaultPassword(context);
- this.defaultUser = NetconfConfigUtil.getSSHDefaultUser(context);
- // Since there is no user data store yet (ldap, ...) this adds default user/password to UserManager
- // if these parameters are set in netconf configuration file.
- if (defaultUser.isPresent() &&
- defaultPassword.isPresent()){
- logger.trace(String.format("Default username and password for netconf ssh bridge found. Adding user %s to user manager.",defaultUser.get()));
- List<String> roles = new ArrayList<String>(1);
- roles.add(UserLevel.SYSTEMADMIN.toString());
- iUserManager.addLocalUser(new UserConfig(defaultUser.get(), defaultPassword.get(), roles));
- }
- authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
+ privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
} catch (Exception e) {
- logger.error("Error instantiating AuthProvider {}",e);
+ logger.error("Exception occurred while generating PEM string {}", e);
+ throw new IllegalStateException("Error generating RSA key from file " + path);
}
- this.server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress,authProvider);
-
- Thread serverThread = new Thread(server,"netconf SSH server thread");
- serverThread.setDaemon(true);
- serverThread.start();
- logger.trace("Netconf SSH bridge up and running.");
} else {
- logger.trace("No valid connection configuration for SSH bridge found.");
- throw new IllegalStateException("No valid connection configuration for SSH bridge found.");
+ // read from file
+ try (FileInputStream fis = new FileInputStream(path)) {
+ privateKeyPEMString = IOUtils.toString(fis);
+ } catch (final IOException e) {
+ logger.error("Error reading RSA key from file '{}'", path);
+ throw new IOException("Error reading RSA key from file " + path, e);
+ }
}
+ final AuthProvider authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
+ this.server = NetconfSSHServer.start(sshSocketAddress.getPort(), tcpSocketAddress, authProvider);
+
+ final Thread serverThread = new Thread(server, "netconf SSH server thread");
+ serverThread.setDaemon(true);
+ serverThread.start();
+ logger.trace("Netconf SSH bridge up and running.");
}
- private void onUserManagerFound(IUserManager userManager) throws IOException {
+
+ private void onUserManagerFound(final IUserManager userManager) throws Exception{
if (server!=null && server.isUp()){
server.addUserManagerService(userManager);
} else {
this.server.removeUserManagerService();
}
private void listenForManagerService(){
- ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(context, IUserManager.class,customizer);
+ final ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(context, IUserManager.class,customizer);
listenerTracker.open();
}
}
<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));
package org.opendaylight.controller.netconf.util.osgi;
import com.google.common.base.Optional;
-import com.google.common.base.Strings;
-import java.net.InetSocketAddress;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.InetSocketAddress;
public final class NetconfConfigUtil {
private static final Logger logger = LoggerFactory.getLogger(NetconfConfigUtil.class);
+ public static final InetSocketAddress DEFAULT_NETCONF_TCP_ADDRESS
+ = new InetSocketAddress("127.0.0.1", 8383);
+ public static final InetSocketAddress DEFAULT_NETCONF_SSH_ADDRESS
+ = new InetSocketAddress("0.0.0.0", 1830);
+
private static final String PREFIX_PROP = "netconf.";
- private NetconfConfigUtil() {}
+ private NetconfConfigUtil() {
+ }
private enum InfixProp {
tcp, ssh
private static final String ADDRESS_SUFFIX_PROP = ".address";
private static final String CLIENT_PROP = ".client";
private static final String PRIVATE_KEY_PATH_PROP = ".pk.path";
- private static final String SSH_DEFAULT_USER = ".default.user";
- private static final String SSH_DEFAULT_PASSWORD = ".default.password";
private static final String CONNECTION_TIMEOUT_MILLIS_PROP = "connectionTimeoutMillis";
private static final long DEFAULT_TIMEOUT_MILLIS = 5000;
- public static long extractTimeoutMillis(BundleContext bundleContext) {
- String key = PREFIX_PROP + CONNECTION_TIMEOUT_MILLIS_PROP;
- String timeoutString = bundleContext.getProperty(key);
+ public static long extractTimeoutMillis(final BundleContext bundleContext) {
+ final String key = PREFIX_PROP + CONNECTION_TIMEOUT_MILLIS_PROP;
+ final String timeoutString = bundleContext.getProperty(key);
if (timeoutString == null || timeoutString.length() == 0) {
return DEFAULT_TIMEOUT_MILLIS;
}
try {
return Long.parseLong(timeoutString);
- }catch(NumberFormatException e) {
+ } catch (final NumberFormatException e) {
logger.warn("Cannot parse {} property: {}, using defaults", key, timeoutString, e);
return DEFAULT_TIMEOUT_MILLIS;
}
}
- public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound, boolean forClient) {
-
- Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp, exceptionMessageIfNotFound, forClient);
-
- if (!inetSocketAddressOptional.isPresent()) {
- throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound);
- }
- InetSocketAddress inetSocketAddress = inetSocketAddressOptional.get();
- if (inetSocketAddress.getAddress().isAnyLocalAddress()) {
+ public static InetSocketAddress extractTCPNetconfServerAddress(final BundleContext context, final InetSocketAddress defaultAddress) {
+ final Optional<InetSocketAddress> extracted = extractNetconfServerAddress(context, InfixProp.tcp);
+ final InetSocketAddress netconfTcpAddress = getNetconfAddress(defaultAddress, extracted, InfixProp.tcp);
+ logger.debug("Using {} as netconf tcp address", netconfTcpAddress);
+ if (netconfTcpAddress.getAddress().isAnyLocalAddress()) {
logger.warn("Unprotected netconf TCP address is configured to ANY local address. This is a security risk. " +
"Consider changing {} to 127.0.0.1", PREFIX_PROP + InfixProp.tcp + ADDRESS_SUFFIX_PROP);
}
- return inetSocketAddress;
+ return netconfTcpAddress;
}
- public static Optional<InetSocketAddress> extractSSHNetconfAddress(BundleContext context, String exceptionMessage) {
- return extractSomeNetconfAddress(context, InfixProp.ssh, exceptionMessage, false);
+ public static InetSocketAddress extractTCPNetconfClientAddress(final BundleContext context, final InetSocketAddress defaultAddress) {
+ final Optional<InetSocketAddress> extracted = extractNetconfClientAddress(context, InfixProp.tcp);
+ return getNetconfAddress(defaultAddress, extracted, InfixProp.tcp);
}
- public static String getPrivateKeyPath(BundleContext context){
- return getPropertyValue(context,PREFIX_PROP + InfixProp.ssh +PRIVATE_KEY_PATH_PROP);
+ /**
+ * Get extracted address or default.
+ *
+ * @throws java.lang.IllegalStateException if neither address is present.
+ */
+ private static InetSocketAddress getNetconfAddress(final InetSocketAddress defaultAddress, Optional<InetSocketAddress> extractedAddress, InfixProp infix) {
+ InetSocketAddress inetSocketAddress;
+
+ if (extractedAddress.isPresent() == false) {
+ logger.debug("Netconf {} address not found, falling back to default {}", infix, defaultAddress);
+
+ if (defaultAddress == null) {
+ logger.warn("Netconf {} address not found, default address not provided", infix);
+ throw new IllegalStateException("Netconf " + infix + " address not found, default address not provided");
+ }
+ inetSocketAddress = defaultAddress;
+ } else {
+ inetSocketAddress = extractedAddress.get();
+ }
+
+ return inetSocketAddress;
}
- public static Optional<String> getSSHDefaultUser(BundleContext context){
- return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_USER);
+
+ public static InetSocketAddress extractSSHNetconfAddress(final BundleContext context, final InetSocketAddress defaultAddress) {
+ Optional<InetSocketAddress> extractedAddress = extractNetconfServerAddress(context, InfixProp.ssh);
+ InetSocketAddress netconfSSHAddress = getNetconfAddress(defaultAddress, extractedAddress, InfixProp.ssh);
+ logger.debug("Using {} as netconf SSH address", netconfSSHAddress);
+ return netconfSSHAddress;
}
- public static Optional<String> getSSHDefaultPassword(BundleContext context){
- return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_PASSWORD);
+
+ public static String getPrivateKeyPath(final BundleContext context) {
+ return getPropertyValue(context, PREFIX_PROP + InfixProp.ssh + PRIVATE_KEY_PATH_PROP);
}
- private static String getPropertyValue(BundleContext context, String propertyName){
- String propertyValue = context.getProperty(propertyName);
- if (propertyValue == null){
- throw new IllegalStateException("Cannot find initial property with name '"+propertyName+"'");
+ private static String getPropertyValue(final BundleContext context, final String propertyName) {
+ final String propertyValue = context.getProperty(propertyName);
+ if (propertyValue == null) {
+ throw new IllegalStateException("Cannot find initial property with name '" + propertyName + "'");
}
return propertyValue;
}
- private static Optional<String> getOptionalPropertyValue(BundleContext context, String propertyName){
- String propertyValue = context.getProperty(propertyName);
- if (Strings.isNullOrEmpty(propertyValue)){
- return Optional.absent();
- }
- return Optional.fromNullable(propertyValue);
- }
+
/**
- * @param context
- * from which properties are being read.
- * @param infixProp
- * either tcp or ssh
- * @return value if address and port are valid.
- * @throws IllegalStateException
- * if address or port are invalid, or configuration is missing
+ * @param context from which properties are being read.
+ * @param infixProp either tcp or ssh
+ * @return value if address and port are present and valid, Optional.absent otherwise.
+ * @throws IllegalStateException if address or port are invalid, or configuration is missing
*/
- private static Optional<InetSocketAddress> extractSomeNetconfAddress(BundleContext context,
- InfixProp infixProp,
- String exceptionMessage,
- boolean client) {
- String address = "";
- if (client) {
- address = context.getProperty(PREFIX_PROP + infixProp + CLIENT_PROP + ADDRESS_SUFFIX_PROP);
- }
- if (address == null || address.equals("")){
- address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
- }
- if (address == null || address.equals("")) {
- throw new IllegalStateException("Cannot find initial netconf configuration for parameter "
- +PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP
- +" in config.ini. "+exceptionMessage);
- }
- String portKey = "";
- if (client) {
- portKey = PREFIX_PROP + infixProp + CLIENT_PROP + PORT_SUFFIX_PROP;
+ private static Optional<InetSocketAddress> extractNetconfServerAddress(final BundleContext context,
+ final InfixProp infixProp) {
+
+ final Optional<String> address = getProperty(context, PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
+ final Optional<String> port = getProperty(context, PREFIX_PROP + infixProp + PORT_SUFFIX_PROP);
+
+ if (address.isPresent() && port.isPresent()) {
+ try {
+ return Optional.of(parseAddress(address, port));
+ } catch (final RuntimeException e) {
+ logger.warn("Unable to parse {} netconf address from {}:{}, fallback to default",
+ infixProp, address, port, e);
+ }
}
- if (portKey == null || portKey.equals("")){
- portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
+ return Optional.absent();
+ }
+
+ private static InetSocketAddress parseAddress(final Optional<String> address, final Optional<String> port) {
+ final int portNumber = Integer.valueOf(port.get());
+ return new InetSocketAddress(address.get(), portNumber);
+ }
+
+ private static Optional<InetSocketAddress> extractNetconfClientAddress(final BundleContext context,
+ final InfixProp infixProp) {
+ final Optional<String> address = getProperty(context,
+ PREFIX_PROP + infixProp + CLIENT_PROP + ADDRESS_SUFFIX_PROP);
+ final Optional<String> port = getProperty(context,
+ PREFIX_PROP + infixProp + CLIENT_PROP + PORT_SUFFIX_PROP);
+
+ if (address.isPresent() && port.isPresent()) {
+ try {
+ return Optional.of(parseAddress(address, port));
+ } catch (final RuntimeException e) {
+ logger.warn("Unable to parse client {} netconf address from {}:{}, fallback to server address",
+ infixProp, address, port, e);
+ }
}
- String portString = context.getProperty(portKey);
- checkNotNull(portString, "Netconf port must be specified in properties file with " + portKey);
- try {
- int port = Integer.valueOf(portString);
- return Optional.of(new InetSocketAddress(address, port));
- } catch (RuntimeException e) {
- throw new IllegalStateException("Cannot create " + infixProp + " netconf address from address:" + address
- + " and port:" + portString, e);
+ return extractNetconfServerAddress(context, infixProp);
+ }
+
+ private static Optional<String> getProperty(final BundleContext context, final String propKey) {
+ String value = context.getProperty(propKey);
+ if (value != null && value.isEmpty()) {
+ value = null;
}
+ return Optional.fromNullable(value);
}
}
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException;
import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
-import javax.annotation.Nullable;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
public final class XmlElement {
private final Element element;
public void checkNamespaceAttribute(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException {
if (!getNamespaceAttribute().equals(expectedNamespace))
{
- throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s",
+ throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s should be %s",
getNamespaceAttribute(),
expectedNamespace),
NetconfDocumentedException.ErrorType.application,
public void checkNamespace(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException {
if (!getNamespace().equals(expectedNamespace))
{
- throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s",
+ throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s should be %s",
getNamespace(),
expectedNamespace),
NetconfDocumentedException.ErrorType.application,
}
public String getTextContent() throws NetconfDocumentedException {
- Node textChild = element.getFirstChild();
- if (null == textChild){
- throw new NetconfDocumentedException(String.format( "Child node expected, got null for " + getName() + " : " + element),
- NetconfDocumentedException.ErrorType.application,
- NetconfDocumentedException.ErrorTag.invalid_value,
- NetconfDocumentedException.ErrorSeverity.error);
+ NodeList childNodes = element.getChildNodes();
+ if (childNodes.getLength() == 0) {
+ return "";
}
- if (!(textChild instanceof Text)){
- throw new NetconfDocumentedException(String.format(getName() + " should contain text." +
- Text.class.getName() + " expected, got " + textChild),
- NetconfDocumentedException.ErrorType.application,
- NetconfDocumentedException.ErrorTag.invalid_value,
- NetconfDocumentedException.ErrorSeverity.error);
+ for(int i = 0; i < childNodes.getLength(); i++) {
+ Node textChild = childNodes.item(i);
+ if (textChild instanceof Text) {
+ String content = textChild.getTextContent();
+ return content.trim();
+ }
}
- String content = textChild.getTextContent();
- // Trim needed
- return content.trim();
+ throw new NetconfDocumentedException(getName() + " should contain text.",
+ NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.invalid_value,
+ NetconfDocumentedException.ErrorSeverity.error
+ );
}
public String getNamespaceAttribute() throws MissingNameSpaceException {
return attribute;
}
- public String getNamespace() throws MissingNameSpaceException {
+ public Optional<String> getNamespaceOptionally() {
String namespaceURI = element.getNamespaceURI();
- if (namespaceURI == null || namespaceURI.equals("")){
+ if (Strings.isNullOrEmpty(namespaceURI)) {
+ return Optional.absent();
+ } else {
+ return Optional.of(namespaceURI);
+ }
+ }
+
+ public String getNamespace() throws MissingNameSpaceException {
+ Optional<String> namespaceURI = getNamespaceOptionally();
+ if (namespaceURI.isPresent() == false){
throw new MissingNameSpaceException(String.format("No namespace defined for %s", this),
NetconfDocumentedException.ErrorType.application,
NetconfDocumentedException.ErrorTag.operation_failed,
NetconfDocumentedException.ErrorSeverity.error);
}
- return namespaceURI;
+ return namespaceURI.get();
}
@Override
import com.google.common.base.Charsets;
import com.google.common.base.Optional;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
-
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.validation.SchemaFactory;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
public final class XmlUtil {
public static final String XMLNS_ATTRIBUTE_KEY = "xmlns";
- private static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+ public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
private static final DocumentBuilderFactory BUILDERFACTORY;
static {
return typeElement;
}
- public static Element createPrefixedTextElement(Document document, String qName, String prefix, String content, Optional<String> namespace) {
- return createTextElement(document, qName, createPrefixedValue(prefix, content), namespace);
+ public static Element createTextElementWithNamespacedContent(Document document, String qName, String prefix,
+ String namespace, String contentWithoutPrefix) {
+
+ String content = createPrefixedValue(XmlNetconfConstants.PREFIX, contentWithoutPrefix);
+ Element element = createTextElement(document, qName, content, Optional.<String>absent());
+ String prefixedNamespaceAttr = createPrefixedValue(XMLNS_ATTRIBUTE_KEY, prefix);
+ element.setAttributeNS(XMLNS_URI, prefixedNamespaceAttr, namespace);
+ return element;
}
public static String createPrefixedValue(String prefix, String value) {
import org.custommonkey.xmlunit.NodeTest;
import org.custommonkey.xmlunit.NodeTestException;
import org.custommonkey.xmlunit.NodeTester;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@Override
public void noMoreNodes(NodeTest forTest) throws NodeTestException {
- assertTrue(elementFound);
+ assertTrue(XmlUtil.toString(doc), elementFound);
}
};
assertNodeTestPasses(nt, tester, new short[]{Node.ELEMENT_NODE}, true);
</type>
<name>instance-from-code</name>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <sleep-factor>
+ 2.58
+ </sleep-factor>
- <sleep-factor>
- 2.58
- </sleep-factor>
+ <extended>
+ 10
+ </extended>
- <extended>
- 10
- </extended>
+ <extended-twice>
+ 20
+ </extended-twice>
- <extended-twice>
- 20
- </extended-twice>
+ <extended-enum>
+ TWO
+ </extended-enum>
- <extended-enum>
- TWO
- </extended-enum>
+ <simple-long-2>44</simple-long-2>
+ <binaryLeaf>YmluYXJ5</binaryLeaf>
- <simple-long-2>44</simple-long-2>
- <binaryLeaf>YmluYXJ5</binaryLeaf>
-
- <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
- <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
- <simple-int1>444</simple-int1>
- <simple-int2>4444</simple-int2>
- <simple-int3>454</simple-int3>
- <complex-dto-bInner>
- <simple-int3>44</simple-int3>
- <deep>
- <simple-int3>4</simple-int3>
- </deep>
+ <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
+ <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-int1>444</simple-int1>
+ <simple-int2>4444</simple-int2>
+ <simple-int3>454</simple-int3>
+ <complex-dto-bInner>
+ <simple-int3>44</simple-int3>
+ <deep>
+ <simple-int3>4</simple-int3>
+ </deep>
+ <simple-list>4</simple-list>
+ </complex-dto-bInner>
<simple-list>4</simple-list>
- </complex-dto-bInner>
- <simple-list>4</simple-list>
- </dto_d>
- <simpleInt>44</simpleInt>
- <simple-test>545</simple-test>
- <simple-long>454545</simple-long>
- <simpleBoolean>false</simpleBoolean>
- <dto-c>
- <dto-a-inner>
- <dto-a-inner-inner>
- <simple-arg>456</simple-arg>
- </dto-a-inner-inner>
- <simple-arg>44</simple-arg>
- </dto-a-inner>
- </dto-c>
- <simple-short>4</simple-short>
- <simple-BigInteger>999</simple-BigInteger>
- <simple-byte>4</simple-byte>
- <peers>
- <port>port1</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <peers>
- <port>port23</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep_user</name>
- </testing-dep>
+ </dto_d>
+ <simpleInt>44</simpleInt>
+ <simple-test>545</simple-test>
+ <simple-long>454545</simple-long>
+ <simpleBoolean>false</simpleBoolean>
+ <dto-c>
+ <dto-a-inner>
+ <dto-a-inner-inner>
+ <simple-arg>456</simple-arg>
+ </dto-a-inner-inner>
+ <simple-arg>44</simple-arg>
+ </dto-a-inner>
+ </dto-c>
+ <simple-short>4</simple-short>
+ <simple-BigInteger>999</simple-BigInteger>
+ <simple-byte>4</simple-byte>
+ <peers>
+ <port>port1</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <peers>
+ <port>port23</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep_user</name>
+ </testing-dep>
- <testing-deps>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep_user</name>
- </testing-deps>
- <testing-deps>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep_user_two</name>
- </testing-deps>
+ <testing-deps>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep_user</name>
+ </testing-deps>
+ <testing-deps>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep_user_two</name>
+ </testing-deps>
+ </impl-netconf>
</module>
<module>
test-impl:impl-netconf
</type>
<name>test2</name>
- <simple-short>4</simple-short>
-
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep_user_two</name>
- </testing-dep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-short>4</simple-short>
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep_user_two</name>
+ </testing-dep>
+ </impl-netconf>
</module>
</modules>
test-impl:impl-netconf
</type>
<name>instance-from-code</name>
- <simple-long-2>44</simple-long-2>
- <binaryLeaf>8ad1</binaryLeaf>
- <dto_d>
- <simple-int1>444</simple-int1>
- <simple-int2>4444</simple-int2>
- <simple-int3>454</simple-int3>
- <complex-dto-bInner>
- <simple-int3>44</simple-int3>
- <deep>
- <simple-int3>4</simple-int3>
- </deep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-long-2>44</simple-long-2>
+ <binaryLeaf>8ad1</binaryLeaf>
+ <dto_d>
+ <simple-int1>444</simple-int1>
+ <simple-int2>4444</simple-int2>
+ <simple-int3>454</simple-int3>
+ <complex-dto-bInner>
+ <simple-int3>44</simple-int3>
+ <deep>
+ <simple-int3>4</simple-int3>
+ </deep>
+ <simple-list>4</simple-list>
+ </complex-dto-bInner>
<simple-list>4</simple-list>
- </complex-dto-bInner>
- <simple-list>4</simple-list>
- </dto_d>
- <simpleInt>44</simpleInt>
- <simple-test>545</simple-test>
- <simple-long>454545</simple-long>
- <simpleBoolean>false</simpleBoolean>
- <dto-c>
- <dto-a-inner>
- <dto-a-inner-inner>
- <simple-arg>456</simple-arg>
- </dto-a-inner-inner>
- <simple-arg>44</simple-arg>
- </dto-a-inner>
- </dto-c>
- <simple-short>4</simple-short>
- <simple-BigInteger>999</simple-BigInteger>
- <simple-byte>4</simple-byte>
- <peers>
- <port>port1</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <peers>
- <port>port23</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
+ </dto_d>
+ <simpleInt>44</simpleInt>
+ <simple-test>545</simple-test>
+ <simple-long>454545</simple-long>
+ <simpleBoolean>false</simpleBoolean>
+ <dto-c>
+ <dto-a-inner>
+ <dto-a-inner-inner>
+ <simple-arg>456</simple-arg>
+ </dto-a-inner-inner>
+ <simple-arg>44</simple-arg>
+ </dto-a-inner>
+ </dto-c>
+ <simple-short>4</simple-short>
+ <simple-BigInteger>999</simple-BigInteger>
+ <simple-byte>4</simple-byte>
+ <peers>
+ <port>port1</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <peers>
+ <port>port23</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ </impl-netconf>
</module>
<module>
<type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
</type>
<name>instance-from-code</name>
-
- <ip xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">127.1.2.3</ip>
- <union-test-attr xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">randomStringForUnion</union-test-attr>
-
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <ip xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">127.1.2.3</ip>
+ <union-test-attr xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">randomStringForUnion</union-test-attr>
+ </impl-netconf>
</module>
</modules>
</type>
<name>test1</name>
-
- <simple-long-2>44</simple-long-2>
- <binaryLeaf>8545649856</binaryLeaf>
- <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
- <dto_d>
- <simple-int1>444</simple-int1>
- <simple-int2 xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">4444</simple-int2>
- <simple-int3>454</simple-int3>
- <complex-dto-bInner>
- <simple-int3>44</simple-int3>
- <deep>
- <simple-int3>4</simple-int3>
- </deep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-long-2>44</simple-long-2>
+ <binaryLeaf>8545649856</binaryLeaf>
+ <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
+ <dto_d>
+ <simple-int1>444</simple-int1>
+ <simple-int2 xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl2">4444</simple-int2>
+ <simple-int3>454</simple-int3>
+ <complex-dto-bInner>
+ <simple-int3>44</simple-int3>
+ <deep>
+ <simple-int3>4</simple-int3>
+ </deep>
+ <simple-list>4</simple-list>
+ </complex-dto-bInner>
<simple-list>4</simple-list>
- </complex-dto-bInner>
- <simple-list>4</simple-list>
- </dto_d>
- <simpleInt>44</simpleInt>
- <simple-test>545</simple-test>
- <simple-long>454545</simple-long>
- <simpleBoolean>false</simpleBoolean>
- <dto-c>
- <dto-a-inner>
- <dto-a-inner-inner>
- <simple-arg>456</simple-arg>
- </dto-a-inner-inner>
- <simple-arg>44</simple-arg>
- </dto-a-inner>
- </dto-c>
- <simple-short>4</simple-short>
- <simple-BigInteger>999</simple-BigInteger>
- <simple-byte>4</simple-byte>
- <peers>
- <port>port1</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <peers>
- <port>port23</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ </dto_d>
+ <simpleInt>44</simpleInt>
+ <simple-test>545</simple-test>
+ <simple-long>454545</simple-long>
+ <simpleBoolean>false</simpleBoolean>
+ <dto-c>
+ <dto-a-inner>
+ <dto-a-inner-inner>
+ <simple-arg>456</simple-arg>
+ </dto-a-inner-inner>
+ <simple-arg>44</simple-arg>
+ </dto-a-inner>
+ </dto-c>
+ <simple-short>4</simple-short>
+ <simple-BigInteger>999</simple-BigInteger>
+ <simple-byte>4</simple-byte>
+ <peers>
+ <port>port1</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <peers>
+ <port>port23</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
<module>
test-impl:impl-netconf
</type>
<name>test2</name>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
</modules>
</type>
</module>
+ <module>
+ <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ test-impl:impl
+ </type>
+
+ <name>testimpl</name>
+ <simpleInt>1</simpleInt>
+ <simpleInt xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">2</simpleInt>
+ </module>
+
<module>
<type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
test-impl:impl-netconf
</type>
<name>test1</name>
-
- <simple-long-2>44</simple-long-2>
- <simple-long-2 xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">44</simple-long-2>
- <binaryLeaf>8</binaryLeaf>
- <binaryLeaf>1</binaryLeaf>
- <binaryLeaf>0</binaryLeaf>
- <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
- <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
- <simple-int1>444</simple-int1>
- <simple-int2>4444</simple-int2>
- <simple-int3>454</simple-int3>
- <complex-dto-bInner>
- <simple-int3>44</simple-int3>
- <deep>
- <simple-int3>4</simple-int3>
- </deep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-long-2>44</simple-long-2>
+ <simple-long-2 xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">44</simple-long-2>
+ <binaryLeaf></binaryLeaf>
+ <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
+ <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-int1>444</simple-int1>
+ <simple-int2>4444</simple-int2>
+ <simple-int3>454</simple-int3>
+ <complex-dto-bInner>
+ <simple-int3>44</simple-int3>
+ <deep>
+ <simple-int3>4</simple-int3>
+ </deep>
+ <simple-list>4</simple-list>
+ </complex-dto-bInner>
<simple-list>4</simple-list>
- </complex-dto-bInner>
- <simple-list>4</simple-list>
- </dto_d>
- <simpleInt>44</simpleInt>
- <simple-test>545</simple-test>
- <simple-long>454545</simple-long>
- <simpleBoolean>false</simpleBoolean>
- <dto-c>
- <dto-a-inner>
- <dto-a-inner-inner>
- <simple-arg>456</simple-arg>
- </dto-a-inner-inner>
- <simple-arg>44</simple-arg>
- </dto-a-inner>
- </dto-c>
- <simple-short>4</simple-short>
- <simple-BigInteger>999</simple-BigInteger>
- <simple-byte>4</simple-byte>
- <peers>
- <port>port1</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <peers>
- <port>port23</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ </dto_d>
+ <simpleInt>44</simpleInt>
+ <simple-test>545</simple-test>
+ <simple-long>454545</simple-long>
+ <simpleBoolean>false</simpleBoolean>
+ <dto-c>
+ <dto-a-inner>
+ <dto-a-inner-inner>
+ <simple-arg>456</simple-arg>
+ </dto-a-inner-inner>
+ <simple-arg>44</simple-arg>
+ </dto-a-inner>
+ </dto-c>
+ <simple-short>4</simple-short>
+ <simple-BigInteger>999</simple-BigInteger>
+ <simple-byte>4</simple-byte>
+ <peers>
+ <port>port1</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <peers>
+ <port>port23</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
<module>
test-impl:impl-netconf
</type>
<name>test2</name>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
</modules>
<module>
<type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
- test-impl:impl-netconf
+ test-impl:impl
</type>
<name>test1</name>
-
- <simple-long-2>44</simple-long-2>
- <binaryLeaf>8</binaryLeaf>
- <binaryLeaf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">1</binaryLeaf>
- <binaryLeaf>0</binaryLeaf>
- <type xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">configAttributeType</type>
- <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
- <simple-int1>444</simple-int1>
- <simple-int2>4444</simple-int2>
- <simple-int3>454</simple-int3>
- <complex-dto-bInner>
- <simple-int3>44</simple-int3>
- <deep>
- <simple-int3>4</simple-int3>
- </deep>
- <simple-list>4</simple-list>
- </complex-dto-bInner>
- <simple-list>4</simple-list>
- </dto_d>
- <simpleInt>44</simpleInt>
- <simple-test>545</simple-test>
- <simple-long>454545</simple-long>
- <simpleBoolean>false</simpleBoolean>
- <dto-c>
- <dto-a-inner>
- <dto-a-inner-inner>
- <simple-arg>456</simple-arg>
- </dto-a-inner-inner>
- <simple-arg>44</simple-arg>
- </dto-a-inner>
- </dto-c>
- <simple-short>4</simple-short>
- <simple-BigInteger>999</simple-BigInteger>
- <simple-byte>4</simple-byte>
- <peers>
- <port>port1</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <peers>
- <port>port23</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ <allow-user>1</allow-user>
+ <allow-user xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">2</allow-user>
</module>
<module>
test-impl:impl-netconf
</type>
<name>test2</name>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
</modules>
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <service>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <instance>
- <name>ref_dep</name>
- <provider>/modules/module[type='impl-dep'][name='dep']
- </provider>
- </instance>
- <instance>
- <name>ref_dep_2</name>
- <provider>/modules/module[type='impl-dep'][name='dep2']
- </provider>
- </instance>
- <instance>
- <name>ref_test1</name>
- <provider>
- /modules/module[type='impl-netconf'][name='test1']
- </provider>
- </instance>
- </service>
+
</services>
</config>
</edit-config>
</type>
<name>test1</name>
-
- <simple-long-2>44</simple-long-2>
- <binaryLeaf>8545649856</binaryLeaf>
- <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
- <simple-int1>444</simple-int1>
- <simple-int2>4444</simple-int2>
- <simple-int3>454</simple-int3>
- <complex-dto-bInner>
- <simple-int3>44</simple-int3>
- <deep>
- <simple-int3>4</simple-int3>
- </deep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-long-2>44</simple-long-2>
+ <binaryLeaf>8545649856</binaryLeaf>
+ <dto_d xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-int1>444</simple-int1>
+ <simple-int2>4444</simple-int2>
+ <simple-int3>454</simple-int3>
+ <complex-dto-bInner>
+ <simple-int3>44</simple-int3>
+ <deep>
+ <simple-int3>4</simple-int3>
+ </deep>
+ <simple-list>4</simple-list>
+ </complex-dto-bInner>
<simple-list>4</simple-list>
- </complex-dto-bInner>
- <simple-list>4</simple-list>
- </dto_d>
- <simpleInt>44</simpleInt>
- <simple-test>545</simple-test>
- <simple-long>454545</simple-long>
- <simpleBoolean>false</simpleBoolean>
- <dto-c>
- <dto-a-inner>
- <dto-a-inner-inner>
- <simple-arg>456</simple-arg>
- </dto-a-inner-inner>
- <simple-arg>44</simple-arg>
- </dto-a-inner>
- </dto-c>
- <simple-short>4</simple-short>
- <simple-BigInteger>999</simple-BigInteger>
- <simple-byte>4</simple-byte>
- <peers>
- <port>port1</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <peers>
- <port>port23</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ </dto_d>
+ <simpleInt>44</simpleInt>
+ <simple-test>545</simple-test>
+ <simple-long>454545</simple-long>
+ <simpleBoolean>false</simpleBoolean>
+ <dto-c>
+ <dto-a-inner>
+ <dto-a-inner-inner>
+ <simple-arg>456</simple-arg>
+ </dto-a-inner-inner>
+ <simple-arg>44</simple-arg>
+ </dto-a-inner>
+ </dto-c>
+ <simple-short>4</simple-short>
+ <simple-BigInteger>999</simple-BigInteger>
+ <simple-byte>4</simple-byte>
+ <peers>
+ <port>port1</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <peers>
+ <port>port23</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
<module>
test-impl:impl-netconf
</type>
<name>test2</name>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
</modules>
</type>
<name>test1</name>
-
- <simple-long-2>44</simple-long-2>
- <binaryLeaf>8545649856</binaryLeaf>
- <dto_d>
- <unknownAttribute>error</unknownAttribute>
- <simple-int1>444</simple-int1>
- <simple-int2>4444</simple-int2>
- <simple-int3>454</simple-int3>
- <complex-dto-bInner>
- <simple-int3>44</simple-int3>
- <deep>
- <simple-int3>4</simple-int3>
- </deep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-long-2>44</simple-long-2>
+ <binaryLeaf>8545649856</binaryLeaf>
+ <dto_d>
+ <unknownAttribute>error</unknownAttribute>
+ <simple-int1>444</simple-int1>
+ <simple-int2>4444</simple-int2>
+ <simple-int3>454</simple-int3>
+ <complex-dto-bInner>
+ <simple-int3>44</simple-int3>
+ <deep>
+ <simple-int3>4</simple-int3>
+ </deep>
+ <simple-list>4</simple-list>
+ </complex-dto-bInner>
<simple-list>4</simple-list>
- </complex-dto-bInner>
- <simple-list>4</simple-list>
- </dto_d>
- <simpleInt>44</simpleInt>
- <simple-test>545</simple-test>
- <simple-long>454545</simple-long>
- <simpleBoolean>false</simpleBoolean>
- <dto-c>
- <dto-a-inner>
- <dto-a-inner-inner>
- <simple-arg>456</simple-arg>
- </dto-a-inner-inner>
- <simple-arg>44</simple-arg>
- </dto-a-inner>
- </dto-c>
- <simple-short>4</simple-short>
- <simple-BigInteger>999</simple-BigInteger>
- <simple-byte>4</simple-byte>
- <peers>
- <port>port1</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <peers>
- <port>port23</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ </dto_d>
+ <simpleInt>44</simpleInt>
+ <simple-test>545</simple-test>
+ <simple-long>454545</simple-long>
+ <simpleBoolean>false</simpleBoolean>
+ <dto-c>
+ <dto-a-inner>
+ <dto-a-inner-inner>
+ <simple-arg>456</simple-arg>
+ </dto-a-inner-inner>
+ <simple-arg>44</simple-arg>
+ </dto-a-inner>
+ </dto-c>
+ <simple-short>4</simple-short>
+ <simple-BigInteger>999</simple-BigInteger>
+ <simple-byte>4</simple-byte>
+ <peers>
+ <port>port1</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <peers>
+ <port>port23</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
<module>
test-impl:impl-netconf
</type>
<name>test2</name>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
</modules>
</type>
<name>test1</name>
-
- <simple-long-2>44</simple-long-2>
- <binaryLeaf>8545649856</binaryLeaf>
- <dto_d>
- <simple-int1>444</simple-int1>
- <simple-int2>4444</simple-int2>
- <simple-int3>454</simple-int3>
- <complex-dto-bInner>
- <simple-int3>44</simple-int3>
- <deep>
- <simple-int3>4</simple-int3>
- </deep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <simple-long-2>44</simple-long-2>
+ <binaryLeaf>8545649856</binaryLeaf>
+ <dto_d>
+ <simple-int1>444</simple-int1>
+ <simple-int2>4444</simple-int2>
+ <simple-int3>454</simple-int3>
+ <complex-dto-bInner>
+ <simple-int3>44</simple-int3>
+ <deep>
+ <simple-int3>4</simple-int3>
+ </deep>
+ <simple-list>4</simple-list>
+ </complex-dto-bInner>
<simple-list>4</simple-list>
- </complex-dto-bInner>
- <simple-list>4</simple-list>
- </dto_d>
- <simpleInt>44</simpleInt>
- <simple-test>545</simple-test>
- <simple-long>454545</simple-long>
- <simpleBoolean>false</simpleBoolean>
- <dto-c>
- <dto-a-inner>
- <dto-a-inner-inner>
- <simple-arg>456</simple-arg>
- </dto-a-inner-inner>
- <simple-arg>44</simple-arg>
- </dto-a-inner>
- </dto-c>
- <simple-short>4</simple-short>
- <simple-BigInteger>999</simple-BigInteger>
- <simple-byte>4</simple-byte>
- <peers>
- <port>port1</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- </peers>
- <peers>
- <port>port23</port>
- <simple-int3>456</simple-int3>
- <core-size>44</core-size>
- <unknownAttribute>error</unknownAttribute>
- </peers>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ </dto_d>
+ <simpleInt>44</simpleInt>
+ <simple-test>545</simple-test>
+ <simple-long>454545</simple-long>
+ <simpleBoolean>false</simpleBoolean>
+ <dto-c>
+ <dto-a-inner>
+ <dto-a-inner-inner>
+ <simple-arg>456</simple-arg>
+ </dto-a-inner-inner>
+ <simple-arg>44</simple-arg>
+ </dto-a-inner>
+ </dto-c>
+ <simple-short>4</simple-short>
+ <simple-BigInteger>999</simple-BigInteger>
+ <simple-byte>4</simple-byte>
+ <peers>
+ <port>port1</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ </peers>
+ <peers>
+ <port>port23</port>
+ <simple-int3>456</simple-int3>
+ <core-size>44</core-size>
+ <unknownAttribute>error</unknownAttribute>
+ </peers>
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
<module>
test-impl:impl-netconf
</type>
<name>test2</name>
- <testing-dep>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
- <name>ref_dep</name>
- </testing-dep>
+ <impl-netconf xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ <testing-dep>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+ <name>ref_dep</name>
+ </testing-dep>
+ </impl-netconf>
</module>
</modules>
<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>
import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
public class Activator extends ComponentActivatorAbstractBase {
NeutronRouterInterface.class,
NeutronPortInterface.class,
NeutronSubnetInterface.class,
- NeutronNetworkInterface.class };
+ NeutronNetworkInterface.class,
+ NeutronSecurityGroupInterface.class,
+ NeutronSecurityRuleInterface.class};
return res;
}
"setConfigurationContainerService",
"unsetConfigurationContainerService").setRequired(true));
}
+ if (imp.equals(NeutronSecurityGroupInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronSecurityGroupCRUD.class.getName(),
+ IConfigurationContainerAware.class.getName()}, null);
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("salListenerName", "neutron");
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IClusterContainerServices.class)
+ .setCallbacks("setClusterContainerService",
+ "unsetClusterContainerService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
+ }
+ if (imp.equals(NeutronSecurityRuleInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronSecurityRuleCRUD.class.getName(),
+ IConfigurationContainerAware.class.getName()}, null);
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("salListenerName", "neutron");
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IClusterContainerServices.class)
+ .setCallbacks("setClusterContainerService",
+ "unsetClusterContainerService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
+ }
}
}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.implementation;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class NeutronSecurityGroupInterface implements INeutronSecurityGroupCRUD, IConfigurationContainerAware, IObjectReader {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronSecurityGroupInterface.class);
+ private static final String FILE_NAME ="neutron.securitygroup.conf";
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
+ private ConcurrentMap<String, NeutronSecurityGroup> securityGroupDB;
+
+ // methods needed for creating caches
+ void setClusterContainerService(IClusterContainerServices s) {
+ logger.debug("Cluster Service set");
+ clusterContainerService = s;
+ }
+
+ void unsetClusterContainerService(IClusterContainerServices s) {
+ if (clusterContainerService == s) {
+ logger.debug("Cluster Service removed!");
+ clusterContainerService = null;
+ }
+ }
+
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ configurationService = null;
+ }
+
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron Security Groups");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronSecurityGroups",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron Security Groups - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron Security Groups already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron Security Groups");
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ private void retrieveCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron Security Groups");
+ securityGroupDB = (ConcurrentMap<String, NeutronSecurityGroup>) clusterContainerService
+ .getCache("neutronSecurityGroups");
+ if (securityGroupDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron Security Groups");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron Security Groups");
+ }
+
+ private void destroyCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for Neutron Security Groups");
+ clusterContainerService.destroyCache("neutronSecurityGroups");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ loadConfiguration();
+ }
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ void init(Component c) {
+ Dictionary<?, ?> props = c.getServiceProperties();
+ if (props != null) {
+ this.containerName = (String) props.get("containerName");
+ logger.debug("Running containerName: {}", this.containerName);
+ } else {
+ // In the Global instance case the containerName is empty
+ this.containerName = "";
+ }
+ startUp();
+ }
+
+ /**
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
+ */
+ void destroy() {
+ destroyCache();
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
+ */
+ void start() {
+ }
+
+ /**
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
+ */
+ void stop() {
+ }
+
+ // this method uses reflection to update an object from it's delta.
+
+ private boolean overwrite(Object target, Object delta) {
+ Method[] methods = target.getClass().getMethods();
+
+ for(Method toMethod: methods){
+ if(toMethod.getDeclaringClass().equals(target.getClass())
+ && toMethod.getName().startsWith("set")){
+
+ String toName = toMethod.getName();
+ String fromName = toName.replace("set", "get");
+
+ try {
+ Method fromMethod = delta.getClass().getMethod(fromName);
+ Object value = fromMethod.invoke(delta, (Object[])null);
+ if(value != null){
+ toMethod.invoke(target, value);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean neutronSecurityGroupExists(String uuid) {
+ return securityGroupDB.containsKey(uuid);
+ }
+
+ @Override
+ public NeutronSecurityGroup getNeutronSecurityGroup(String uuid) {
+ if (!neutronSecurityGroupExists(uuid)) {
+ logger.debug("No Security Groups Have Been Defined");
+ return null;
+ }
+ return securityGroupDB.get(uuid);
+ }
+
+ @Override
+ public List<NeutronSecurityGroup> getAllNeutronSecurityGroups() {
+ Set<NeutronSecurityGroup> allSecurityGroups = new HashSet<NeutronSecurityGroup>();
+ for (Entry<String, NeutronSecurityGroup> entry : securityGroupDB.entrySet()) {
+ NeutronSecurityGroup securityGroup = entry.getValue();
+ allSecurityGroups.add(securityGroup);
+ }
+ logger.debug("Exiting getSecurityGroups, Found {} OpenStackSecurityGroup", allSecurityGroups.size());
+ List<NeutronSecurityGroup> ans = new ArrayList<NeutronSecurityGroup>();
+ ans.addAll(allSecurityGroups);
+ return ans;
+ }
+
+ @Override
+ public boolean addNeutronSecurityGroup(NeutronSecurityGroup input) {
+ if (neutronSecurityGroupExists(input.getSecurityGroupUUID())) {
+ return false;
+ }
+ securityGroupDB.putIfAbsent(input.getSecurityGroupUUID(), input);
+ return true;
+ }
+
+ @Override
+ public boolean removeNeutronSecurityGroup(String uuid) {
+ if (!neutronSecurityGroupExists(uuid)) {
+ return false;
+ }
+ securityGroupDB.remove(uuid);
+ return true;
+ }
+
+ @Override
+ public boolean updateNeutronSecurityGroup(String uuid, NeutronSecurityGroup delta) {
+ if (!neutronSecurityGroupExists(uuid)) {
+ return false;
+ }
+ NeutronSecurityGroup target = securityGroupDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ @Override
+ public boolean neutronSecurityGroupInUse(String securityGroupUUID) {
+ return !neutronSecurityGroupExists(securityGroupUUID);
+ }
+
+ private void loadConfiguration() {
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronSecurityGroup nn = (NeutronSecurityGroup) conf;
+ securityGroupDB.put(nn.getSecurityGroupUUID(), nn);
+ }
+ }
+
+ @Override
+ public Status saveConfiguration() {
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(securityGroupDB.values()),
+ FILE_NAME);
+ }
+
+ @Override
+ public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+ return ois.readObject();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.implementation;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class NeutronSecurityRuleInterface implements INeutronSecurityRuleCRUD, IConfigurationContainerAware, IObjectReader {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronSecurityRuleInterface.class);
+ private static final String FILE_NAME = "neutron.securityrule.conf";
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
+ private ConcurrentMap<String, NeutronSecurityRule> securityRuleDB;
+
+ // methods needed for creating caches
+ void setClusterContainerService(IClusterContainerServices s) {
+ logger.debug("Cluster Service set");
+ clusterContainerService = s;
+ }
+
+ void unsetClusterContainerService(IClusterContainerServices s) {
+ if (clusterContainerService == s) {
+ logger.debug("Cluster Service removed!");
+ clusterContainerService = null;
+ }
+ }
+
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ configurationService = null;
+ }
+
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron Security Rules");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronSecurityRules",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron Security Rules - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron Security Rules already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron Security Rules");
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void retrieveCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron Security Rules");
+ securityRuleDB = (ConcurrentMap<String, NeutronSecurityRule>) clusterContainerService
+ .getCache("neutronSecurityRules");
+ if (securityRuleDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron Security Rules");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron Security Rules");
+ }
+
+ private void destroyCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for Neutron Security Rules");
+ clusterContainerService.destroyCache("neutronSecurityRules");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ loadConfiguration();
+ }
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ */
+ void init(Component c) {
+ Dictionary<?, ?> props = c.getServiceProperties();
+ if (props != null) {
+ this.containerName = (String) props.get("containerName");
+ logger.debug("Running containerName: {}", this.containerName);
+ } else {
+ // In the Global instance case the containerName is empty
+ this.containerName = "";
+ }
+ startUp();
+ }
+
+ /**
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ */
+ void destroy() {
+ destroyCache();
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ */
+ void start() {
+ }
+
+ /**
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ */
+ void stop() {
+ }
+
+ // this method uses reflection to update an object from it's delta.
+ private boolean overwrite(Object target, Object delta) {
+ Method[] methods = target.getClass().getMethods();
+
+ for (Method toMethod : methods) {
+ if (toMethod.getDeclaringClass().equals(target.getClass())
+ && toMethod.getName().startsWith("set")) {
+
+ String toName = toMethod.getName();
+ String fromName = toName.replace("set", "get");
+
+ try {
+ Method fromMethod = delta.getClass().getMethod(fromName);
+ Object value = fromMethod.invoke(delta, (Object[]) null);
+ if (value != null) {
+ toMethod.invoke(target, value);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean neutronSecurityRuleExists(String uuid) {
+ return securityRuleDB.containsKey(uuid);
+ }
+
+ @Override
+ public NeutronSecurityRule getNeutronSecurityRule(String uuid) {
+ if (!neutronSecurityRuleExists(uuid)) {
+ logger.debug("No Security Rules Have Been Defined");
+ return null;
+ }
+ return securityRuleDB.get(uuid);
+ }
+
+ @Override
+ public List<NeutronSecurityRule> getAllNeutronSecurityRules() {
+ Set<NeutronSecurityRule> allSecurityRules = new HashSet<NeutronSecurityRule>();
+ for (Entry<String, NeutronSecurityRule> entry : securityRuleDB.entrySet()) {
+ NeutronSecurityRule securityRule = entry.getValue();
+ allSecurityRules.add(securityRule);
+ }
+ logger.debug("Exiting getSecurityRule, Found {} OpenStackSecurityRule", allSecurityRules.size());
+ List<NeutronSecurityRule> ans = new ArrayList<NeutronSecurityRule>();
+ ans.addAll(allSecurityRules);
+ return ans;
+ }
+
+ @Override
+ public boolean addNeutronSecurityRule(NeutronSecurityRule input) {
+ if (neutronSecurityRuleExists(input.getSecurityRuleUUID())) {
+ return false;
+ }
+ securityRuleDB.putIfAbsent(input.getSecurityRuleUUID(), input);
+ return true;
+ }
+
+ @Override
+ public boolean removeNeutronSecurityRule(String uuid) {
+ if (!neutronSecurityRuleExists(uuid)) {
+ return false;
+ }
+ securityRuleDB.remove(uuid);
+ return true;
+ }
+
+ @Override
+ public boolean updateNeutronSecurityRule(String uuid, NeutronSecurityRule delta) {
+ if (!neutronSecurityRuleExists(uuid)) {
+ return false;
+ }
+ NeutronSecurityRule target = securityRuleDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ @Override
+ public boolean neutronSecurityRuleInUse(String securityRuleUUID) {
+ return !neutronSecurityRuleExists(securityRuleUUID);
+ }
+
+ private void loadConfiguration() {
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronSecurityRule nn = (NeutronSecurityRule) conf;
+ securityRuleDB.put(nn.getSecurityRuleUUID(), nn);
+ }
+ }
+
+ @Override
+ public Status saveConfiguration() {
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(securityRuleDB.values()),
+ FILE_NAME);
+ }
+
+ @Override
+ public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+ return ois.readObject();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Security Groups needs to implement
+ */
+
+public interface INeutronSecurityGroupAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified security group can be created
+ *
+ * @param securityGroup instance of proposed new Neutron Security Group object
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the create operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canCreateNeutronSecurityGroup(NeutronSecurityGroup securityGroup);
+
+ /**
+ * Services provide this interface method for taking action after a security group has been created
+ *
+ * @param securityGroup instance of new Neutron Security Group object
+ * @return void
+ */
+ public void neutronSecurityGroupCreated(NeutronSecurityGroup securityGroup);
+
+ /**
+ * Services provide this interface method to indicate if the specified security group can be changed using the specified
+ * delta
+ *
+ * @param delta updates to the security group object using patch semantics
+ * @param original instance of the Neutron Security Group object to be updated
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the update operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canUpdateNeutronSecurityGroup(NeutronSecurityGroup delta, NeutronSecurityGroup original);
+
+ /**
+ * Services provide this interface method for taking action after a security group has been updated
+ *
+ * @param securityGroup instance of modified Neutron Security Group object
+ * @return void
+ */
+ public void neutronSecurityGroupUpdated(NeutronSecurityGroup securityGroup);
+
+ /**
+ * Services provide this interface method to indicate if the specified security group can be deleted
+ *
+ * @param securityGroup instance of the Neutron Security Group object to be deleted
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the delete operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canDeleteNeutronSecurityGroup(NeutronSecurityGroup securityGroup);
+
+ /**
+ * Services provide this interface method for taking action after a security group has been deleted
+ *
+ * @param securityGroup instance of deleted Neutron Security Group object
+ * @return void
+ */
+ public void neutronSecurityGroupDeleted(NeutronSecurityGroup securityGroup);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB OpenStack Security Group objects
+ */
+
+public interface INeutronSecurityGroupCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ * Security Group object exists
+ *
+ * @param uuid UUID of the Security Group object
+ * @return boolean
+ */
+
+ public boolean neutronSecurityGroupExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * Security Group object exists
+ *
+ * @param uuid UUID of the Security Group object
+ * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup.OpenStackSecurity Groups}
+ * OpenStack Security Group class
+ */
+
+ public NeutronSecurityGroup getNeutronSecurityGroup(String uuid);
+
+ /**
+ * Applications call this interface method to return all Security Group objects
+ *
+ * @return List of OpenStackSecurity Groups objects
+ */
+
+ public List<NeutronSecurityGroup> getAllNeutronSecurityGroups();
+
+ /**
+ * Applications call this interface method to add a Security Group object to the
+ * concurrent map
+ *
+ * @param input OpenStackSecurity Group object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addNeutronSecurityGroup(NeutronSecurityGroup input);
+
+ /**
+ * Applications call this interface method to remove a Neutron Security Group object to the
+ * concurrent map
+ *
+ * @param uuid identifier for the security group object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeNeutronSecurityGroup(String uuid);
+
+ /**
+ * Applications call this interface method to edit a Security Group object
+ *
+ * @param uuid identifier of the security group object
+ * @param delta OpenStackSecurity Group object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateNeutronSecurityGroup(String uuid, NeutronSecurityGroup delta);
+
+ /**
+ * Applications call this interface method to see if a MAC address is in use
+ *
+ * @param uuid identifier of the security group object
+ * @return boolean on whether the Security Groups is already in use
+ */
+
+ public boolean neutronSecurityGroupInUse(String uuid);
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods required to be aware of Neutron Security Rules
+ */
+
+public interface INeutronSecurityRuleAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified security rule can be created
+ *
+ * @param securityRule instance of proposed new Neutron Security Rule object
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the create operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canCreateNeutronSecurityRule(NeutronSecurityRule securityRule);
+
+ /**
+ * Services provide this interface method for taking action after a security rule has been created
+ *
+ * @param securityRule instance of new Neutron Security Rule object
+ * @return void
+ */
+ public void neutronSecurityRuleCreated(NeutronSecurityRule securityRule);
+
+ /**
+ * Services provide this interface method to indicate if the specified security rule can be changed using the specified
+ * delta
+ *
+ * @param delta updates to the security rule object using patch semantics
+ * @param original instance of the Neutron Security Rule object to be updated
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the update operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canUpdateNeutronSecurityRule(NeutronSecurityRule delta, NeutronSecurityRule original);
+
+ /**
+ * Services provide this interface method for taking action after a security rule has been updated
+ *
+ * @param securityRule instance of modified Neutron Security Rule object
+ * @return void
+ */
+ public void neutronSecurityRuleUpdated(NeutronSecurityRule securityRule);
+
+ /**
+ * Services provide this interface method to indicate if the specified security rule can be deleted
+ *
+ * @param securityRule instance of the Neutron Security Rule object to be deleted
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the delete operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canDeleteNeutronSecurityRule(NeutronSecurityRule securityRule);
+
+ /**
+ * Services provide this interface method for taking action after a security rule has been deleted
+ *
+ * @param securityRule instance of deleted Neutron Security Rule object
+ * @return void
+ */
+ public void neutronSecurityRuleDeleted(NeutronSecurityRule securityRule);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB OpenStack Security Rule objects
+ */
+
+public interface INeutronSecurityRuleCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ * Security Rule object exists
+ *
+ * @param uuid UUID of theSecurity Rule object
+ * @return boolean
+ */
+
+ public boolean neutronSecurityRuleExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * Security Rule object exists
+ *
+ * @param uuid UUID of the security rule object
+ * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule.OpenStackNetworks}
+ * OpenStackSecurity Rule class
+ */
+
+ public NeutronSecurityRule getNeutronSecurityRule(String uuid);
+
+ /**
+ * Applications call this interface method to return all Security Rule objects
+ *
+ * @return List of OpenStack SecurityRules objects
+ */
+
+ public List<NeutronSecurityRule> getAllNeutronSecurityRules();
+
+ /**
+ * Applications call this interface method to add a Security Rule object to the
+ * concurrent map
+ *
+ * @param input OpenStack security rule object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addNeutronSecurityRule(NeutronSecurityRule input);
+
+ /**
+ * Applications call this interface method to remove a Neutron Security Rule object to the
+ * concurrent map
+ *
+ * @param uuid identifier for the security rule object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeNeutronSecurityRule(String uuid);
+
+ /**
+ * Applications call this interface method to edit aSecurity Rule object
+ *
+ * @param uuid identifier of the security rule object
+ * @param delta OpenStackSecurity Rule object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateNeutronSecurityRule(String uuid, NeutronSecurityRule delta);
+
+ /**
+ * Applications call this interface method to see if a MAC address is in use
+ *
+ * @param uuid identifier of the security rule object
+ * @return boolean on whether the macAddress is already associated with a
+ * port or not
+ */
+
+ public boolean neutronSecurityRuleInUse(String uuid);
+
+}
INeutronFloatingIPCRUD answer = (INeutronFloatingIPCRUD) ServiceHelper.getGlobalInstance(INeutronFloatingIPCRUD.class, o);
return answer;
}
-}
+
+ public static INeutronSecurityGroupCRUD getINeutronSecurityGroupCRUD(Object o) {
+ INeutronSecurityGroupCRUD answer = (INeutronSecurityGroupCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityGroupCRUD.class, o);
+ return answer;
+ }
+
+ public static INeutronSecurityRuleCRUD getINeutronSecurityRuleCRUD(Object o) {
+ INeutronSecurityRuleCRUD answer = (INeutronSecurityRuleCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityRuleCRUD.class, o);
+ return answer;
+ }
+}
\ No newline at end of file
@XmlElement (name="tenant_id")
String tenantID;
- // TODO: add security groups
- // @XmlElement (name="security_groups")
- // List<String> securityGroups;
+ @XmlElement (name="security_groups")
+ List<NeutronSecurityGroup> securityGroups;
/* this attribute stores the floating IP address assigned to
* each fixed IP address
this.tenantID = tenantID;
}
+ public List<NeutronSecurityGroup> getSecurityGroups() {
+ return securityGroups;
+ }
+
+ public void setSecurityGroups(List<NeutronSecurityGroup> securityGroups) {
+ this.securityGroups = securityGroups;
+ }
+
public NeutronFloatingIP getFloatingIP(String key) {
if (!floatingIPMap.containsKey(key)) {
return null;
return "NeutronPort [portUUID=" + portUUID + ", networkUUID=" + networkUUID + ", name=" + name
+ ", adminStateUp=" + adminStateUp + ", status=" + status + ", macAddress=" + macAddress
+ ", fixedIPs=" + fixedIPs + ", deviceID=" + deviceID + ", deviceOwner=" + deviceOwner + ", tenantID="
- + tenantID + ", floatingIPMap=" + floatingIPMap + "]";
+ + tenantID + ", floatingIPMap=" + floatingIPMap + ", securityGroups=" + securityGroups + "]";
}
}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OpenStack Neutron v2.0 Security Group bindings.
+ * See OpenStack Network API v2.0 Reference for description of
+ * annotated attributes. The current fields are as follows:
+ * <p/>
+ * id uuid-str unique ID for the security group.
+ * name String name of the security group.
+ * description String name of the security group.
+ * tenant_id uuid-str Owner of security rule..
+ * security_group_rules List<NeutronSecurityRule> nested RO in the sec group.
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronSecurityGroup extends ConfigurationObject implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @XmlElement(name = "id")
+ String securityGroupUUID;
+
+ @XmlElement(name = "name")
+ String securityGroupName;
+
+ @XmlElement(name = "description")
+ String securityGroupDescription;
+
+ @XmlElement(name = "tenant_id")
+ String securityGroupTenantID;
+
+ @XmlElement(name = "security_group_rules")
+ List<NeutronSecurityRule> neutronSecurityRule;
+
+ List<NeutronPort> neutronPorts;
+
+ public NeutronSecurityGroup() {
+ neutronPorts = new ArrayList<NeutronPort> ();
+ List<NeutronSecurityRule> securityRules;
+
+ }
+
+ public String getSecurityGroupUUID() {
+ return securityGroupUUID;
+ }
+
+ public void setSecurityGroupUUID(String securityGroupUUID) {
+ this.securityGroupUUID = securityGroupUUID;
+ }
+
+ public String getSecurityGroupName() {
+ return securityGroupName;
+ }
+
+ public void setSecurityGroupName(String securityGroupName) {
+ this.securityGroupName = securityGroupName;
+ }
+
+ public String getSecurityGroupDescription() {
+ return securityGroupDescription;
+ }
+
+ public void setSecurityGroupDescription(String securityGroupDescription) {
+ this.securityGroupDescription = securityGroupDescription;
+ }
+
+ public String getSecurityGroupTenantID() {
+ return securityGroupTenantID;
+ }
+
+ public void setSecurityGroupTenantID(String securityGroupTenantID) {
+ this.securityGroupTenantID = securityGroupTenantID;
+ }
+
+ // Rules In Group
+ public List<NeutronSecurityRule> getSecurityRules() {
+ return neutronSecurityRule;
+ }
+
+ public void setSecurityRules(NeutronSecurityRule neutronSecurityRule) {
+ this.neutronSecurityRule = (List<NeutronSecurityRule>) neutronSecurityRule;
+ }
+
+ public NeutronSecurityGroup extractFields(List<String> fields) {
+ NeutronSecurityGroup ans = new NeutronSecurityGroup ();
+ Iterator<String> i = fields.iterator ();
+ while (i.hasNext ()) {
+ String s = i.next ();
+ if (s.equals ("id")) {
+ ans.setSecurityGroupUUID (this.getSecurityGroupUUID ());
+ }
+ if (s.equals ("name")) {
+ ans.setSecurityGroupName (this.getSecurityGroupName ());
+ }
+ if (s.equals ("description")) {
+ ans.setSecurityGroupDescription (this.getSecurityGroupDescription ());
+ }
+ if (s.equals ("tenant_id")) {
+ ans.setSecurityGroupTenantID (this.getSecurityGroupTenantID ());
+ }
+ if (s.equals ("security_group_rules")) {
+ ans.setSecurityRules ((NeutronSecurityRule) this.getSecurityRules ());
+ }
+ }
+ return ans;
+ }
+
+ @Override
+ public String toString() {
+ return "NeutronSecurityGroup{" +
+ "securityGroupUUID='" + securityGroupUUID + '\'' +
+ ", securityGroupName='" + securityGroupName + '\'' +
+ ", securityGroupDescription='" + securityGroupDescription + '\'' +
+ ", securityGroupTenantID='" + securityGroupTenantID + '\'' +
+ ", securityRules=" + neutronSecurityRule + "]";
+ }
+
+ public void initDefaults() {
+ //TODO verify no defaults values are nessecary required.
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron;
+
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * See OpenStack Network API v2.0 Reference for description of
+ * annotated attributes. The current fields are as follows:
+ * <p/>
+ * id uuid (String) UUID for the security group rule.
+ * security_rule_id uuid (String) The security group to associate rule.
+ * direction String Direction the VM traffic (ingress/egress).
+ * security_group_id The security group to associate rule with.
+ * protocol String IP Protocol (icmp, tcp, udp, etc).
+ * port_range_min Integer Port at start of range
+ * port_range_max Integer Port at end of range
+ * ethertype String ethertype in L2 packet (IPv4, IPv6, etc)
+ * remote_ip_prefix String (IP cidr) CIDR for address range.
+ * remote_group_id uuid-str Source security group to apply to rule.
+ * tenant_id uuid-str Owner of security rule. Admin only outside tenant.
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronSecurityRule extends ConfigurationObject implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @XmlElement(name = "id")
+ String securityRuleUUID;
+
+ @XmlElement(name = "direction")
+ String securityRuleDirection;
+
+ @XmlElement(name = "protocol")
+ String securityRuleProtocol;
+
+ @XmlElement(name = "port_range_min")
+ Integer securityRulePortMin;
+
+ @XmlElement(name = " port_range_max")
+ Integer securityRulePortMax;
+
+ @XmlElement(name = "ethertype")
+ String securityRuleEthertype;
+
+ @XmlElement(name = "remote_ip_prefix")
+ String securityRuleRemoteIpPrefix;
+
+ @XmlElement(name = "remote_group_id")
+ String securityRemoteGroupID;
+
+ @XmlElement(name = "security_group_id")
+ String securityRuleGroupID;
+
+ @XmlElement(name = "tenant_id")
+ String securityRuleTenantID;
+
+ public NeutronSecurityRule() {
+ List<NeutronSecurityRule> securityRules;
+ }
+
+ public String getSecurityRuleUUID() {
+ return securityRuleUUID;
+ }
+
+ public void setSecurityRuleUUID(String securityRuleUUID) {
+ this.securityRuleUUID = securityRuleUUID;
+ }
+
+ public String getSecurityRuleDirection() {
+ return securityRuleDirection;
+ }
+
+ public void setSecurityRuleDirection(String securityRuleDirection) {
+ this.securityRuleDirection = securityRuleDirection;
+ }
+
+ public String getSecurityRuleProtocol() {
+ return securityRuleProtocol;
+ }
+
+ public void setSecurityRuleProtocol(String securityRuleProtocol) {
+ this.securityRuleProtocol = securityRuleProtocol;
+ }
+
+ public Integer getSecurityRulePortMin() {
+ return securityRulePortMin;
+ }
+
+ public void setSecurityRulePortMin(Integer securityRulePortMin) {
+ this.securityRulePortMin = securityRulePortMin;
+ }
+
+ public Integer getSecurityRulePortMax() {
+ return securityRulePortMax;
+ }
+
+ public void setSecurityRulePortMax(Integer securityRulePortMax) {
+ this.securityRulePortMax = securityRulePortMax;
+ }
+
+ public String getSecurityRuleEthertype() {
+ return securityRuleEthertype;
+ }
+
+ public void setSecurityRuleEthertype(String securityRuleEthertype) {
+ this.securityRuleEthertype = securityRuleEthertype;
+ }
+
+ public String getSecurityRuleRemoteIpPrefix() {
+ return securityRuleRemoteIpPrefix;
+ }
+
+ public void setSecurityRuleRemoteIpPrefix(String securityRuleRemoteIpPrefix) {
+ this.securityRuleRemoteIpPrefix = securityRuleRemoteIpPrefix;
+ }
+
+ public String getSecurityRemoteGroupID() {
+ return securityRemoteGroupID;
+ }
+
+ public void setSecurityRemoteGroupID(String securityRemoteGroupID) {
+ this.securityRemoteGroupID = securityRemoteGroupID;
+ }
+
+ public String getSecurityRuleGroupID() {
+ return securityRuleGroupID;
+ }
+
+ public void setSecurityRuleGroupID(String securityRuleGroupID) {
+ this.securityRuleGroupID = securityRuleGroupID;
+ }
+
+ public String getSecurityRuleTenantID() {
+ return securityRuleTenantID;
+ }
+
+ public void setSecurityRuleTenantID(String securityRuleTenantID) {
+ this.securityRuleTenantID = securityRuleTenantID;
+ }
+
+ public NeutronSecurityRule extractFields(List<String> fields) {
+ NeutronSecurityRule ans = new NeutronSecurityRule();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setSecurityRuleUUID(this.getSecurityRuleUUID());
+ }
+ if (s.equals("direction")) {
+ ans.setSecurityRuleDirection(this.getSecurityRuleDirection());
+ }
+ if (s.equals("protocol")) {
+ ans.setSecurityRuleProtocol(this.getSecurityRuleProtocol());
+ }
+ if (s.equals("port_range_min")) {
+ ans.setSecurityRulePortMin(this.getSecurityRulePortMin());
+ }
+ if (s.equals("port_range_max")) {
+ ans.setSecurityRulePortMax(this.getSecurityRulePortMax());
+ }
+ if (s.equals("ethertype")) {
+ ans.setSecurityRuleEthertype(this.getSecurityRuleEthertype());
+ }
+ if (s.equals("remote_ip_prefix")) {
+ ans.setSecurityRuleRemoteIpPrefix(this.getSecurityRuleRemoteIpPrefix());
+ }
+ if (s.equals("remote_group_id")) {
+ ans.setSecurityRemoteGroupID(this.getSecurityRemoteGroupID());
+ }
+ if (s.equals("security_group_id")) {
+ ans.setSecurityRuleGroupID(this.getSecurityRuleGroupID());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setSecurityRuleTenantID(this.getSecurityRuleTenantID());
+ }
+ }
+ return ans;
+ }
+
+ @Override
+ public String toString() {
+ return "NeutronSecurityRule{" +
+ "securityRuleUUID='" + securityRuleUUID + '\'' +
+ ", securityRuleDirection='" + securityRuleDirection + '\'' +
+ ", securityRuleProtocol='" + securityRuleProtocol + '\'' +
+ ", securityRulePortMin=" + securityRulePortMin +
+ ", securityRulePortMax=" + securityRulePortMax +
+ ", securityRuleEthertype='" + securityRuleEthertype + '\'' +
+ ", securityRuleRemoteIpPrefix='" + securityRuleRemoteIpPrefix + '\'' +
+ ", securityRemoteGroupID=" + securityRemoteGroupID +
+ ", securityRuleGroupID='" + securityRuleGroupID + '\'' +
+ ", securityRuleTenantID='" + securityRuleTenantID + '\'' +
+ '}';
+ }
+
+ public void initDefaults() {
+ //TODO verify no defaults values are nessecary required.
+ }
+}
\ No newline at end of file
classes.add(NeutronPortsNorthbound.class);
classes.add(NeutronRoutersNorthbound.class);
classes.add(NeutronFloatingIPsNorthbound.class);
+ classes.add(NeutronSecurityGroupsNorthbound.class);
+ classes.add(NeutronSecurityRulesNorthbound.class);
return classes;
}
if (portInterface.macInUse(singleton.getMacAddress())) {
throw new ResourceConflictException("MAC Address is in use.");
}
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
- if (instances != null) {
- for (Object instance : instances) {
- INeutronPortAware service = (INeutronPortAware) instance;
- int status = service.canCreatePort(singleton);
- if (status < 200 || status > 299) {
- return Response.status(status).build();
- }
- }
- }
/*
* if fixed IPs are specified, each one has to have an existing subnet ID
* that is in the same scoping network as the port. In addition, if an IP
}
}
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ int status = service.canCreatePort(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+
// add the port to the cache
portInterface.addPort(singleton);
if (instances != null) {
if (portInterface.macInUse(test.getMacAddress())) {
throw new ResourceConflictException("MAC address in use");
}
- if (instances != null) {
- for (Object instance : instances) {
- INeutronPortAware service = (INeutronPortAware) instance;
- int status = service.canCreatePort(test);
- if (status < 200 || status > 299) {
- return Response.status(status).build();
- }
- }
- }
+
/*
* if fixed IPs are specified, each one has to have an existing subnet ID
* that is in the same scoping network as the port. In addition, if an IP
}
}
}
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ int status = service.canCreatePort(test);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
}
//once everything has passed, then we can add to the cache
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.List;
+
+
+@XmlRootElement
+@XmlAccessorType (XmlAccessType.NONE)
+
+public class NeutronSecurityGroupRequest {
+ /**
+ * See OpenStack Network API v2.0 Reference for a
+ * description of annotated attributes and operations
+ */
+
+ @XmlElement (name = "security_group")
+ NeutronSecurityGroup singletonSecurityGroup;
+
+ @XmlElement (name = "security_groups")
+ List<NeutronSecurityGroup> bulkRequest;
+
+ NeutronSecurityGroupRequest() {
+ }
+
+ NeutronSecurityGroupRequest(List<NeutronSecurityGroup> bulk) {
+ bulkRequest = bulk;
+ singletonSecurityGroup = null;
+ }
+
+ NeutronSecurityGroupRequest(NeutronSecurityGroup group) {
+ singletonSecurityGroup = group;
+ }
+
+ public List<NeutronSecurityGroup> getBulk() {
+ return bulkRequest;
+ }
+
+ public NeutronSecurityGroup getSingleton() {
+ return singletonSecurityGroup;
+ }
+
+ public boolean isSingleton() {
+ return (singletonSecurityGroup != null);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.northbound;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Neutron Northbound REST APIs for Security Group.<br>
+ * This class provides REST APIs for managing neutron Security Group
+ * <p/>
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ */
+@Path ("/security-groups")
+public class NeutronSecurityGroupsNorthbound {
+ static final Logger logger = LoggerFactory.getLogger(NeutronSecurityGroupsNorthbound.class);
+
+ private NeutronSecurityGroup extractFields(NeutronSecurityGroup o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all Security Groups
+ */
+ @GET
+ @Produces ({MediaType.APPLICATION_JSON})
+ @StatusCodes ({
+ @ResponseCode (code = 200, condition = "Operation successful"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+
+ public Response listGroups(
+ // return fields
+ @QueryParam ("fields") List<String> fields,
+ // OpenStack security group attributes
+ @QueryParam ("id") String querySecurityGroupUUID,
+ @QueryParam ("name") String querySecurityGroupName,
+ @QueryParam ("description") String querySecurityDescription,
+ @QueryParam ("tenant_id") String querySecurityTenantID,
+ @QueryParam ("limit") String limit,
+ @QueryParam ("marker") String marker,
+ @QueryParam ("page_reverse") String pageReverse
+ ) {
+ INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+
+ if (securityGroupInterface == null) {
+ throw new ServiceUnavailableException("Security Group CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronSecurityGroup> allSecurityGroups = securityGroupInterface.getAllNeutronSecurityGroups();
+ List<NeutronSecurityGroup> ans = new ArrayList<NeutronSecurityGroup>();
+ Iterator<NeutronSecurityGroup> i = allSecurityGroups.iterator();
+ while (i.hasNext()) {
+ NeutronSecurityGroup nsg = i.next();
+ if ((querySecurityGroupUUID == null ||
+ querySecurityGroupUUID.equals(nsg.getSecurityGroupUUID())) &&
+ (querySecurityGroupName == null ||
+ querySecurityGroupName.equals(nsg.getSecurityGroupName())) &&
+ (querySecurityDescription == null ||
+ querySecurityDescription.equals(nsg.getSecurityGroupDescription())) &&
+ (querySecurityTenantID == null ||
+ querySecurityTenantID.equals(nsg.getSecurityGroupTenantID()))) {
+ if (fields.size() > 0) {
+ ans.add(extractFields(nsg, fields));
+ } else {
+ ans.add(nsg);
+ }
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronSecurityGroupRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific Security Group
+ */
+
+ @Path ("{securityGroupUUID}")
+ @GET
+ @Produces ({MediaType.APPLICATION_JSON})
+ @StatusCodes ({
+ @ResponseCode (code = 200, condition = "Operation successful"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 404, condition = "Not Found"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+ public Response showSecurityGroup(@PathParam ("securityGroupUUID") String securityGroupUUID,
+ // return fields
+ @QueryParam ("fields") List<String> fields) {
+ INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+ if (securityGroupInterface == null) {
+ throw new ServiceUnavailableException("Security Group CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) {
+ throw new ResourceNotFoundException("Security Group UUID does not exist.");
+ }
+ if (!fields.isEmpty()) {
+ NeutronSecurityGroup ans = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
+ return Response.status(200).entity(
+ new NeutronSecurityGroupRequest(extractFields(ans, fields))).build();
+ } else {
+ return Response.status(200).entity(new NeutronSecurityGroupRequest(securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID))).build();
+ }
+ }
+
+ /**
+ * Creates new Security Group
+ */
+
+ @POST
+ @Produces ({MediaType.APPLICATION_JSON})
+ @Consumes ({MediaType.APPLICATION_JSON})
+ @StatusCodes ({
+ @ResponseCode (code = 201, condition = "Created"),
+ @ResponseCode (code = 400, condition = "Bad Request"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 403, condition = "Forbidden"),
+ @ResponseCode (code = 404, condition = "Not Found"),
+ @ResponseCode (code = 409, condition = "Conflict"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+ public Response createSecurityGroups(final NeutronSecurityGroupRequest input) {
+ INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+ if (securityGroupInterface == null) {
+ throw new ServiceUnavailableException("Security Group CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ if (input.isSingleton()) {
+ NeutronSecurityGroup singleton = input.getSingleton();
+
+ /*
+ * Verify that the Security Group doesn't already exist.
+ */
+ if (securityGroupInterface.neutronSecurityGroupExists(singleton.getSecurityGroupUUID())) {
+ throw new BadRequestException("Security Group UUID already exists");
+ }
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+ int status = service.canCreateNeutronSecurityGroup(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ // Add to Neutron cache
+ securityGroupInterface.addNeutronSecurityGroup(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+ service.neutronSecurityGroupCreated(singleton);
+ }
+ }
+ } else {
+ List<NeutronSecurityGroup> bulk = input.getBulk();
+ Iterator<NeutronSecurityGroup> i = bulk.iterator();
+ HashMap<String, NeutronSecurityGroup> testMap = new HashMap<String, NeutronSecurityGroup>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronSecurityGroup test = i.next();
+
+ /*
+ * Verify that the security group doesn't already exist
+ */
+
+ if (securityGroupInterface.neutronSecurityGroupExists(test.getSecurityGroupUUID())) {
+ throw new BadRequestException("Security Group UUID already is already created");
+ }
+ if (instances != null) for (Object instance : instances) {
+ INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+ int status = service.canCreateNeutronSecurityGroup(test);
+ if ((status < 200) || (status > 299)) return Response.status(status).build();
+ }
+ }
+
+ /*
+ * now, each element of the bulk request can be added to the cache
+ */
+ i = bulk.iterator();
+ while (i.hasNext()) {
+ NeutronSecurityGroup test = i.next();
+ securityGroupInterface.addNeutronSecurityGroup(test);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+ service.neutronSecurityGroupCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a Security Group
+ */
+
+ @Path ("{securityGroupUUID}")
+ @PUT
+ @Produces ({MediaType.APPLICATION_JSON})
+ @Consumes ({MediaType.APPLICATION_JSON})
+ @StatusCodes ({
+ @ResponseCode (code = 200, condition = "Operation successful"),
+ @ResponseCode (code = 400, condition = "Bad Request"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 403, condition = "Forbidden"),
+ @ResponseCode (code = 404, condition = "Not Found"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+ public Response updateSecurityGroup(
+ @PathParam ("securityGroupUUID") String securityGroupUUID, final NeutronSecurityGroupRequest input) {
+ INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+ if (securityGroupInterface == null) {
+ throw new ServiceUnavailableException("Security Group CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the Security Group exists and there is only one delta provided
+ */
+ if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) {
+ throw new ResourceNotFoundException("Security Group UUID does not exist.");
+ }
+ if (!input.isSingleton()) {
+ throw new BadRequestException("Only singleton edit supported");
+ }
+ NeutronSecurityGroup delta = input.getSingleton();
+ NeutronSecurityGroup original = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
+
+ if (delta.getSecurityGroupUUID() != null ||
+ delta.getSecurityGroupTenantID() != null ||
+ delta.getSecurityGroupName() != null ||
+ delta.getSecurityGroupDescription() != null) {
+ throw new BadRequestException("Attribute edit blocked by Neutron");
+ }
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+ int status = service.canUpdateNeutronSecurityGroup(delta, original);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * update the object and return it
+ */
+ securityGroupInterface.updateNeutronSecurityGroup(securityGroupUUID, delta);
+ NeutronSecurityGroup updatedSecurityGroup = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+ service.neutronSecurityGroupUpdated(updatedSecurityGroup);
+ }
+ }
+ return Response.status(200).entity(new NeutronSecurityGroupRequest(securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID))).build();
+ }
+
+ /**
+ * Deletes a Security Group
+ */
+
+ @Path ("{securityGroupUUID}")
+ @DELETE
+ @StatusCodes ({
+ @ResponseCode (code = 204, condition = "No Content"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 404, condition = "Not Found"),
+ @ResponseCode (code = 409, condition = "Conflict"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+ public Response deleteSecurityGroup(
+ @PathParam ("securityGroupUUID") String securityGroupUUID) {
+ INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+ if (securityGroupInterface == null) {
+ throw new ServiceUnavailableException("Security Group CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the Security Group exists and it isn't currently in use
+ */
+ if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) {
+ throw new ResourceNotFoundException("Security Group UUID does not exist.");
+ }
+ if (securityGroupInterface.neutronSecurityGroupInUse(securityGroupUUID)) {
+ return Response.status(409).build();
+ }
+ NeutronSecurityGroup singleton = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+ int status = service.canDeleteNeutronSecurityGroup(singleton);
+ if ((status < 200) || (status > 299)) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * remove it and return 204 status
+ */
+ securityGroupInterface.removeNeutronSecurityGroup(securityGroupUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance;
+ service.neutronSecurityGroupDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.List;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronSecurityRuleRequest {
+ /**
+ * See OpenStack Network API v2.0 Reference for a
+ * description of annotated attributes and operations
+ */
+
+ @XmlElement(name="security_group_rule")
+ NeutronSecurityRule singletonSecurityRule;
+
+ @XmlElement(name="security_group_rules")
+ List<NeutronSecurityRule> bulkRequest;
+
+ NeutronSecurityRuleRequest() {
+ }
+
+ NeutronSecurityRuleRequest(List<NeutronSecurityRule> bulk) {
+ bulkRequest = bulk;
+ singletonSecurityRule = null;
+ }
+
+ NeutronSecurityRuleRequest(NeutronSecurityRule rule) {
+ singletonSecurityRule = rule;
+ }
+
+ public NeutronSecurityRule getSingleton() {
+ return singletonSecurityRule;
+ }
+
+ public boolean isSingleton() {
+ return (singletonSecurityRule != null);
+ }
+ public List<NeutronSecurityRule> getBulk() {
+ return bulkRequest;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.networkconfig.neutron.northbound;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Neutron Northbound REST APIs for Security Rule.<br>
+ * This class provides REST APIs for managing neutron Security Rule
+ * <p/>
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ */
+
+@Path ("/security-group-rules")
+public class NeutronSecurityRulesNorthbound {
+ static final Logger logger = LoggerFactory.getLogger(NeutronSecurityRulesNorthbound.class);
+
+ private NeutronSecurityRule extractFields(NeutronSecurityRule o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all Security Rules
+ */
+ @GET
+ @Produces ({MediaType.APPLICATION_JSON})
+ @StatusCodes ({
+ @ResponseCode (code = 200, condition = "Operation successful"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+ public Response listRules(
+ // return fields
+ @QueryParam ("fields") List<String> fields,
+ // OpenStack security rule attributes
+ @QueryParam ("id") String querySecurityRuleUUID,
+ @QueryParam ("direction") String querySecurityRuleDirection,
+ @QueryParam ("protocol") String querySecurityRuleProtocol,
+ @QueryParam ("port_range_min") Integer querySecurityRulePortMin,
+ @QueryParam ("port_range_max") Integer querySecurityRulePortMax,
+ @QueryParam ("ethertype") String querySecurityRuleEthertype,
+ @QueryParam ("remote_ip_prefix") String querySecurityRuleIpPrefix,
+ @QueryParam ("remote_group_id") String querySecurityRemoteGroupID,
+ @QueryParam ("security_group_id") String querySecurityRuleGroupID,
+ @QueryParam ("tenant_id") String querySecurityRuleTenantID,
+ @QueryParam ("limit") String limit,
+ @QueryParam ("marker") String marker,
+ @QueryParam ("page_reverse") String pageReverse
+ ) {
+ INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+ if (securityRuleInterface == null) {
+ throw new ServiceUnavailableException("Security Rule CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronSecurityRule> allSecurityRules = securityRuleInterface.getAllNeutronSecurityRules();
+ List<NeutronSecurityRule> ans = new ArrayList<NeutronSecurityRule>();
+ Iterator<NeutronSecurityRule> i = allSecurityRules.iterator();
+ while (i.hasNext()) {
+ NeutronSecurityRule nsr = i.next();
+ if ((querySecurityRuleUUID == null ||
+ querySecurityRuleUUID.equals(nsr.getSecurityRuleUUID())) &&
+ (querySecurityRuleDirection == null ||
+ querySecurityRuleDirection.equals(nsr.getSecurityRuleDirection())) &&
+ (querySecurityRuleProtocol == null ||
+ querySecurityRuleProtocol.equals(nsr.getSecurityRuleProtocol())) &&
+ (querySecurityRulePortMin == null ||
+ querySecurityRulePortMin.equals(nsr.getSecurityRulePortMin())) &&
+ (querySecurityRulePortMax == null ||
+ querySecurityRulePortMax.equals(nsr.getSecurityRulePortMax())) &&
+ (querySecurityRuleEthertype == null ||
+ querySecurityRuleEthertype.equals(nsr.getSecurityRuleEthertype())) &&
+ (querySecurityRuleIpPrefix == null ||
+ querySecurityRuleIpPrefix.equals(nsr.getSecurityRuleRemoteIpPrefix())) &&
+ (querySecurityRuleGroupID == null ||
+ querySecurityRuleGroupID.equals(nsr.getSecurityRuleGroupID())) &&
+ (querySecurityRemoteGroupID == null ||
+ querySecurityRemoteGroupID.equals(nsr.getSecurityRemoteGroupID())) &&
+ (querySecurityRuleTenantID == null ||
+ querySecurityRuleTenantID.equals(nsr.getSecurityRuleTenantID()))) {
+ if (fields.size() > 0) {
+ ans.add(extractFields(nsr, fields));
+ } else {
+ ans.add(nsr);
+ }
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronSecurityRuleRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific Security Rule
+ */
+
+ @Path ("{securityRuleUUID}")
+ @GET
+ @Produces ({MediaType.APPLICATION_JSON})
+ @StatusCodes ({
+ @ResponseCode (code = 200, condition = "Operation successful"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 404, condition = "Not Found"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+ public Response showSecurityRule(@PathParam ("securityRuleUUID") String securityRuleUUID,
+ // return fields
+ @QueryParam ("fields") List<String> fields) {
+ INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+ if (securityRuleInterface == null) {
+ throw new ServiceUnavailableException("Security Rule CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) {
+ throw new ResourceNotFoundException("Security Rule UUID does not exist.");
+ }
+ if (!fields.isEmpty()) {
+ NeutronSecurityRule ans = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
+ return Response.status(200).entity(
+ new NeutronSecurityRuleRequest(extractFields(ans, fields))).build();
+ } else {
+ return Response.status(200).entity(new NeutronSecurityRuleRequest(securityRuleInterface.getNeutronSecurityRule(securityRuleUUID))).build();
+ }
+ }
+
+ /**
+ * Creates new Security Rule
+ */
+
+ @POST
+ @Produces ({MediaType.APPLICATION_JSON})
+ @Consumes ({MediaType.APPLICATION_JSON})
+ @StatusCodes ({
+ @ResponseCode (code = 201, condition = "Created"),
+ @ResponseCode (code = 400, condition = "Bad Request"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 403, condition = "Forbidden"),
+ @ResponseCode (code = 404, condition = "Not Found"),
+ @ResponseCode (code = 409, condition = "Conflict"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+ public Response createSecurityRules(final NeutronSecurityRuleRequest input) {
+ INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+ if (securityRuleInterface == null) {
+ throw new ServiceUnavailableException("Security Rule CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this);
+ if (securityGroupInterface == null) {
+ throw new ServiceUnavailableException("Security Group CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * Existing entry checks
+ */
+
+ if (input.isSingleton()) {
+ NeutronSecurityRule singleton = input.getSingleton();
+
+ if (securityRuleInterface.neutronSecurityRuleExists(singleton.getSecurityRuleUUID())) {
+ throw new BadRequestException("Security Rule UUID already exists");
+ }
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+ int status = service.canCreateNeutronSecurityRule(singleton);
+ if ((status < 200) || (status > 299)) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ // add rule to cache
+ singleton.initDefaults();
+ securityRuleInterface.addNeutronSecurityRule(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+ service.neutronSecurityRuleCreated(singleton);
+ }
+ }
+
+ securityRuleInterface.addNeutronSecurityRule(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+ service.neutronSecurityRuleCreated(singleton);
+ }
+ }
+ } else {
+ List<NeutronSecurityRule> bulk = input.getBulk();
+ Iterator<NeutronSecurityRule> i = bulk.iterator();
+ HashMap<String, NeutronSecurityRule> testMap = new HashMap<String, NeutronSecurityRule>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronSecurityRule test = i.next();
+
+ /*
+ * Verify that the security rule doesn't already exist
+ */
+
+ if (securityRuleInterface.neutronSecurityRuleExists(test.getSecurityRuleUUID())) {
+ throw new BadRequestException("Security Rule UUID already exists");
+ }
+ if (testMap.containsKey(test.getSecurityRuleUUID())) {
+ throw new BadRequestException("Security Rule UUID already exists");
+ }
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+ int status = service.canCreateNeutronSecurityRule(test);
+ if ((status < 200) || (status > 299)) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ }
+
+ /*
+ * now, each element of the bulk request can be added to the cache
+ */
+ i = bulk.iterator();
+ while (i.hasNext()) {
+ NeutronSecurityRule test = i.next();
+ securityRuleInterface.addNeutronSecurityRule(test);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+ service.neutronSecurityRuleCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a Security Rule
+ */
+
+ @Path ("{securityRuleUUID}")
+ @PUT
+ @Produces ({MediaType.APPLICATION_JSON})
+ @Consumes ({MediaType.APPLICATION_JSON})
+ @StatusCodes ({
+ @ResponseCode (code = 200, condition = "Operation successful"),
+ @ResponseCode (code = 400, condition = "Bad Request"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 403, condition = "Forbidden"),
+ @ResponseCode (code = 404, condition = "Not Found"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+ public Response updateSecurityRule(
+ @PathParam ("securityRuleUUID") String securityRuleUUID, final NeutronSecurityRuleRequest input) {
+ INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+ if (securityRuleInterface == null) {
+ throw new ServiceUnavailableException("Security Rule CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the Security Rule exists and there is only one delta provided
+ */
+ if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) {
+ throw new ResourceNotFoundException("Security Rule UUID does not exist.");
+ }
+ if (!input.isSingleton()) {
+ throw new BadRequestException("Only singleton edit supported");
+ }
+ NeutronSecurityRule delta = input.getSingleton();
+ NeutronSecurityRule original = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
+
+ /*
+ * updates restricted by Neutron
+ *
+ */
+ if (delta.getSecurityRuleUUID() != null ||
+ delta.getSecurityRuleDirection() != null ||
+ delta.getSecurityRuleProtocol() != null ||
+ delta.getSecurityRulePortMin() != null ||
+ delta.getSecurityRulePortMax() != null ||
+ delta.getSecurityRuleEthertype() != null ||
+ delta.getSecurityRuleRemoteIpPrefix() != null ||
+ delta.getSecurityRuleGroupID() != null ||
+ delta.getSecurityRemoteGroupID() != null ||
+ delta.getSecurityRuleTenantID() != null) {
+ throw new BadRequestException("Attribute edit blocked by Neutron");
+ }
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+ int status = service.canUpdateNeutronSecurityRule(delta, original);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * update the object and return it
+ */
+ securityRuleInterface.updateNeutronSecurityRule(securityRuleUUID, delta);
+ NeutronSecurityRule updatedSecurityRule = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+ service.neutronSecurityRuleUpdated(updatedSecurityRule);
+ }
+ }
+ return Response.status(200).entity(new NeutronSecurityRuleRequest(securityRuleInterface.getNeutronSecurityRule(securityRuleUUID))).build();
+ }
+
+ /**
+ * Deletes a Security Rule
+ */
+
+ @Path ("{securityRuleUUID}")
+ @DELETE
+ @StatusCodes ({
+ @ResponseCode (code = 204, condition = "No Content"),
+ @ResponseCode (code = 401, condition = "Unauthorized"),
+ @ResponseCode (code = 404, condition = "Not Found"),
+ @ResponseCode (code = 409, condition = "Conflict"),
+ @ResponseCode (code = 501, condition = "Not Implemented")})
+ public Response deleteSecurityRule(
+ @PathParam ("securityRuleUUID") String securityRuleUUID) {
+ INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this);
+ if (securityRuleInterface == null) {
+ throw new ServiceUnavailableException("Security Rule CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the Security Rule exists and it isn't currently in use
+ */
+ if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) {
+ throw new ResourceNotFoundException("Security Rule UUID does not exist.");
+ }
+ if (securityRuleInterface.neutronSecurityRuleInUse(securityRuleUUID)) {
+ return Response.status(409).build();
+ }
+ NeutronSecurityRule singleton = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+ int status = service.canDeleteNeutronSecurityRule(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * remove it and return 204 status
+ */
+ securityRuleInterface.removeNeutronSecurityRule(securityRuleUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance;
+ service.neutronSecurityRuleDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+}
\ No newline at end of file
<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>