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>
<aopalliance.version>1.0.0</aopalliance.version>
<appauth.version>0.4.2-SNAPSHOT</appauth.version>
<!-- Controller Modules Versions -->
+ <aries.util.version>1.1.0</aries.util.version>
<arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
<asm.version>4.1</asm.version>
<!-- Plugin Versions -->
<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>
*/
package org.opendaylight.controller.config.api;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
-import javax.management.ObjectName;
-
/**
* Each new {@link org.opendaylight.controller.config.spi.Module} can receive
* resolver from {@link org.opendaylight.controller.config.spi.ModuleFactory}
* To be used during validation phase to validate serice interface of
* dependent module.
*
- * @param expectedServiceInterface
- * MBean/MXBean interface which will back the proxy object.
- * @param objectName
- * ObjectName of dependent module without transaction name
- * (platformON).
- * @param jmxAttribute
- * @throws {@link IllegalArgumentException} when module is not found
- * @throws {@link IllegalStateException} if module does not export this
- * service interface.
+ * @param expectedServiceInterface MBean/MXBean interface which will back the proxy object.
+ * @param objectName ObjectName of dependent module without transaction name
+ * (platformON).
+ * @param jmxAttribute for reporting
+ * @throws IllegalArgumentException when module is not found
+ * @throws IllegalStateException if module does not export this
+ * service interface.
*/
void validateDependency(
Class<? extends AbstractServiceInterface> expectedServiceInterface,
* To be used during commit phase to wire actual dependencies.
*
* @return dependency instance using
- * {@link org.opendaylight.controller.config.spi.Module#getInstance()}
- * @throws {@link IllegalArgumentException} when module is not found
+ * {@link org.opendaylight.controller.config.spi.Module#getInstance()}
+ * @throws IllegalArgumentException when module is not found
*/
<T> T resolveInstance(Class<T> expectedType, ObjectName objectName,
- JmxAttribute jmxAttribute);
-
- // TODO finish javadoc
+ JmxAttribute jmxAttribute);
/**
* To be used during commit phase to resolve identity-ref config attributes.
*/
<T extends BaseIdentity> Class<? extends T> resolveIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass);
+
+ /**
+ * Validate identity-ref config attribute.
+ */
<T extends BaseIdentity> void validateIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass, JmxAttribute jmxAttribute);
+ /**
+ * Can be used during validation or commit phase to get attribute value of dependent module.
+ *
+ * @param name either direct ObjectName of a Module (type=Module) or service reference (type=ServiceReference) of dependent Module
+ * @param attribute String identifying attribute name in JMX. Note that attributes start with upper case. See {@link org.opendaylight.controller.config.api.JmxAttribute#getAttributeName()}
+ */
+ Object getAttribute(ObjectName name, String attribute)
+ throws MBeanException, AttributeNotFoundException,
+ InstanceNotFoundException, ReflectionException;
+
+
+ /**
+ * Helper method around {@link javax.management.JMX#newMXBeanProxy(javax.management.MBeanServerConnection, javax.management.ObjectName, Class)} }.
+ * Returns MXBean proxy for dependent module. Can be used during validation or commit phase to inspect dependent module's attributes.
+ *
+ * @param objectName either direct ObjectName of a Module (type=Module) or service reference (type=ServiceReference) of dependent Module
+ * @param interfaceClass MXBean interface to be used as a proxy
+ * @param <T> type of proxy for type safe return value
+ * @return instance of MXBean proxy
+ */
+ <T> T newMXBeanProxy(ObjectName objectName, Class<T> interfaceClass);
+
}
this.attributeName = attributeName;
}
+ /**
+ * Name of attribute in JMX.
+ */
public String getAttributeName() {
return attributeName;
}
*/
package org.opendaylight.controller.config.manager.impl;
+import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;
import java.util.ArrayList;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import static com.google.common.base.Preconditions.checkNotNull;
/**
* This is a JMX bean representing current transaction. It contains
* transaction identifier, unique version and parent version for
this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
this.transactionStatus = new TransactionStatus();
this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(),
- transactionStatus, writableSRRegistry, codecRegistry);
+ transactionStatus, writableSRRegistry, codecRegistry, transactionsMBeanServer);
this.transactionsMBeanServer = transactionsMBeanServer;
this.configMBeanServer = configMBeanServer;
this.blankTransaction = blankTransaction;
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
+import static java.lang.String.format;
+
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMX;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.IdentityAttributeRef;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.ObjectName;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import static java.lang.String.format;
-
/**
* Protect {@link org.opendaylight.controller.config.spi.Module#getInstance()}
* by creating proxy that would throw exception if those methods are called
private final Set<ModuleIdentifier> dependencies = new HashSet<>();
private final ServiceReferenceReadableRegistry readableRegistry;
private final CodecRegistry codecRegistry;
+ private final String transactionName;
+ private final MBeanServer mBeanServer;
DependencyResolverImpl(ModuleIdentifier currentModule,
TransactionStatus transactionStatus, ModulesHolder modulesHolder,
- ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
+ ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry,
+ String transactionName, MBeanServer mBeanServer) {
this.codecRegistry = codecRegistry;
this.name = currentModule;
this.transactionStatus = transactionStatus;
this.modulesHolder = modulesHolder;
this.readableRegistry = readableRegistry;
+ this.transactionName = transactionName;
+ this.mBeanServer = mBeanServer;
}
/**
JmxAttributeValidationException.checkNotNull(dependentReadOnlyON,
"is null, expected dependency implementing "
- + expectedServiceInterface, jmxAttribute);
+ + expectedServiceInterface, jmxAttribute
+ );
// check that objectName belongs to this transaction - this should be
JmxAttributeValidationException.checkCondition(
hasTransaction == false,
format("ObjectName should not contain "
- + "transaction name. %s set to %s. ", jmxAttribute,
- dependentReadOnlyON), jmxAttribute);
+ + "transaction name. %s set to %s. ", jmxAttribute,
+ dependentReadOnlyON
+ ), jmxAttribute
+ );
dependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
+ "attribute %s",
foundFactory.getImplementationName(), foundFactory,
expectedServiceInterface, dependentReadOnlyON,
- jmxAttribute);
+ jmxAttribute
+ );
throw new JmxAttributeValidationException(message, jmxAttribute);
}
synchronized (this) {
String message = format(
"Error while %s resolving instance %s. getInstance() returned null. "
+ "Expected type %s , attribute %s", name,
- dependentModuleIdentifier, expectedType, jmxAttribute);
+ dependentModuleIdentifier, expectedType, jmxAttribute
+ );
throw new JmxAttributeValidationException(message, jmxAttribute);
}
try {
String message = format(
"Instance cannot be cast to expected type. Instance class is %s , "
+ "expected type %s , attribute %s",
- instance.getClass(), expectedType, jmxAttribute);
+ instance.getClass(), expectedType, jmxAttribute
+ );
throw new JmxAttributeValidationException(message, e, jmxAttribute);
}
}
return name;
}
+ @Override
+ public Object getAttribute(ObjectName name, String attribute)
+ throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException {
+ name = translateServiceRefIfPossible(name);
+ // add transaction name
+ name = ObjectNameUtil.withTransactionName(name, transactionName);
+ return mBeanServer.getAttribute(name, attribute);
+ }
+
+ @Override
+ public <T> T newMXBeanProxy(ObjectName name, Class<T> interfaceClass) {
+ name = translateServiceRefIfPossible(name);
+ // add transaction name
+ name = ObjectNameUtil.withTransactionName(name, transactionName);
+ return JMX.newMXBeanProxy(mBeanServer, name, interfaceClass);
+ }
}
import java.util.Map;
import javax.annotation.concurrent.GuardedBy;
import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanServer;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.DependencyResolverFactory;
import org.opendaylight.controller.config.api.JmxAttribute;
public class DependencyResolverManager implements DependencyResolverFactory, AutoCloseable {
@GuardedBy("this")
private final Map<ModuleIdentifier, DependencyResolverImpl> moduleIdentifiersToDependencyResolverMap = new HashMap<>();
+ private final TransactionIdentifier transactionIdentifier;
private final ModulesHolder modulesHolder;
private final TransactionStatus transactionStatus;
private final ServiceReferenceReadableRegistry readableRegistry;
private final CodecRegistry codecRegistry;
private final DeadlockMonitor deadlockMonitor;
+ private final MBeanServer mBeanServer;
public DependencyResolverManager(TransactionIdentifier transactionIdentifier,
- TransactionStatus transactionStatus, ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
+ TransactionStatus transactionStatus,
+ ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry,
+ MBeanServer mBeanServer) {
+ this.transactionIdentifier = transactionIdentifier;
this.modulesHolder = new ModulesHolder(transactionIdentifier);
this.transactionStatus = transactionStatus;
this.readableRegistry = readableRegistry;
this.codecRegistry = codecRegistry;
this.deadlockMonitor = new DeadlockMonitor(transactionIdentifier);
+ this.mBeanServer = mBeanServer;
}
@Override
DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap.get(name);
if (dependencyResolver == null) {
transactionStatus.checkNotCommitted();
- dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry, codecRegistry);
+ dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry,
+ codecRegistry, transactionIdentifier.getName(), mBeanServer);
moduleIdentifiersToDependencyResolverMap.put(name, dependencyResolver);
}
return dependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
import org.opendaylight.controller.config.manager.impl.ModuleInternalInfo;
import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.osgi.framework.BundleContext;
-public class DependencyResolverManagerTest {
+public class DependencyResolverManagerTest extends AbstractLockedPlatformMBeanServerTest {
final ModuleIdentifier apspName = new ModuleIdentifier("apsp", "apsp"); // depends
// on:
public void setUp() {
transactionStatus = mock(TransactionStatus.class);
ServiceReferenceReadableRegistry mockedRegistry = mock(ServiceReferenceReadableRegistry.class);
- tested = new DependencyResolverManager(new TransactionIdentifier("txName"), transactionStatus, mockedRegistry, null);
+ tested = new DependencyResolverManager(new TransactionIdentifier("txName"), transactionStatus, mockedRegistry,
+ null, platformMBeanServer);
doNothing().when(transactionStatus).checkCommitStarted();
doNothing().when(transactionStatus).checkNotCommitted();
}
*/
package org.opendaylight.controller.config.manager.testingservices.parallelapsp;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.base.Strings;
+import java.io.Closeable;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.NotThreadSafe;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.annotations.RequireInterface;
import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolConfigMXBean;
import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolIfc;
import org.opendaylight.controller.config.spi.Module;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.management.ObjectName;
-import java.io.Closeable;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
/**
* Represents service that has dependency to thread pool.
*/
checkState("Commit was not triggered".equals(e.getMessage()),
e.getMessage());
}
+
+ // test retrieving dependent module's attribute
+ int threadCount;
+ try {
+ threadCount = (Integer)dependencyResolver.getAttribute(threadPoolON, "ThreadCount");
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ checkState(threadCount > 0);
+ TestingThreadPoolConfigMXBean proxy = dependencyResolver.newMXBeanProxy(threadPoolON, TestingThreadPoolConfigMXBean.class);
+ checkState(threadCount == proxy.getThreadCount());
}
@Override
*/
package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test;
+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.junit.internal.matchers.StringContains.containsString;
+
+import java.util.Map;
+import javax.management.ObjectName;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPConfigMXBean;
import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPImpl;
import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolConfigMXBean;
import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
-import javax.management.ObjectName;
-import java.util.Map;
-
-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.junit.internal.matchers.StringContains.containsString;
-
public class DependentWiringTest extends AbstractParallelAPSPTest {
private final String fixed1 = "fixed1";
private final String apsp1 = "apsp-parallel";
parallelAPSPRuntimeProxy.getMaxNumberOfThreads());
}
+
+ @Test
+ public void testUsingServiceReferences() throws Exception {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ ObjectName threadPoolON = createFixed1(transaction, 10);
+ transaction.lookupConfigBean(getThreadPoolImplementationName(), fixed1);
+ String refName = "ref";
+ ObjectName serviceReferenceON = transaction.saveServiceReference(TestingThreadPoolServiceInterface.QNAME, refName,
+ threadPoolON);
+ createParallelAPSP(transaction, serviceReferenceON);
+ transaction.commit();
+
+ }
}
-
-
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) {
<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>
#Hosttracker hostsdb key scheme setting
hosttracker.keyscheme=IP
+
+# LISP Flow Mapping configuration
+# Map-Register messages overwrite existing RLOC sets in EID-to-RLOC mappings
+lisp.mappingOverwrite = true
+# Enable the Solicit-Map-Request (SMR) mechanism
+lisp.smr = false
<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>
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.ConsumerContext
-import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer
+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.controller.sal.core.ComponentActivatorAbstractBase
import org.opendaylight.controller.sal.core.Node
import org.opendaylight.controller.sal.core.NodeConnector
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.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.packet.service.rev130709.PacketProcessingService
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 {
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,
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;
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.md.sal.binding.util.TypeSafeDataReader
import org.opendaylight.controller.sal.core.ConstructionException
import org.opendaylight.controller.sal.core.Edge
import org.opendaylight.controller.sal.core.Node
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.LoggerFactory
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);
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>
* component of the controller or application supplies a concrete implementation
* of this interface.
*
- * A user-implemented component (application) which faciliates the SAL and SAL
+ * A user-implemented component (application) which facilitates the SAL and SAL
* services to access infrastructure services or providers' functionality.
*
*
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;
return potential;
}
+ int normalizedCount = getAugmentationCount(normalized);
AugmentationIdentifier lastArgument = (AugmentationIdentifier) Iterables.getLast(normalized.getPath());
// Here we employ small trick - Binding-aware Codec injects an pointer
// 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 (!isChoiceOrCasePath(childPath)) {
- InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(toBindingImpl(
- childPath).get());
- 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);
}
- return toBindingImpl(normalized);
+
+ LOG.trace("Failed to find augmentation matching {}", normalized);
+ return Optional.absent();
}
private Optional<InstanceIdentifier<? extends DataObject>> toBindingImpl(
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath;
try {
- if (isChoiceOrCasePath(normalized)) {
+ if (isNotRepresentable(normalized)) {
return Optional.absent();
}
legacyPath = legacyToNormalized.toLegacy(normalized);
return Optional.<InstanceIdentifier<? extends DataObject>> of(bindingToLegacy.fromDataDom(legacyPath));
}
- private boolean isChoiceOrCasePath(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+ private boolean isNotRepresentable(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
throws DataNormalizationException {
DataNormalizationOperation<?> op = findNormalizationOperation(normalized);
- return op.isMixin() && op.getIdentifier() instanceof NodeIdentifier;
+ if( op.isMixin() && op.getIdentifier() instanceof NodeIdentifier) {
+ return true;
+ }
+ if(op.isLeaf()) {
+ return true;
+ }
+ return false;
}
private DataNormalizationOperation<?> findNormalizationOperation(
if (isAugmentationIdentifier(processed)) {
return processed;
}
- // Here we employ small trick - DataNormalizer injecst augmentation
+ // Here we employ small trick - DataNormalizer injects augmentation
// identifier if child is
// also part of the path (since using a child we can safely identify
// augmentation)
} 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 boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed) {
return Iterables.getLast(processed.getPath()) instanceof AugmentationIdentifier;
}
+
+ private static int getAugmentationCount(final InstanceIdentifier<?> potential) {
+ int count = 0;
+ for(org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : potential.getPathArguments()) {
+ if(isAugmentation(arg.getType())) {
+ count++;
+ }
+
+ }
+ return count;
+ }
+
+ private static int getAugmentationCount(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier potential) {
+ int count = 0;
+ for(PathArgument arg : potential.getPath()) {
+ if(arg instanceof AugmentationIdentifier) {
+ count++;
+ }
+ }
+ return count;
+ }
}
}
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) {
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);
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import static org.junit.Assert.assertFalse;
+
+import java.util.concurrent.ExecutionException;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+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.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+public class DeleteNestedAugmentationListenParentTest extends AbstractDataServiceTest {
+
+ private static final NodeKey NODE_KEY = new NodeKey(new NodeId("foo"));
+
+ private static final TableKey TABLE_KEY = new TableKey((short) 0);
+
+ private static final FlowKey FLOW_KEY = new FlowKey(new FlowId("100"));
+
+ private static final InstanceIdentifier<FlowCapableNode> LISTENER_PATH = InstanceIdentifier.builder(Nodes.class) //
+ .child(Node.class)
+ .augmentation(FlowCapableNode.class).build();
+
+
+ private static final InstanceIdentifier<FlowCapableNode> NODE_AUGMENT_PATH = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class,NODE_KEY)
+ .augmentation(FlowCapableNode.class)
+ .build();
+
+ private static final InstanceIdentifier<Flow> FLOW_PATH = NODE_AUGMENT_PATH.builder()
+ .child(Table.class,TABLE_KEY)
+ .child(Flow.class,FLOW_KEY)
+ .build();
+
+
+ @Test
+ public void deleteChildListenParent() throws InterruptedException, ExecutionException {
+ DataModificationTransaction initTx = baDataService.beginTransaction();
+
+ initTx.putOperationalData(FLOW_PATH, flow());
+ initTx.commit().get();
+
+ final SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> event = SettableFuture.create();
+
+ ListenerRegistration<DataChangeListener> listenerReg = baDataService.registerDataChangeListener(FLOW_PATH, new DataChangeListener() {
+
+ @Override
+ public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ event.set(change);
+ }
+ });
+
+ DataModificationTransaction deleteTx = baDataService.beginTransaction();
+ deleteTx.removeOperationalData(FLOW_PATH.augmentation(FlowStatisticsData.class));
+ deleteTx.commit().get();
+
+ DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedEvent = event.get();
+ assertFalse(receivedEvent.getRemovedOperationalData().contains(NODE_AUGMENT_PATH));
+ }
+
+ private Flow flow() {
+ FlowBuilder builder = new FlowBuilder()
+ .setKey(FLOW_KEY)
+ .addAugmentation(FlowStatisticsData.class,new FlowStatisticsDataBuilder()
+ .setFlowStatistics(new FlowStatisticsBuilder()
+ .setBarrier(true)
+ .setMatch(new MatchBuilder()
+ .build())
+ .build())
+ .build())
+ ;//.build();
+ return builder.build();
+ }
+
+}
\ No newline at end of file
*/
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);
- }
-}
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
public abstract NormalizedNode<?, ?> normalize(Node<?> legacyData);
+ public abstract boolean isLeaf();
+
private static abstract class SimpleTypeNormalization<T extends PathArgument> extends DataNormalizationOperation<T> {
protected SimpleTypeNormalization(final T identifier) {
return null;
}
+ @Override
+ public boolean isLeaf() {
+ return true;
+ }
+
}
private static final class LeafNormalization extends SimpleTypeNormalization<NodeIdentifier> {
return builder.build();
}
+ @Override
+ public boolean isLeaf() {
+ return false;
+ }
+
@SuppressWarnings("rawtypes")
protected abstract NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode);
if (potential != null) {
return potential;
}
- potential = fromSchema(schema, child);
+ potential = fromLocalSchema(child);
return register(potential);
}
+ private DataNormalizationOperation<?> fromLocalSchema(final PathArgument child) throws DataNormalizationException {
+ if (child instanceof AugmentationIdentifier) {
+ return fromSchemaAndQNameChecked(schema, ((AugmentationIdentifier) child).getPossibleChildNames()
+ .iterator().next());
+ }
+ return fromSchemaAndQNameChecked(schema, child.getNodeType());
+ }
+
@Override
public DataNormalizationOperation<?> getChild(final QName child) throws DataNormalizationException {
DataNormalizationOperation<?> potential = byQName.get(child);
if (potential != null) {
return potential;
}
- potential = fromSchemaAndPathArgument(schema, child);
+ potential = fromLocalSchemaAndQName(schema, child);
return register(potential);
}
+ protected DataNormalizationOperation<?> fromLocalSchemaAndQName(final DataNodeContainer schema2, final QName child) throws DataNormalizationException {
+ return fromSchemaAndQNameChecked(schema2, child);
+ }
+
private DataNormalizationOperation<?> register(final DataNormalizationOperation<?> potential) {
if (potential != null) {
byArg.put(potential.getIdentifier(), potential);
}
@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());
}
}
}
- private static final class AugmentationNormalization extends MixinNormalizationOp<AugmentationIdentifier> {
-
- private final Map<QName, DataNormalizationOperation<?>> byQName;
- private final Map<PathArgument, DataNormalizationOperation<?>> byArg;
+ private static final class AugmentationNormalization extends DataContainerNormalizationOperation<AugmentationIdentifier> {
public AugmentationNormalization(final AugmentationSchema augmentation, final DataNodeContainer schema) {
- super(augmentationIdentifierFrom(augmentation));
-
- ImmutableMap.Builder<QName, DataNormalizationOperation<?>> byQNameBuilder = ImmutableMap.builder();
- ImmutableMap.Builder<PathArgument, DataNormalizationOperation<?>> byArgBuilder = ImmutableMap.builder();
-
- for (DataSchemaNode augNode : augmentation.getChildNodes()) {
- DataSchemaNode resolvedNode = schema.getDataChildByName(augNode.getQName());
- DataNormalizationOperation<?> resolvedOp = fromDataSchemaNode(resolvedNode);
- byArgBuilder.put(resolvedOp.getIdentifier(), resolvedOp);
- for (QName resQName : resolvedOp.getQNameIdentifiers()) {
- byQNameBuilder.put(resQName, resolvedOp);
- }
- }
- byQName = byQNameBuilder.build();
- byArg = byArgBuilder.build();
-
+ //super();
+ super(augmentationIdentifierFrom(augmentation), augmentationProxy(augmentation,schema));
}
@Override
- public DataNormalizationOperation<?> getChild(final PathArgument child) {
- return byArg.get(child);
+ public boolean isMixin() {
+ return true;
}
+
+
@Override
- public DataNormalizationOperation<?> getChild(final QName child) {
- return byQName.get(child);
+ protected DataNormalizationOperation<?> fromLocalSchemaAndQName(final DataNodeContainer schema, final QName child)
+ throws DataNormalizationException {
+ Optional<DataSchemaNode> potential = findChildSchemaNode(schema, child);
+ if (!potential.isPresent()) {
+ return null;
+ }
+
+ DataSchemaNode result = potential.get();
+ // We try to look up if this node was added by augmentation
+ if ((schema instanceof DataSchemaNode) && result.isAugmenting()) {
+ return fromAugmentation(schema, (AugmentationTarget) schema, result);
+ }
+ return fromDataSchemaNode(result);
}
@Override
}
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
+ protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());
}
}
}
- private static DataNormalizationOperation<?> fromSchemaAndPathArgument(final DataNodeContainer schema,
- final QName child) throws DataNormalizationException {
- DataSchemaNode potential = schema.getDataChildByName(child);
+ private static final Optional<DataSchemaNode> findChildSchemaNode(final DataNodeContainer parent,final QName child) {
+ DataSchemaNode potential = parent.getDataChildByName(child);
if (potential == null) {
Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices = FluentIterable.from(
- schema.getChildNodes()).filter(org.opendaylight.yangtools.yang.model.api.ChoiceNode.class);
+ parent.getChildNodes()).filter(org.opendaylight.yangtools.yang.model.api.ChoiceNode.class);
potential = findChoice(choices, child);
}
+ return Optional.fromNullable(potential);
+ }
- if (potential == null) {
+ private static DataNormalizationOperation<?> fromSchemaAndQNameChecked(final DataNodeContainer schema,
+ final QName child) throws DataNormalizationException {
+
+ Optional<DataSchemaNode> potential = findChildSchemaNode(schema, child);
+ if (!potential.isPresent()) {
throw new DataNormalizationException(String.format("Supplied QName %s is not valid according to schema %s, potential children nodes: %s", child, schema,schema.getChildNodes()));
}
- if ((schema instanceof DataSchemaNode) && !((DataSchemaNode) schema).isAugmenting() && potential.isAugmenting()) {
- return fromAugmentation(schema, (AugmentationTarget) schema, potential);
+ DataSchemaNode result = potential.get();
+ // We try to look up if this node was added by augmentation
+ if ((schema instanceof DataSchemaNode) && result.isAugmenting()) {
+ return fromAugmentation(schema, (AugmentationTarget) schema, result);
}
- return fromDataSchemaNode(potential);
+ return fromDataSchemaNode(result);
}
private static org.opendaylight.yangtools.yang.model.api.ChoiceNode findChoice(
org.opendaylight.yangtools.yang.model.api.ChoiceNode foundChoice = null;
choiceLoop: for (org.opendaylight.yangtools.yang.model.api.ChoiceNode choice : choices) {
for (ChoiceCaseNode caze : choice.getCases()) {
- if (caze.getDataChildByName(child) != null) {
+ if (findChildSchemaNode(caze, child).isPresent()) {
foundChoice = choice;
break choiceLoop;
}
return new AugmentationIdentifier(null, potentialChildren.build());
}
- private static AugmentationNormalization fromAugmentation(final DataNodeContainer schema,
- final AugmentationTarget augments, final DataSchemaNode potential) {
+ private static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation, final DataNodeContainer schema) {
+ Set<DataSchemaNode> children = new HashSet<>();
+ for (DataSchemaNode augNode : augmentation.getChildNodes()) {
+ children.add(schema.getDataChildByName(augNode.getQName()));
+ }
+ return new DataSchemaContainerProxy(children);
+ }
+
+ /**
+ * Returns a DataNormalizationOperation for provided child node
+ *
+ * If supplied child is added by Augmentation this operation returns
+ * a DataNormalizationOperation for augmentation,
+ * otherwise returns a DataNormalizationOperation for child as
+ * call for {@link #fromDataSchemaNode(DataSchemaNode)}.
+ *
+ *
+ * @param parent
+ * @param parentAug
+ * @param child
+ * @return
+ */
+ private static DataNormalizationOperation<?> fromAugmentation(final DataNodeContainer parent,
+ final AugmentationTarget parentAug, final DataSchemaNode child) {
AugmentationSchema augmentation = null;
- for (AugmentationSchema aug : augments.getAvailableAugmentations()) {
- DataSchemaNode child = aug.getDataChildByName(potential.getQName());
- if (child != null) {
+ for (AugmentationSchema aug : parentAug.getAvailableAugmentations()) {
+ DataSchemaNode potential = aug.getDataChildByName(child.getQName());
+ if (potential != null) {
augmentation = aug;
break;
}
}
if (augmentation != null) {
- return new AugmentationNormalization(augmentation, schema);
+ return new AugmentationNormalization(augmentation, parent);
} else {
- return null;
- }
- }
-
- private static DataNormalizationOperation<?> fromSchema(final DataNodeContainer schema, final PathArgument child) throws DataNormalizationException {
- if (child instanceof AugmentationIdentifier) {
- return fromSchemaAndPathArgument(schema, ((AugmentationIdentifier) child).getPossibleChildNames()
- .iterator().next());
+ return fromDataSchemaNode(child);
}
- return fromSchemaAndPathArgument(schema, child.getNodeType());
}
public static DataNormalizationOperation<?> fromDataSchemaNode(final DataSchemaNode potential) {
--- /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.common.impl.util.compat;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+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.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+
+class DataSchemaContainerProxy implements DataNodeContainer {
+
+ private final Set<DataSchemaNode> realChildSchemas;
+ private final Map<QName, DataSchemaNode> mappedChildSchemas;
+
+ public DataSchemaContainerProxy(final Set<DataSchemaNode> realChildSchema) {
+ realChildSchemas = realChildSchema;
+ mappedChildSchemas = new HashMap<QName, DataSchemaNode>();
+ for(DataSchemaNode schema : realChildSchemas) {
+ mappedChildSchemas.put(schema.getQName(),schema);
+ }
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(final QName name) {
+ return mappedChildSchemas.get(name);
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ return realChildSchemas;
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(final String arg0) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return Collections.emptySet();
+ }
+
+}
*/
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
* component of the controller or application supplies a concrete implementation
* of this interface.
*
- * A user-implemented component (application) which faciliates the SAL and SAL
+ * A user-implemented component (application) which facilitates the SAL and SAL
* services to access infrastructure services or providers' functionality.
*
*
* of this interface.
*
* <p>
- * A user-implemented component (application) which faciliates the SAL and SAL
+ * A user-implemented component (application) which facilitates the SAL and SAL
* services to access infrastructure services and to provide functionality to
* {@link Consumer}s and other providers.
*
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;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ 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 NormalizedNode<?, ?> dataTree;
- private StoreMetadataNode metadataTree;
- private SchemaContext schemaContext;
-
- public NormalizedNode<?, ?> getDataTree() {
- return dataTree;
- }
-
- 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));
- }
-
- 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.");
- }
-
}
}
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.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();
+}
* 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.Collections;
-import java.util.Map;
import java.util.Set;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
import com.google.common.base.Strings;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.UnsignedLong;
public final class StoreUtils {
+ private static final int STRINGTREE_INDENT = 4;
private final static Function<Identifiable<Object>, Object> EXTRACT_IDENTIFIER = new Function<Identifiable<Object>, Object>() {
@Override
}
};
- public static final UnsignedLong increase(final UnsignedLong original) {
- return original.plus(UnsignedLong.ONE);
- }
-
- public static final InstanceIdentifier append(final InstanceIdentifier parent, final PathArgument arg) {
-
- return new InstanceIdentifier(ImmutableList.<PathArgument> builder().addAll(parent.getPath()).add(arg).build());
- }
-
- public static AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> initialChangeEvent(
- final InstanceIdentifier path, final StoreMetadataNode data) {
- return new InitialDataChangeEvent(path, data.getData());
+ private StoreUtils() {
+ throw new UnsupportedOperationException("Utility class should not be instantiated");
}
/*
return (Function) EXTRACT_IDENTIFIER;
}
- private static final class InitialDataChangeEvent implements
- AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> {
-
- private final ImmutableMap<InstanceIdentifier, NormalizedNode<?, ?>> payload;
- private final NormalizedNode<?, ?> data;
-
- public InitialDataChangeEvent(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
- payload = ImmutableMap.<InstanceIdentifier, NormalizedNode<?, ?>> of(path, data);
- this.data = data;
- }
-
- @Override
- public Map<InstanceIdentifier, NormalizedNode<?, ?>> getCreatedData() {
- return payload;
- }
-
- @Override
- public Map<InstanceIdentifier, ? extends NormalizedNode<?, ?>> getOriginalData() {
- return Collections.emptyMap();
- }
-
- @Override
- public NormalizedNode<?, ?> getOriginalSubtree() {
- return null;
- }
-
- @Override
- public Set<InstanceIdentifier> getRemovedPaths() {
- return Collections.emptySet();
- }
-
- @Override
- public Map<InstanceIdentifier, NormalizedNode<?, ?>> getUpdatedData() {
- return payload;
- }
+ public static final UnsignedLong increase(final UnsignedLong original) {
+ return original.plus(UnsignedLong.ONE);
+ }
- @Override
- public NormalizedNode<?, ?> getUpdatedSubtree() {
- return data;
- }
+ public static final InstanceIdentifier append(final InstanceIdentifier parent, final PathArgument arg) {
+ return new InstanceIdentifier(ImmutableList.<PathArgument> builder().addAll(parent.getPath()).add(arg).build());
}
public static <V> Set<V> toIdentifierSet(final Iterable<? extends Identifiable<V>> children) {
return FluentIterable.from(children).transform(StoreUtils.<V> identifierExtractor()).toSet();
}
- public static String toStringTree(final StoreMetadataNode metaNode) {
+ public static String toStringTree(final NormalizedNode<?, ?> node) {
StringBuilder builder = new StringBuilder();
- toStringTree(builder, metaNode, 0);
+ toStringTree(builder, node, 0);
return builder.toString();
}
- private static void toStringTree(final StringBuilder builder, final StoreMetadataNode metaNode, final int offset) {
- String prefix = Strings.repeat(" ", offset);
- builder.append(prefix).append(toStringTree(metaNode.getIdentifier()));
- NormalizedNode<?, ?> dataNode = metaNode.getData();
- if (dataNode instanceof NormalizedNodeContainer<?, ?, ?>) {
+ private static void toStringTree(final StringBuilder builder, final NormalizedNode<?, ?> node, final int offset) {
+ final String prefix = Strings.repeat(" ", offset);
+
+ builder.append(prefix).append(toStringTree(node.getIdentifier()));
+ if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
+ final NormalizedNodeContainer<?, ?, ?> container = (NormalizedNodeContainer<?, ?, ?>) node;
+
builder.append(" {\n");
- for (StoreMetadataNode child : metaNode.getChildren()) {
- toStringTree(builder, child, offset + 4);
+ for (NormalizedNode<?, ?> child : container.getValue()) {
+ toStringTree(builder, child, offset + STRINGTREE_INDENT);
}
+
builder.append(prefix).append('}');
} else {
- builder.append(' ').append(dataNode.getValue());
+ builder.append(' ').append(node.getValue());
}
builder.append('\n');
}
--- /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.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;
+
+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.");
+ }
+
+ @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.");
+ }
+}
\ 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.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 StoreMetadataNode rootNode;
+
+ public InMemoryDataTree(StoreMetadataNode 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(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.of(rootNode));
+ }
+
+ @Override
+ public synchronized DataTreeCandidate prepare(DataTreeModification modification) {
+ Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass());
+
+ final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification;
+ final NodeModification root = m.getRootModification();
+
+ if (root.getModificationType() == ModificationType.UNMODIFIED) {
+ return new NoopDataTreeCandidate(PUBLIC_ROOT_PATH, root);
+ }
+
+ rwLock.writeLock().lock();
+ try {
+ // FIXME: rootNode needs to be a read-write snapshot here...
+ final Optional<StoreMetadataNode> newRoot = m.getStrategy().apply(m.getRootModification(), Optional.of(rootNode), StoreUtils.increase(rootNode.getSubtreeVersion()));
+ 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(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 Store snapshot version: {} with version:{}", rootNode.getSubtreeVersion(), c.getAfterRoot().getSubtreeVersion());
+
+ 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.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 StoreMetadataNode newMeta;
+ private final StoreMetadataNode oldMeta;
+ private final NodeModification mod;
+
+ protected AbstractNode(final NodeModification mod,
+ final StoreMetadataNode oldMeta, final StoreMetadataNode newMeta) {
+ this.newMeta = newMeta;
+ this.oldMeta = oldMeta;
+ this.mod = Preconditions.checkNotNull(mod);
+ }
+
+ protected final NodeModification getMod() {
+ return mod;
+ }
+
+ protected final StoreMetadataNode getNewMeta() {
+ return newMeta;
+ }
+
+ protected final StoreMetadataNode getOldMeta() {
+ return oldMeta;
+ }
+
+ private static final StoreMetadataNode childMeta(final StoreMetadataNode parent, final PathArgument id) {
+ return parent == null ? null : parent.getChild(id).orNull();
+ }
+
+ @Override
+ public Iterable<DataTreeCandidateNode> getChildNodes() {
+ return Iterables.transform(mod.getModifications(), new Function<NodeModification, DataTreeCandidateNode>() {
+ @Override
+ public DataTreeCandidateNode apply(final NodeModification input) {
+ final PathArgument id = input.getIdentifier();
+ return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id));
+ }
+ });
+ }
+
+ @Override
+ public ModificationType getModificationType() {
+ return mod.getModificationType();
+ }
+
+ private Optional<NormalizedNode<?, ?>> optionalData(StoreMetadataNode meta) {
+ if (meta == null) {
+ return Optional.absent();
+ }
+ return Optional.<NormalizedNode<?,?>>of(meta.getData());
+ }
+
+ @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(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode newMeta) {
+ super(mod, oldMeta, newMeta);
+ }
+
+ @Override
+ public PathArgument getIdentifier() {
+ return getMod().getIdentifier();
+ }
+ }
+
+ private static final class RootNode extends AbstractNode {
+ public RootNode(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode 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 NodeModification modificationRoot,
+ final StoreMetadataNode oldRoot, final StoreMetadataNode newRoot) {
+ super(rootPath);
+ this.root = new RootNode(modificationRoot, oldRoot, newRoot);
+ }
+
+ StoreMetadataNode getAfterRoot() {
+ return root.getNewMeta();
+ }
+
+ StoreMetadataNode 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.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(StoreMetadataNode.createEmpty(data), null);
+ }
+
+ /**
+ * Get an instance of this factory. This method cannot fail.
+ *
+ * @return Data tree factory instance.
+ */
+ public static final InMemoryDataTreeFactory getInstance() {
+ return INSTANCE;
+ }
+}
* 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 static com.google.common.base.Preconditions.checkState;
import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
-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.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
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 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();
+final class InMemoryDataTreeModification implements DataTreeModification {
+ private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTreeModification.class);
+
+ /*
+ * FIXME: the thread safety of concurrent write/delete/read/seal operations
+ * needs to be evaluated.
+ */
+ private static final AtomicIntegerFieldUpdater<InMemoryDataTreeModification> SEALED_UPDATER =
+ AtomicIntegerFieldUpdater.newUpdater(InMemoryDataTreeModification.class, "sealed");
+ private volatile int sealed = 0;
+
private final ModificationApplyOperation strategyTree;
- private final DataAndMetadataSnapshot snapshot;
- private final NodeModification rootModification;
+ private final InMemoryDataTreeSnapshot snapshot;
+ private final NodeModification rootNode;
- private MutableDataTree(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation strategyTree) {
- this.snapshot = snapshot;
- this.strategyTree = strategyTree;
- this.rootModification = NodeModification.createUnmodified(snapshot.getMetadataTree());
+ InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final ModificationApplyOperation resolver) {
+ this.snapshot = Preconditions.checkNotNull(snapshot);
+ this.strategyTree = Preconditions.checkNotNull(resolver);
+ this.rootNode = NodeModification.createUnmodified(snapshot.getRootNode());
}
+ NodeModification getRootModification() {
+ return rootNode;
+ }
+
+ ModificationApplyOperation getStrategy() {
+ return strategyTree;
+ }
+
+ @Override
public void write(final InstanceIdentifier path, final NormalizedNode<?, ?> value) {
checkSealed();
resolveModificationFor(path).write(value);
}
+ @Override
public void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
checkSealed();
mergeImpl(resolveModificationFor(path),data);
op.merge(data);
}
+ @Override
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);
+ @Override
+ public Optional<NormalizedNode<?, ?>> readNode(final InstanceIdentifier path) {
+ Entry<InstanceIdentifier, NodeModification> modification = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, NodeModification.IS_TERMINAL_PREDICATE);
Optional<StoreMetadataNode> result = resolveSnapshot(modification);
if (result.isPresent()) {
return potentialSnapshot.get();
}
return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
- StoreUtils.increase(snapshot.getMetadataTree().getSubtreeVersion()));
+ StoreUtils.increase(snapshot.getRootNode().getSubtreeVersion()));
} catch (Exception e) {
LOG.error("Could not create snapshot for {}:{}", path,modification,e);
throw e;
}
private OperationWithModification resolveModificationFor(final InstanceIdentifier path) {
- NodeModification modification = rootModification;
+ NodeModification modification = rootNode;
// We ensure strategy is present.
ModificationApplyOperation operation = resolveModificationStrategy(path);
for (PathArgument pathArg : path.getPath()) {
return OperationWithModification.from(operation, modification);
}
- public static MutableDataTree from(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation resolver) {
- return new MutableDataTree(snapshot, resolver);
- }
-
+ @Override
public void seal() {
- final boolean success = sealed.compareAndSet(false, true);
+ final boolean success = SEALED_UPDATER.compareAndSet(this, 0, 1);
Preconditions.checkState(success, "Attempted to seal an already-sealed Data Tree.");
- rootModification.seal();
+ rootNode.seal();
}
private void checkSealed() {
- checkState(!sealed.get(), "Data Tree is sealed. No further modifications allowed.");
+ checkState(sealed == 0, "Data Tree is sealed. No further modifications allowed.");
}
- protected NodeModification getRootModification() {
- return rootModification;
+ @Override
+ public String toString() {
+ return "MutableDataTree [modification=" + rootNode + "]";
}
@Override
- public String toString() {
- return "MutableDataTree [modification=" + rootModification + "]";
+ public DataTreeModification newModification() {
+ // 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.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 StoreMetadataNode rootNode;
+
+ InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final StoreMetadataNode rootNode,
+ final ModificationApplyOperation applyOper) {
+ this.schemaContext = Preconditions.checkNotNull(schemaContext);
+ this.rootNode = Preconditions.checkNotNull(rootNode);
+ this.applyOper = Preconditions.checkNotNull(applyOper);
+ }
+
+ StoreMetadataNode 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.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
*
*
*/
-public interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
+interface ModificationApplyOperation extends StoreTreeNode<ModificationApplyOperation> {
/**
*
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;
}
* 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;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
import static com.google.common.base.Preconditions.checkState;
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.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 NodeModification implements StoreTreeNode<NodeModification>, Identifiable<PathArgument> {
public static final Predicate<NodeModification> IS_TERMINAL_PREDICATE = new Predicate<NodeModification>() {
@Override
*
* @return
*/
- public NormalizedNode<?, ?> getWritenValue() {
+ public NormalizedNode<?, ?> getWrittenValue() {
return 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.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 NodeModification modificationRoot) {
+ super(rootPath);
+ Preconditions.checkArgument(modificationRoot.getModificationType() == ModificationType.UNMODIFIED);
+ }
+
+ @Override
+ public DataTreeCandidateNode getRootNode() {
+ return ROOT;
+ }
+}
* 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.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;
* 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 static com.google.common.base.Preconditions.checkArgument;
import java.util.Set;
import java.util.concurrent.ExecutionException;
+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.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.controller.md.sal.dom.store.impl.tree.StoreUtils;
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 com.google.common.collect.ImmutableMap;
import com.google.common.primitives.UnsignedLong;
-public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
+abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) {
if (schemaNode instanceof ContainerSchemaNode) {
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;
+
+ 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 AugmentationModificationStrategy(augSchema, resolvedTree);
}
@Override
public void verifyStructure(final NodeModification modification) throws IllegalArgumentException {
if (modification.getModificationType() == ModificationType.WRITE) {
- verifyWritenStructure(modification.getWritenValue());
+ verifyWrittenStructure(modification.getWrittenValue());
}
}
- protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
+ protected abstract void verifyWrittenStructure(NormalizedNode<?, ?> writtenValue);
@Override
public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
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()) {
- checkNotConflicting(path,original.get(), current.get());
+ /*
+ * 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 abstract StoreMetadataNode applySubtreeChange(NodeModification modification,
StoreMetadataNode currentMeta, UnsignedLong subtreeVersion);
- public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends
- SchemaAwareApplyOperation {
+ public static abstract class ValueNodeModificationStrategy<T extends DataSchemaNode> extends SchemaAwareApplyOperation {
private final T schema;
private final Class<? extends NormalizedNode<?, ?>> nodeClass;
}
@Override
- protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
- checkArgument(nodeClass.isInstance(writenValue), "Node should must be of type %s", nodeClass);
+ protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
+ checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass);
}
@Override
final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
UnsignedLong nodeVersion = subtreeVersion;
return StoreMetadataNode.builder().setNodeVersion(nodeVersion).setSubtreeVersion(subtreeVersion)
- .setData(modification.getWritenValue()).build();
+ .setData(modification.getWrittenValue()).build();
}
@Override
@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()) {
+ 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);
- NormalizedNode childNode = (NormalizedNode) child;
+
+ /*
+ * FIXME: fail-fast semantics:
+ *
+ * We can validate the data structure here, aborting the commit
+ * before it ever progresses to being committed.
+ */
}
}
protected StoreMetadataNode applyWrite(final NodeModification modification,
final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
- NormalizedNode<?, ?> newValue = modification.getWritenValue();
+ NormalizedNode<?, ?> newValue = modification.getWrittenValue();
final UnsignedLong nodeVersion;
if (currentMeta.isPresent()) {
protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
}
- public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
- NormalizedNodeContainerModificationStrategy {
+ public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends NormalizedNodeContainerModificationStrategy {
private final T schema;
private final LoadingCache<PathArgument, ModificationApplyOperation> childCache = CacheBuilder.newBuilder()
}
- public static class ContainerModificationStrategy extends
- DataNodeContainerModificationStrategy<ContainerSchemaNode> {
+ public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy<ContainerSchemaNode> {
public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) {
super(schemaNode, ContainerNode.class);
}
}
- public static class UnkeyedListItemModificationStrategy extends
- DataNodeContainerModificationStrategy<ListSchemaNode> {
+ public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) {
super(schemaNode, UnkeyedListEntryNode.class);
}
}
- public static class AugmentationModificationStrategy extends
- DataNodeContainerModificationStrategy<AugmentationSchema> {
+ public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy<AugmentationSchema> {
protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
super(createAugmentProxy(schema,resolved), AugmentationNode.class);
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()) {
@Override
protected StoreMetadataNode applyWrite(final NodeModification modification,
final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
- return StoreMetadataNode.createRecursively(modification.getWritenValue(), subtreeVersion);
+ return StoreMetadataNode.createRecursively(modification.getWrittenValue(), subtreeVersion);
}
@Override
}
@Override
- protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
+ protected void verifyWrittenStructure(final NormalizedNode<?, ?> writtenValue) {
}
}
}
- 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()) {
* 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;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
import static com.google.common.base.Preconditions.checkState;
import java.util.Collections;
-import java.util.LinkedHashMap;
+import java.util.HashMap;
import java.util.Map;
import org.opendaylight.yangtools.concepts.Identifiable;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
import com.google.common.primitives.UnsignedLong;
-public class StoreMetadataNode implements Immutable, Identifiable<PathArgument>, StoreTreeNode<StoreMetadataNode> {
-
+class StoreMetadataNode implements Immutable, Identifiable<PathArgument> {
+ private final Map<PathArgument, StoreMetadataNode> children;
private final UnsignedLong nodeVersion;
private final UnsignedLong subtreeVersion;
private final NormalizedNode<?, ?> data;
- private final Map<PathArgument, StoreMetadataNode> children;
-
/**
*
* @param data
* @param subtreeVersion
* @param children Map of children, must not be modified externally
*/
- protected StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
+ private 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.nodeVersion = Preconditions.checkNotNull(nodeVersion);
+ this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
+ this.data = Preconditions.checkNotNull(data);
this.children = Preconditions.checkNotNull(children);
}
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();
}
return this.data;
}
- public Iterable<StoreMetadataNode> getChildren() {
- return Iterables.unmodifiableIterable(children.values());
- }
-
- @Override
- public Optional<StoreMetadataNode> getChild(final PathArgument key) {
+ Optional<StoreMetadataNode> getChild(final PathArgument key) {
return Optional.fromNullable(children.get(key));
}
private boolean dirty = false;
private Builder() {
- children = new LinkedHashMap<>();
+ children = new HashMap<>();
}
- public Builder(StoreMetadataNode node) {
- children = new LinkedHashMap<>(node.children);
+ private Builder(StoreMetadataNode node) {
+ children = new HashMap<>(node.children);
}
public UnsignedLong getVersion() {
public Builder add(final StoreMetadataNode node) {
if (dirty) {
- children = new LinkedHashMap<>(children);
+ children = new HashMap<>(children);
dirty = false;
}
children.put(node.getIdentifier(), node);
public Builder remove(final PathArgument id) {
if (dirty) {
- children = new LinkedHashMap<>(children);
+ children = new HashMap<>(children);
dirty = false;
}
children.remove(id);
* 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;
+package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
*
*/
@SuppressWarnings("rawtypes")
-public class StoreNodeCompositeBuilder {
+class StoreNodeCompositeBuilder {
private final StoreMetadataNode.Builder metadata;
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.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.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.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 {
@Override
public ListenableFuture<RpcResult<CompositeNode>> rpc(QName type, CompositeNode input) {
- return null;
+ return rpcs.invokeRpc( type, input );
}
@Override
-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.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
.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,
+ StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5)), 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;
+++ /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;
* @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>
<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.restconf.impl;
-import com.google.common.base.Objects;
-
-import java.util.Map;
import java.util.concurrent.Future;
import javax.ws.rs.core.Response.Status;
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.ResponseException;
import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.common.QName;
}
public Future<RpcResult<TransactionStatus>> commitConfigurationDataPost( final InstanceIdentifier path,
- final CompositeNode payload ) {
+ final CompositeNode payload) {
this.checkPreconditions();
final DataModificationTransaction transaction = dataService.beginTransaction();
- transaction.putConfigurationData( path, payload );
- Map<InstanceIdentifier, CompositeNode> createdConfigurationData =
- transaction.getCreatedConfigurationData();
- CompositeNode createdNode = createdConfigurationData.get( path );
-
- if( Objects.equal( payload, createdNode ) ) {
- LOG.trace( "Post Configuration via Restconf: {}", path );
- return transaction.commit();
+ /* check for available Node in Configuration DataStore by path */
+ CompositeNode availableNode = transaction.readConfigurationData( 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);
}
-
- LOG.trace( "Post Configuration via Restconf was not executed because data already exists: {}",
- path );
- return null;
+ BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
+ transaction.putConfigurationData( path, payload );
+ return transaction.commit();
}
public Future<RpcResult<TransactionStatus>> commitConfigurationDataPostBehindMountPoint(
this.checkPreconditions();
final DataModificationTransaction transaction = mountPoint.beginTransaction();
- transaction.putConfigurationData( path, payload );
- Map<InstanceIdentifier, CompositeNode> createdConfigurationData =
- transaction.getCreatedConfigurationData();
- CompositeNode createdNode = createdConfigurationData.get( path );
-
- if( Objects.equal( payload, createdNode ) ) {
- LOG.trace( "Post Configuration via Restconf: {}", path );
- return transaction.commit();
+ /* check for available Node in Configuration DataStore by path */
+ CompositeNode availableNode = transaction.readConfigurationData( 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);
}
-
- LOG.trace( "Post Configuration via Restconf was not executed because data already exists: {}",
- path );
- return null;
+ BrokerFacade.LOG.trace( "Post Configuration via Restconf: {}", path );
+ transaction.putConfigurationData( path, payload );
+ return transaction.commit();
}
public Future<RpcResult<TransactionStatus>> commitConfigurationDataDelete( final InstanceIdentifier path ) {
/**
* 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.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;
-
import java.net.URI;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.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.ResponseException;
-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.rpc.impl.BrokerRpcExecutor;
+import org.opendaylight.controller.sal.restconf.rpc.impl.MountPointRpcExecutor;
+import org.opendaylight.controller.sal.restconf.rpc.impl.RpcExecutor;
import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.controller.sal.streams.listeners.Notificator;
import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
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");
@Override
public StructuredData invokeRpc(final String identifier, final CompositeNode payload) {
- final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
- if (Objects.equal(rpc.getQName().getNamespace().toString(), SAL_REMOTE_NAMESPACE) &&
- Objects.equal(rpc.getQName().getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
+ final RpcExecutor rpc = this.resolveIdentifierInInvokeRpc(identifier);
+ QName rpcName = rpc.getRpcDefinition().getQName();
+ URI rpcNamespace = rpcName.getNamespace();
+ if (Objects.equal(rpcNamespace.toString(), SAL_REMOTE_NAMESPACE) &&
+ Objects.equal(rpcName.getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
- final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
- final SimpleNode<? extends Object> pathNode = value == null ? null :
- value.getFirstSimpleByName( QName.create(rpc.getQName(), "path") );
- final Object pathValue = pathNode == null ? null : pathNode.getValue();
+ return invokeSalRemoteRpcSubscribeRPC(payload, rpc.getRpcDefinition());
+ }
- if (!(pathValue instanceof InstanceIdentifier)) {
- throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
- "Instance identifier was not normalized correctly.");
- }
+ return callRpc(rpc, payload);
+ }
- final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
- String streamName = null;
- if (!Iterables.isEmpty(pathIdentifier.getPath())) {
- String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
- streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
- }
+ private StructuredData invokeSalRemoteRpcSubscribeRPC(final CompositeNode payload,
+ final RpcDefinition rpc) {
+ final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
+ final SimpleNode<? extends Object> pathNode = value == null ? null :
+ value.getFirstSimpleByName( QName.create(rpc.getQName(), "path") );
+ final Object pathValue = pathNode == null ? null : pathNode.getValue();
- if (Strings.isNullOrEmpty(streamName)) {
- throw new ResponseException(Status.BAD_REQUEST,
- "Path is empty or contains data node which is not Container or List build-in type.");
- }
+ if (!(pathValue instanceof InstanceIdentifier)) {
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+ "Instance identifier was not normalized correctly.");
+ }
- final SimpleNode<String> streamNameNode = NodeFactory.<String>createImmutableSimpleNode(
- QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
- final List<Node<?>> output = new ArrayList<Node<?>>();
- output.add(streamNameNode);
+ final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
+ String streamName = null;
+ if (!Iterables.isEmpty(pathIdentifier.getPath())) {
+ String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
+ streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
+ }
- final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
- rpc.getOutput().getQName(), null, output, null, null);
+ if (Strings.isNullOrEmpty(streamName)) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Path is empty or contains data node which is not Container or List build-in type.");
+ }
- if (!Notificator.existListenerFor(pathIdentifier)) {
- Notificator.createListener(pathIdentifier, streamName);
- }
+ final SimpleNode<String> streamNameNode = NodeFactory.<String>createImmutableSimpleNode(
+ QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
+ final List<Node<?>> output = new ArrayList<Node<?>>();
+ output.add(streamNameNode);
+
+ 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 ResponseException(
+ Status.UNSUPPORTED_MEDIA_TYPE, "Content-Type contains unsupported Media Type.");
}
-
- final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
- return this.callRpc(rpc, null);
+ final RpcExecutor rpc = resolveIdentifierInInvokeRpc(identifier);
+ return callRpc(rpc, null);
}
- private RpcDefinition resolveIdentifierInInvokeRpc(final String identifier) {
- if (identifier.indexOf("/") < 0) {
- final String identifierDecoded = this.controllerContext.urlPathArgDecode(identifier);
- final RpcDefinition rpc = this.controllerContext.getRpcDefinition(identifierDecoded);
- if (rpc != null) {
- return rpc;
- }
+ private RpcExecutor resolveIdentifierInInvokeRpc(final String identifier) {
+ String identifierEncoded = null;
+ MountInstance mountPoint = null;
+ if (identifier.contains(ControllerContext.MOUNT)) {
+ // mounted RPC call - look up mount instance.
+ InstanceIdWithSchemaNode mountPointId = controllerContext
+ .toMountPointIdentifier(identifier);
+ mountPoint = mountPointId.getMountPoint();
+
+ int startOfRemoteRpcName = identifier.lastIndexOf(ControllerContext.MOUNT)
+ + ControllerContext.MOUNT.length() + 1;
+ String remoteRpcName = identifier.substring(startOfRemoteRpcName);
+ identifierEncoded = remoteRpcName;
+
+ } else if (identifier.indexOf("/") != CHAR_NOT_FOUND) {
+ final String slashErrorMsg = String
+ .format("Identifier %n%s%ncan\'t contain slash "
+ + "character (/).%nIf slash is part of identifier name then use %%2F placeholder.",
+ identifier);
+ throw new ResponseException(Status.NOT_FOUND, slashErrorMsg);
+ } else {
+ identifierEncoded = identifier;
+ }
+ final String identifierDecoded = controllerContext.urlPathArgDecode(identifierEncoded);
+ RpcDefinition rpc = controllerContext.getRpcDefinition(identifierDecoded);
+
+ if (rpc == null) {
throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
}
- final String slashErrorMsg = String.format(
- "Identifier %n%s%ncan\'t contain slash character (/).%nIf slash is part of identifier name then use %%2F placeholder.",
- identifier);
+ if (mountPoint == null) {
+ return new BrokerRpcExecutor(rpc, broker);
+ } else {
+ return new MountPointRpcExecutor(rpc, mountPoint);
+ }
- throw new ResponseException(Status.NOT_FOUND, slashErrorMsg);
}
- private StructuredData callRpc(final RpcDefinition rpc, final CompositeNode payload) {
- if (rpc == null) {
+ private StructuredData callRpc(final RpcExecutor rpcExecutor, final CompositeNode payload) {
+ if (rpcExecutor == null) {
throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
}
CompositeNode rpcRequest = null;
+ RpcDefinition rpc = rpcExecutor.getRpcDefinition();
+ QName rpcName = rpc.getQName();
+
if (payload == null) {
- rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, null, null, null);
- }
- else {
+ rpcRequest = NodeFactory.createMutableCompositeNode(rpcName, null, null, null, null);
+ } else {
final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
- final List<Node<?>> input = new ArrayList<Node<?>>();
- input.add(value);
-
- rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, input, null, null);
+ List<Node<?>> input = Collections.<Node<?>> singletonList(value);
+ rpcRequest = NodeFactory.createMutableCompositeNode(rpcName, null, input, null, null);
}
- final RpcResult<CompositeNode> rpcResult = broker.invokeRpc(rpc.getQName(), rpcRequest);
+ RpcResult<CompositeNode> rpcResult = rpcExecutor.invokeRpc(rpcRequest);
- if (!rpcResult.isSuccessful()) {
- throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Operation failed");
- }
+ checkRpcSuccessAndThrowException(rpcResult);
- CompositeNode result = rpcResult.getResult();
- if (result == null) {
+ if (rpcResult.getResult() == null) {
return null;
}
- return new StructuredData(result, rpc.getOutput(), null);
+ if( rpc.getOutput() == null )
+ {
+ return null; //no output, nothing to send back.
+ }
+
+ return new StructuredData(rpcResult.getResult(), rpc.getOutput(), null);
+ }
+
+ private void checkRpcSuccessAndThrowException(RpcResult<CompositeNode> rpcResult) {
+ if (rpcResult.isSuccessful() == false) {
+ //TODO: Get smart about what error code we are return (Future Bug coming)
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+ "The operation was not successful and there were no RPC errors returned");
+ }
}
@Override
status = future == null ? null : future.get();
}
}
+ catch( ResponseException e ){ throw e; }
catch( Exception e ) {
throw new ResponseException( e, "Error creating data" );
}
status = future == null ? null : future.get();
}
}
+ catch( ResponseException e ){ throw e; }
catch( Exception e ) {
throw new ResponseException( e, "Error creating data" );
}
--- /dev/null
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public abstract class AbstractRpcExecutor implements RpcExecutor {
+ private final RpcDefinition rpcDef;
+
+ public AbstractRpcExecutor( RpcDefinition rpcDef ){
+ this.rpcDef = rpcDef;
+ }
+
+ @Override
+ public RpcDefinition getRpcDefinition() {
+ return rpcDef;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public class BrokerRpcExecutor extends AbstractRpcExecutor {
+ private final BrokerFacade broker;
+
+ public BrokerRpcExecutor( RpcDefinition rpcDef, BrokerFacade broker )
+ {
+ super( rpcDef );
+ this.broker = broker;
+ }
+
+ @Override
+ public RpcResult<CompositeNode> invokeRpc(CompositeNode rpcRequest) {
+ return broker.invokeRpc( getRpcDefinition().getQName(), rpcRequest );
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import java.util.concurrent.ExecutionException;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Provides an implementation which invokes rpc methods via a mounted yang data model.
+ * @author Devin Avery
+ *
+ */
+public class MountPointRpcExecutor extends AbstractRpcExecutor {
+ private final MountInstance mountPoint;
+
+ public MountPointRpcExecutor(RpcDefinition rpcDef, MountInstance mountPoint) {
+ super( rpcDef );
+ this.mountPoint = mountPoint;
+ Preconditions.checkNotNull( mountPoint, "MountInstance can not be null." );
+ }
+
+ @Override
+ public RpcResult<CompositeNode> invokeRpc( CompositeNode rpcRequest ) throws ResponseException {
+ ListenableFuture<RpcResult<CompositeNode>> rpcFuture =
+ mountPoint.rpc( getRpcDefinition().getQName(), rpcRequest);
+ try {
+ return rpcFuture.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+ e.getCause().getMessage() );
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+* Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.sal.restconf.rpc.impl;
+
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+
+public interface RpcExecutor {
+ RpcResult<CompositeNode> invokeRpc( CompositeNode rpcRequest );
+
+ RpcDefinition getRpcDefinition();
+}
\ No newline at end of file
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
-import java.util.Collections;
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;
inOrder.verify( mockTransaction ).commit();
}
- @Test
+ @Test(expected=ResponseException.class)
public void testCommitConfigurationDataPostAlreadyExists() {
when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
mockTransaction.putConfigurationData( instanceID, dataNode );
- when( mockTransaction.getCreatedConfigurationData() )
- .thenReturn( Collections.<InstanceIdentifier,CompositeNode>emptyMap() );
-
- Future<RpcResult<TransactionStatus>> actualFuture =
- brokerFacade.commitConfigurationDataPost( instanceID, dataNode );
-
- assertNull( "Retruned non-null Future", actualFuture );
- verify( mockTransaction, never() ).commit();
+ when ( mockTransaction.readConfigurationData( instanceID ) )
+ .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());
+ throw e;
+ }
}
@Test
inOrder.verify( mockTransaction ).commit();
}
- @Test
+ @Test(expected=ResponseException.class)
public void testCommitConfigurationDataPostBehindMountPointAlreadyExists() {
when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
mockTransaction.putConfigurationData( instanceID, dataNode );
- when( mockTransaction.getCreatedConfigurationData() )
- .thenReturn( Collections.<InstanceIdentifier,CompositeNode>emptyMap() );
-
- Future<RpcResult<TransactionStatus>> actualFuture =
- brokerFacade.commitConfigurationDataPostBehindMountPoint( mockMountInstance,
- instanceID, dataNode );
-
- assertNull( "Retruned non-null Future", actualFuture );
- verify( mockTransaction, never() ).commit();
+ when ( mockTransaction.readConfigurationData( instanceID ) )
+ .thenReturn( dataNode );
+ 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());
+ throw e;
+ }
}
@Test
/*
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2014 Brocade Communications Systems, Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
+import java.io.FileNotFoundException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Set;
+import javax.ws.rs.core.Response.Status;
+
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.ModifyAction;
import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import com.google.common.util.concurrent.ListenableFuture;
public class InvokeRpcMethodTest {
- private static Set<Module> modules;
+ private RestconfImpl restconfImpl = null;
+ private static ControllerContext controllerContext = null;
private class AnswerImpl implements Answer<RpcResult<CompositeNode>> {
@Override
}
@BeforeClass
- public static void initialization() {
- modules = TestUtils.loadModulesFrom("/invoke-rpc");
- assertEquals(1, modules.size());
- Module module = TestUtils.resolveModule("invoke-rpc-module", modules);
+ public static void init() throws FileNotFoundException {
+ Set<Module> allModules = new HashSet<Module>( TestUtils
+ .loadModulesFrom("/full-versions/yangs") );
+ allModules.addAll( TestUtils.loadModulesFrom("/invoke-rpc") );
+ assertNotNull(allModules);
+ Module module = TestUtils.resolveModule("invoke-rpc-module", allModules);
assertNotNull(module);
+ SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
+ controllerContext = spy( ControllerContext.getInstance() );
+ controllerContext.setSchemas(schemaContext);
+
+ }
+
+ @Before
+ public void initMethod()
+ {
+ restconfImpl = RestconfImpl.getInstance();
+ restconfImpl.setControllerContext( controllerContext );
}
/**
* from string - first argument).
*/
@Test
- public void invokeRpcMethodTest() {
- ControllerContext contContext = ControllerContext.getInstance();
- contContext.onGlobalContextUpdated(TestUtils.loadSchemaContext(modules));
+ public void invokeRpcMtethodTest() {
+ ControllerContext contContext = controllerContext;
try {
contContext.findModuleNameByNamespace(new URI("invoke:rpc:module"));
} catch (URISyntaxException e) {
when(mockedBrokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenAnswer(new AnswerImpl());
StructuredData structData = restconf.invokeRpc("invoke-rpc-module:rpc-test", preparePayload());
-
- CompositeNode rpcCompNode = structData.getData();
- CompositeNode cont = null;
- assertEquals("invoke:rpc:module", rpcCompNode.getNodeType().getNamespace().toString());
- assertEquals("rpc-test", rpcCompNode.getNodeType().getLocalName());
-
- for (Node<?> node : rpcCompNode.getChildren()) {
- if (node.getNodeType().getLocalName().equals("cont")
- && node.getNodeType().getNamespace().toString().equals("nmspc")) {
- if (node instanceof CompositeNode) {
- cont = (CompositeNode) node;
- }
- }
- }
- assertNotNull(cont);
+ assertTrue(structData == null);
}
return cont;
}
+ @Test
+ public void testInvokeRpcWithNoPayloadRpc_FailNoErrors() {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(false);
+
+ ArgumentCaptor<CompositeNode> payload = ArgumentCaptor
+ .forClass(CompositeNode.class);
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when(
+ brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)cancel-toast")),
+ payload.capture())).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ try {
+ restconfImpl.invokeRpc("toaster:cancel-toast", "");
+ fail("Expected an exception to be thrown.");
+ } catch (ResponseException e) {
+ assertEquals(e.getMessage(),
+ Status.INTERNAL_SERVER_ERROR.getStatusCode(), e
+ .getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNoPayloadRpc_FailWithRpcError() {
+ List<RpcError> rpcErrors = new LinkedList<RpcError>();
+
+ RpcError unknownError = mock(RpcError.class);
+ when( unknownError.getTag() ).thenReturn( "bogusTag" );
+ rpcErrors.add( unknownError );
+
+ RpcError knownError = mock( RpcError.class );
+ when( knownError.getTag() ).thenReturn( "in-use" );
+ rpcErrors.add( knownError );
+
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(false);
+ when(rpcResult.getErrors()).thenReturn( rpcErrors );
+
+ ArgumentCaptor<CompositeNode> payload = ArgumentCaptor
+ .forClass(CompositeNode.class);
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when(
+ brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)cancel-toast")),
+ payload.capture())).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ try {
+ restconfImpl.invokeRpc("toaster:cancel-toast", "");
+ fail("Expected an exception to be thrown.");
+ } catch (ResponseException e) {
+ //TODO: Change to a 409 in the future - waiting on additional BUG to enhance this.
+ assertEquals(e.getMessage(), 500, e.getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNoPayload_Success() {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(true);
+
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when(
+ brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)cancel-toast")),
+ any( CompositeNode.class ))).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ StructuredData output = restconfImpl.invokeRpc("toaster:cancel-toast",
+ "");
+ assertEquals(null, output);
+ //additional validation in the fact that the restconfImpl does not throw an exception.
+ }
+
+ @Test
+ public void testInvokeRpcMethodExpectingNoPayloadButProvidePayload() {
+ try {
+ restconfImpl.invokeRpc("toaster:cancel-toast", " a payload ");
+ fail("Expected an exception");
+ } catch (ResponseException e) {
+ assertEquals(e.getMessage(),
+ Status.UNSUPPORTED_MEDIA_TYPE.getStatusCode(), e
+ .getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcMethodWithBadMethodName() {
+ try {
+ restconfImpl.invokeRpc("toaster:bad-method", "");
+ fail("Expected an exception");
+ } catch (ResponseException e) {
+ assertEquals(e.getMessage(), Status.NOT_FOUND.getStatusCode(), e
+ .getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcMethodWithInput() {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(true);
+
+ CompositeNode payload = mock(CompositeNode.class);
+
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when(
+ brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)make-toast")),
+ any(CompositeNode.class))).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ StructuredData output = restconfImpl.invokeRpc("toaster:make-toast",
+ payload);
+ assertEquals(null, output);
+ //additional validation in the fact that the restconfImpl does not throw an exception.
+ }
+
+ @Test
+ public void testThrowExceptionWhenSlashInModuleName() {
+ try {
+ restconfImpl.invokeRpc("toaster/slash", "");
+ fail("Expected an exception.");
+ } catch (ResponseException e) {
+ assertEquals(e.getMessage(), Status.NOT_FOUND.getStatusCode(), e
+ .getResponse().getStatus());
+ }
+ }
+
+ @Test
+ public void testInvokeRpcWithNoPayloadWithOutput_Success() {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(true);
+
+ CompositeNode compositeNode = mock( CompositeNode.class );
+ when( rpcResult.getResult() ).thenReturn( compositeNode );
+
+ BrokerFacade brokerFacade = mock(BrokerFacade.class);
+ when( brokerFacade.invokeRpc(
+ eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)testOutput")),
+ any( CompositeNode.class ))).thenReturn(rpcResult);
+
+ restconfImpl.setBroker(brokerFacade);
+
+ StructuredData output = restconfImpl.invokeRpc("toaster:testOutput",
+ "");
+ assertNotNull( output );
+ assertSame( compositeNode, output.getData() );
+ assertNotNull( output.getSchema() );
+ }
+
+ @Test
+ public void testMountedRpcCallNoPayload_Success() throws Exception
+ {
+ RpcResult<CompositeNode> rpcResult = mock(RpcResult.class);
+ when(rpcResult.isSuccessful()).thenReturn(true);
+
+ ListenableFuture<RpcResult<CompositeNode>> mockListener = mock( ListenableFuture.class );
+ when( mockListener.get() ).thenReturn( rpcResult );
+
+ QName cancelToastQName = QName.create( "cancelToast" );
+
+ RpcDefinition mockRpc = mock( RpcDefinition.class );
+ when( mockRpc.getQName() ).thenReturn( cancelToastQName );
+
+ MountInstance mockMountPoint = mock( MountInstance.class );
+ when( mockMountPoint.rpc( eq( cancelToastQName ), any( CompositeNode.class ) ) )
+ .thenReturn( mockListener );
+
+ InstanceIdWithSchemaNode mockedInstanceId = mock( InstanceIdWithSchemaNode.class );
+ when( mockedInstanceId.getMountPoint() ).thenReturn( mockMountPoint );
+
+ ControllerContext mockedContext = mock( ControllerContext.class );
+ String cancelToastStr = "toaster:cancel-toast";
+ when( mockedContext.urlPathArgDecode( cancelToastStr ) ).thenReturn( cancelToastStr );
+ when( mockedContext.getRpcDefinition( cancelToastStr ) ).thenReturn( mockRpc );
+ when( mockedContext.toMountPointIdentifier( "opendaylight-inventory:nodes/node/"
+ + "REMOTE_HOST/yang-ext:mount/toaster:cancel-toast" ) ).thenReturn( mockedInstanceId );
+
+ restconfImpl.setControllerContext( mockedContext );
+ StructuredData output = restconfImpl.invokeRpc(
+ "opendaylight-inventory:nodes/node/REMOTE_HOST/yang-ext:mount/toaster:cancel-toast",
+ "");
+ assertEquals(null, output);
+
+ //additional validation in the fact that the restconfImpl does not throw an exception.
+ }
+
+
}
*/
package org.opendaylight.controller.sal.restconf.impl.test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
import java.io.FileNotFoundException;
import java.util.Set;
+
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+/**
+ * @See {@link InvokeRpcMethodTest}
+ *
+ */
public class RestconfImplTest {
- private static final RestconfImpl restconfImpl = RestconfImpl.getInstance();
+ private RestconfImpl restconfImpl = null;
+ private static ControllerContext controllerContext = null;
@BeforeClass
public static void init() throws FileNotFoundException {
- Set<Module> allModules = TestUtils.loadModulesFrom("/full-versions/yangs");
+ Set<Module> allModules = TestUtils
+ .loadModulesFrom("/full-versions/yangs");
assertNotNull(allModules);
SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
- ControllerContext controllerContext = ControllerContext.getInstance();
+ controllerContext = spy( ControllerContext.getInstance() );
controllerContext.setSchemas(schemaContext);
- restconfImpl.setControllerContext(controllerContext);
+
+ }
+
+ @Before
+ public void initMethod()
+ {
+ restconfImpl = RestconfImpl.getInstance();
+ restconfImpl.setControllerContext( controllerContext );
}
@Test
public void testExample() throws FileNotFoundException {
- CompositeNode loadedCompositeNode = TestUtils.readInputToCnSn("/parts/ietf-interfaces_interfaces.xml", XmlToCompositeNodeProvider.INSTANCE);
+ CompositeNode loadedCompositeNode = TestUtils.readInputToCnSn(
+ "/parts/ietf-interfaces_interfaces.xml",
+ XmlToCompositeNodeProvider.INSTANCE);
BrokerFacade brokerFacade = mock(BrokerFacade.class);
- when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode);
- assertEquals(loadedCompositeNode, brokerFacade.readOperationalData(null));
+ when(brokerFacade.readOperationalData(any(InstanceIdentifier.class)))
+ .thenReturn(loadedCompositeNode);
+ assertEquals(loadedCompositeNode,
+ brokerFacade.readOperationalData(null));
}
+
}
--- /dev/null
+ module toaster {
+
+ yang-version 1;
+
+ namespace
+ "http://netconfcentral.org/ns/toaster";
+
+ prefix toast;
+
+ organization "Netconf Central";
+
+ contact
+ "Andy Bierman <andy@netconfcentral.org>";
+
+ description
+ "YANG version of the TOASTER-MIB.";
+
+ revision "2009-11-20" {
+ description
+ "Toaster module in progress.";
+ }
+
+
+ identity toast-type {
+ description
+ "Base for all bread types supported by the toaster.
+ New bread types not listed here nay be added in the
+ future.";
+ }
+
+ identity white-bread {
+ base toast:toast-type;
+ description "White bread.";
+ }
+
+ identity wheat-bread {
+ base toast-type;
+ description "Wheat bread.";
+ }
+
+ identity wonder-bread {
+ base toast-type;
+ description "Wonder bread.";
+ }
+
+ identity frozen-waffle {
+ base toast-type;
+ description "Frozen waffle.";
+ }
+
+ identity frozen-bagel {
+ base toast-type;
+ description "Frozen bagel.";
+ }
+
+ identity hash-brown {
+ base toast-type;
+ description "Hash browned potatos.";
+ }
+
+ typedef DisplayString {
+ type string {
+ length "0 .. 255";
+ }
+ description
+ "YANG version of the SMIv2 DisplayString TEXTUAL-CONVENTION.";
+ reference
+ "RFC 2579, section 2.";
+
+ }
+
+ container toaster {
+ presence
+ "Indicates the toaster service is available";
+ description
+ "Top-level container for all toaster database objects.";
+ leaf toasterManufacturer {
+ type DisplayString;
+ config false;
+ mandatory true;
+ description
+ "The name of the toaster's manufacturer. For instance,
+ Microsoft Toaster.";
+ }
+
+ leaf toasterModelNumber {
+ type DisplayString;
+ config false;
+ mandatory true;
+ description
+ "The name of the toaster's model. For instance,
+ Radiant Automatic.";
+ }
+
+ leaf toasterStatus {
+ type enumeration {
+ enum "up" {
+ value 1;
+ description
+ "The toaster knob position is up.
+ No toast is being made now.";
+ }
+ enum "down" {
+ value 2;
+ description
+ "The toaster knob position is down.
+ Toast is being made now.";
+ }
+ }
+ config false;
+ mandatory true;
+ description
+ "This variable indicates the current state of
+ the toaster.";
+ }
+ } // container toaster
+
+ rpc make-toast {
+ description
+ "Make some toast.
+ The toastDone notification will be sent when
+ the toast is finished.
+ An 'in-use' error will be returned if toast
+ is already being made.
+ A 'resource-denied' error will be returned
+ if the toaster service is disabled.";
+ input {
+ leaf toasterDoneness {
+ type uint32 {
+ range "1 .. 10";
+ }
+ default '5';
+ description
+ "This variable controls how well-done is the
+ ensuing toast. It should be on a scale of 1 to 10.
+ Toast made at 10 generally is considered unfit
+ for human consumption; toast made at 1 is warmed
+ lightly.";
+ }
+
+ leaf toasterToastType {
+ type identityref {
+ base toast:toast-type;
+ }
+ default 'wheat-bread';
+ description
+ "This variable informs the toaster of the type of
+ material that is being toasted. The toaster
+ uses this information, combined with
+ toasterDoneness, to compute for how
+ long the material must be toasted to achieve
+ the required doneness.";
+ }
+ }
+ } // rpc make-toast
+
+ rpc testOutput {
+ output {
+ leaf textOut {
+ type string;
+ }
+ }
+ }
+
+ rpc cancel-toast {
+ description
+ "Stop making toast, if any is being made.
+ A 'resource-denied' error will be returned
+ if the toaster service is disabled.";
+ } // rpc cancel-toast
+
+ notification toastDone {
+ description
+ "Indicates that the toast in progress has completed.";
+ leaf toastStatus {
+ type enumeration {
+ enum "done" {
+ value 0;
+ description "The toast is done.";
+ }
+ enum "cancelled" {
+ value 1;
+ description
+ "The toast was cancelled.";
+ }
+ enum "error" {
+ value 2;
+ description
+ "The toaster service was disabled or
+ the toaster is broken.";
+ }
+ }
+ description
+ "Indicates the final toast status";
+ }
+ } // notification toastDone
+ } // module toaster
<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;
+++ /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>
package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
+import java.lang.ref.SoftReference;
import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
import javax.annotation.concurrent.GuardedBy;
public class YangStoreServiceImpl implements YangStoreService {
private final SchemaContextProvider service;
@GuardedBy("this")
- private YangStoreSnapshotImpl cache = null;
+ private SoftReference<YangStoreSnapshotImpl> cache = new SoftReference<>(null);
public YangStoreServiceImpl(SchemaContextProvider service) {
this.service = service;
@Override
public synchronized YangStoreSnapshotImpl getYangStoreSnapshot() throws YangStoreException {
- if (cache == null) {
- cache = new YangStoreSnapshotImpl(service.getSchemaContext());
+ YangStoreSnapshotImpl yangStoreSnapshot = cache.get();
+ if (yangStoreSnapshot == null) {
+ yangStoreSnapshot = new YangStoreSnapshotImpl(service.getSchemaContext());
+ cache = new SoftReference<>(yangStoreSnapshot);
}
- return cache;
+ return yangStoreSnapshot;
}
/**
* Called when schema context changes, invalidates cache.
*/
public synchronized void refresh() {
- cache = null;
+ cache.clear();
}
}
throw new IllegalStateException(e);
}
logger.info("Configuration Persister initialization completed.");
+
+ /*
+ * We have completed initial configuration. At this point
+ * it is good idea to perform garbage collection to prune
+ * any garbage we have accumulated during startup.
+ */
+ logger.debug("Running post-initialization garbage collection...");
+ System.gc();
+ logger.debug("Post-initialization garbage collection completed.");
+
ConfigPersisterNotificationHandler jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator);
synchronized (ConfigPersisterActivator.this) {
autoCloseables.add(jmxNotificationHandler);
synchronized (ConfigPersisterActivator.this) {
autoCloseables.add(new AutoCloseable() {
@Override
- public void close() throws Exception {
+ public void close() {
pushingThread.interrupt();
}
});
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util;
-
-import org.opendaylight.controller.netconf.api.NetconfMessage;
+package org.opendaylight.controller.netconf.api;
/**
* Session capable of exi communication according to http://tools.ietf.org/html/draft-varga-netconf-exi-capability-02
<groupId>${project.groupId}</groupId>
<artifactId>netconf-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netconf-util</artifactId>
javax.xml.parsers,
javax.xml.xpath,
org.opendaylight.controller.netconf.api,
- org.opendaylight.controller.netconf.util,
org.opendaylight.controller.netconf.util.*,
+ org.opendaylight.controller.netconf.nettyutil.*,
org.opendaylight.protocol.framework,
org.openexi.*,
org.slf4j,
package org.opendaylight.controller.netconf.client;
+import io.netty.channel.Channel;
import java.util.Collection;
-
-import org.opendaylight.controller.netconf.util.AbstractNetconfSession;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXIToMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToEXIEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSession;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXIToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToEXIEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.netty.channel.Channel;
-
public final class NetconfClientSession extends AbstractNetconfSession<NetconfClientSession, NetconfClientSessionListener> {
private static final Logger logger = LoggerFactory.getLogger(NetconfClientSession.class);
package org.opendaylight.controller.netconf.client;
+import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
import java.util.Collection;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
-
import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
-import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSessionNegotiator;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
-import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import io.netty.channel.Channel;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
-
public class NetconfClientSessionNegotiator extends
AbstractNetconfSessionNegotiator<NetconfClientSessionPreferences, NetconfClientSession, NetconfClientSessionListener>
{
import org.opendaylight.controller.netconf.api.NetconfClientSessionPreferences;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
-import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.protocol.framework.SessionListenerFactory;
import org.opendaylight.protocol.framework.SessionNegotiator;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
-import org.opendaylight.controller.netconf.util.handler.ssh.SshHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker;
-import org.opendaylight.protocol.framework.SessionListenerFactory;
-
import java.io.IOException;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.SshHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.Invoker;
+import org.opendaylight.protocol.framework.SessionListenerFactory;
final class SshClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
import org.opendaylight.protocol.framework.SessionListenerFactory;
class TcpClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.protocol.framework.ReconnectStrategy;
-import java.net.InetSocketAddress;
-
public class NetconfClientConfiguration {
private final NetconfClientProtocol clientProtocol;
*/
package org.opendaylight.controller.netconf.client.conf;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.protocol.framework.ReconnectStrategy;
-import java.net.InetSocketAddress;
-
public class NetconfClientConfigurationBuilder {
public static final int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 5000;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.protocol.framework.ReconnectStrategy;
import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
-import java.net.InetSocketAddress;
-
public final class NetconfReconnectingClientConfiguration extends NetconfClientConfiguration {
private final ReconnectStrategyFactory connectStrategyFactory;
package org.opendaylight.controller.netconf.client.conf;
import java.net.InetSocketAddress;
-
import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.protocol.framework.ReconnectStrategy;
import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
<groupId>${project.groupId}</groupId>
<artifactId>netconf-mapping-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netconf-util</artifactId>
org.opendaylight.controller.netconf.api,
org.opendaylight.controller.netconf.api.jmx,
org.opendaylight.controller.netconf.mapping.api,
- org.opendaylight.controller.netconf.util,
- org.opendaylight.controller.netconf.util.mapping,
- org.opendaylight.controller.netconf.util.osgi,
- org.opendaylight.controller.netconf.util.xml,
- org.opendaylight.controller.netconf.util.exception,
- org.opendaylight.controller.netconf.util.handler,
+ org.opendaylight.controller.netconf.util.*,
org.opendaylight.protocol.framework,
org.osgi.framework,
org.osgi.util.tracker,
org.slf4j,
org.w3c.dom,
org.xml.sax,
- org.opendaylight.controller.netconf.util.messages,
io.netty.util.internal,
org.opendaylight.controller.netconf.api.monitoring,
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924,
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas,
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,
org.opendaylight.yangtools.yang.binding,
- org.openexi.*,</Import-Package>
+ org.openexi.*,
+ org.opendaylight.controller.netconf.nettyutil.*</Import-Package>
</instructions>
</configuration>
</plugin>
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
+import java.net.InetSocketAddress;
import org.opendaylight.controller.netconf.impl.util.DeserializerExceptionHandler;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer;
import org.opendaylight.protocol.framework.AbstractDispatcher;
-import java.net.InetSocketAddress;
-
public class NetconfServerDispatcher extends AbstractDispatcher<NetconfServerSession, NetconfServerSessionListener> {
private final ServerChannelInitializer initializer;
package org.opendaylight.controller.netconf.impl;
+import com.google.common.base.Preconditions;
+import io.netty.channel.Channel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
-import org.opendaylight.controller.netconf.util.AbstractNetconfSession;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXIToMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToEXIEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSession;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXIToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToEXIEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import io.netty.channel.Channel;
-
public final class NetconfServerSession extends AbstractNetconfSession<NetconfServerSession, NetconfServerSessionListener> implements NetconfManagementSession {
private static final Logger logger = LoggerFactory.getLogger(NetconfServerSession.class);
package org.opendaylight.controller.netconf.impl;
+import com.google.common.base.Optional;
+import io.netty.channel.Channel;
+import io.netty.util.Timer;
+import io.netty.util.concurrent.Promise;
import java.net.InetSocketAddress;
-
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
-import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator;
+import org.opendaylight.controller.netconf.nettyutil.AbstractNetconfSessionNegotiator;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-
-import io.netty.channel.Channel;
-import io.netty.util.Timer;
-import io.netty.util.concurrent.Promise;
-
public class NetconfServerSessionNegotiator extends
AbstractNetconfSessionNegotiator<NetconfServerSessionPreferences, NetconfServerSession, NetconfServerSessionListener> {
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.concurrent.GlobalEventExecutor;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
-
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
-import org.opendaylight.controller.netconf.util.messages.NetconfStartExiMessage;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.HashedWheelTimer;
-import io.netty.util.concurrent.GlobalEventExecutor;
-
@RunWith(Parameterized.class)
public class ConcurrentClientsTest {
private static final Logger logger = LoggerFactory.getLogger(ConcurrentClientsTest.class);
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;
-
import java.util.Queue;
-
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.handler.ChunkedFramingMechanismEncoder;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.ChunkedFramingMechanismEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfChunkAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEOMAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
</properties>
<dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.logback_settings</artifactId>
<artifactId>netconf-monitoring</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-netty-util</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netconf-ssh</artifactId>
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import ch.ethz.ssh2.Connection;
+import io.netty.channel.ChannelFuture;
+import io.netty.util.concurrent.GlobalEventExecutor;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Collection;
import java.util.List;
-
import junit.framework.Assert;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.controller.usermanager.IUserManager;
import org.opendaylight.protocol.framework.NeverReconnectStrategy;
-import ch.ethz.ssh2.Connection;
-import io.netty.channel.ChannelFuture;
-import io.netty.util.concurrent.GlobalEventExecutor;
-
public class NetconfITSecureTest extends AbstractNetconfConfigTest {
private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024);
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ ~
+ ~ This program and the accompanying materials are made available under the
+ ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-subsystem</artifactId>
+ <version>0.2.5-SNAPSHOT</version>
+ </parent>
+ <artifactId>netconf-netty-util</artifactId>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <!-- compile dependencies -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-mapping-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-handler</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>protocol-framework</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>ganymed</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openexi</groupId>
+ <artifactId>nagasena</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openexi</groupId>
+ <artifactId>nagasena-rta</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>ch.ethz.ssh2, com.google.common.base, com.google.common.collect, io.netty.buffer,
+ io.netty.channel, io.netty.channel.socket, io.netty.handler.codec, io.netty.handler.ssl, io.netty.util,
+ io.netty.util.concurrent, javax.xml.transform, javax.xml.transform.dom, javax.xml.transform.sax,
+ javax.xml.transform.stream, org.opendaylight.controller.netconf.api,
+ org.opendaylight.controller.netconf.util.messages, org.opendaylight.controller.netconf.util.xml,
+ org.opendaylight.protocol.framework, org.openexi.proc, org.openexi.proc.common, org.openexi.proc.grammars,
+ org.openexi.sax, org.openexi.schema, org.slf4j, org.w3c.dom, org.xml.sax</Import-Package>
+ <Export-Package>org.opendaylight.controller.netconf.nettyutil,
+ org.opendaylight.controller.netconf.nettyutil.handler,
+ org.opendaylight.controller.netconf.nettyutil.handler.exi,
+ org.opendaylight.controller.netconf.nettyutil.handler.ssh,
+ org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication,
+ org.opendaylight.controller.netconf.nettyutil.handler.ssh.client</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ <phase>package</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util;
+package org.opendaylight.controller.netconf.nettyutil;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.Promise;
-
import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfHelloMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEOMAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfHelloMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToHelloMessageDecoder;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
public abstract class AbstractChannelInitializer<S extends NetconfSession> {
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util;
+package org.opendaylight.controller.netconf.nettyutil;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandler;
import java.io.IOException;
-
+import org.opendaylight.controller.netconf.api.NetconfExiSession;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.api.NetconfSessionListener;
import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.handler.NetconfEXICodec;
-import org.opendaylight.controller.netconf.util.xml.EXIParameters;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.controller.netconf.nettyutil.handler.exi.EXIParameters;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.protocol.framework.AbstractProtocolSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelHandler;
-
public abstract class AbstractNetconfSession<S extends NetconfSession, L extends NetconfSessionListener<S>> extends AbstractProtocolSession<NetconfMessage> implements NetconfSession, NetconfExiSession {
private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfSession.class);
private final L sessionListener;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util;
+package org.opendaylight.controller.netconf.nettyutil;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.Promise;
+import java.util.concurrent.TimeUnit;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSessionListener;
import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfChunkAggregator;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToHelloMessageDecoder;
+import org.opendaylight.controller.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
-import java.util.concurrent.TimeUnit;
-
public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionPreferences, S extends AbstractNetconfSession<S, L>, L extends NetconfSessionListener<S>>
extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
import org.slf4j.Logger;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import java.util.List;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import com.google.common.base.Preconditions;
import org.openexi.proc.HeaderOptionsOutputType;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import java.io.InputStream;
import java.util.List;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import java.util.List;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.xml;
+package org.opendaylight.controller.netconf.nettyutil.handler.exi;
import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.openexi.proc.common.AlignmentType;
import org.openexi.proc.common.EXIOptions;
import org.openexi.proc.common.EXIOptionsException;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.messages;
+package org.opendaylight.controller.netconf.nettyutil.handler.exi;
import java.util.List;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import java.io.IOException;
import java.net.SocketAddress;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.Invoker;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.SshClient;
-import org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter;
-import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocket;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClient;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.Invoker;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClientAdapter;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
/**
* Netty SSH handler class. Acts as interface between Netty and SSH library. All standard Netty message handling
- * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter};
+ * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClientAdapter};
*/
public class SshHandler extends ChannelOutboundHandlerAdapter {
private static final String SOCKET = "socket";
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.authentication;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication;
import ch.ethz.ssh2.Connection;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.authentication;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication;
import ch.ethz.ssh2.Connection;
/**
* Class Providing username/password authentication option to
- * {@link org.opendaylight.controller.netconf.util.handler.ssh.SshHandler}
+ * {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.SshHandler}
*/
public class LoginPassword extends AuthenticationHandler {
private final String username;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
import java.io.IOException;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.channel.Channel;
-import org.opendaylight.controller.netconf.util.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocket;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
import java.io.IOException;
import java.util.HashMap;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.VirtualSocketException;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocketException;
/**
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.client;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket;
+package org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket;
/**
* Exception class which provides notification about exceptional situations at the virtual socket layer.
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.handler;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.netconf.util.messages;
+package org.opendaylight.controller.netconf.nettyutil.handler;
import static org.junit.Assert.assertEquals;
-import io.netty.buffer.Unpooled;
+import com.google.common.io.Files;
+import io.netty.buffer.Unpooled;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
-
import org.junit.Test;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
-
-import com.google.common.io.Files;
public class NetconfMessageFactoryTest {
@Test
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-api</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>protocol-framework</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.thirdparty</groupId>
- <artifactId>ganymed</artifactId>
- </dependency>
- <dependency>
- <groupId>org.openexi</groupId>
- <artifactId>nagasena</artifactId>
- </dependency>
- <dependency>
- <groupId>org.openexi</groupId>
- <artifactId>nagasena-rta</artifactId>
- </dependency>
-
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Export-Package>org.opendaylight.controller.netconf.util,
- org.opendaylight.controller.netconf.util.xml,
- org.opendaylight.controller.netconf.util.osgi,
- org.opendaylight.controller.netconf.util.mapping,
- org.opendaylight.controller.netconf.util.messages,
- org.opendaylight.controller.netconf.util.handler,
- org.opendaylight.controller.netconf.util.handler.*,
- org.opendaylight.controller.netconf.util.exception,</Export-Package>
- <Import-Package>com.google.common.base,
- com.google.common.collect,
- ch.ethz.ssh2,
- io.netty.buffer,
- io.netty.channel,
- io.netty.channel.socket,
- io.netty.handler.codec,
- io.netty.handler.ssl,
- io.netty.util,
- io.netty.util.concurrent,
- javax.annotation,
- javax.net.ssl,
- javax.xml.namespace,
- javax.xml.parsers,
- javax.xml.transform,
- javax.xml.transform.dom,
- javax.xml.transform.stream,
- javax.xml.validation,
- javax.xml.xpath,
- javax.xml.transform.sax,
- org.opendaylight.controller.netconf.api,
- org.opendaylight.controller.netconf.mapping.api,
- org.opendaylight.protocol.framework,
- org.osgi.framework,
- org.slf4j,
- org.w3c.dom,
- org.xml.sax,
- org.xml.sax.helpers,
- org.opendaylight.controller.config.api,
- org.openexi.*,</Import-Package>
+ <Import-Package>com.google.common.base, com.google.common.collect, io.netty.channel,
+ io.netty.util.concurrent, javax.annotation, javax.xml.namespace, javax.xml.parsers, javax.xml.transform,
+ javax.xml.transform.dom, javax.xml.transform.stream, javax.xml.validation, javax.xml.xpath,
+ org.opendaylight.controller.netconf.api, org.opendaylight.controller.netconf.mapping.api,
+ org.osgi.framework, org.slf4j, org.w3c.dom, org.xml.sax</Import-Package>
+ <Export-Package>org.opendaylight.controller.netconf.util.*</Export-Package>
</instructions>
</configuration>
</plugin>
import com.google.common.base.Preconditions;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
public final class NetconfUtil {
private NetconfUtil() {}
- public static NetconfMessage createMessage(final File f) {
- Preconditions.checkNotNull(f, "File parameter was null");
- try {
- return createMessage(new FileInputStream(f));
- } catch (final FileNotFoundException e) {
- logger.warn("File {} not found.", f, e);
- }
- return null;
- }
-
- public static NetconfMessage createMessage(final InputStream is) {
- Preconditions.checkNotNull(is, "InputStream parameter was null");
- Document doc = null;
- try {
- doc = XmlUtil.readXmlToDocument(is);
- } catch (final IOException e) {
- logger.warn("Error ocurred while parsing stream.", e);
- } catch (final SAXException e) {
- logger.warn("Error ocurred while final parsing stream.", e);
- }
- return (doc == null) ? null : new NetconfMessage(doc);
- }
-
public static Document checkIsMessageOk(Document response) throws NetconfDocumentedException {
XmlElement element = XmlElement.fromDomDocument(response);
Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
<module>netconf-impl</module>
<module>config-netconf-connector</module>
<module>netconf-util</module>
+ <module>netconf-netty-util</module>
<module>config-persister-impl</module>
<module>netconf-mapping-api</module>
<module>netconf-client</module>
*/
@Override
public void notifyNodeDisconnectFromMaster(Node node) {
- for (String pluginType : this.pluginService.keySet()) {
- IPluginInConnectionService s = pluginService.get(pluginType);
- s.notifyNodeDisconnectFromMaster(node);
+ IPluginInConnectionService s = pluginService.get(node.getType());
+ if (s != null) {
+ s.notifyNodeDisconnectFromMaster(node);
}
}
-}
\ No newline at end of file
+}
import org.opendaylight.controller.sal.reader.NodeDescription;
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
ForwardingMode mode = (ForwardingMode) nodeProperties.get(ForwardingMode.name);
forwardingModeChanged = mode.isProactive();
}
+ } else if ((conf == null) && !(GlobalConstants.DEFAULT.toString().equals(containerName))) {
+ ISwitchManager defaultSwitchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, GlobalConstants.DEFAULT.toString(), this);
+ if (defaultSwitchManager != null) {
+ Property defaultContainerSwitchDesc = (Description) defaultSwitchManager.getNodeProp(node, Description.propertyName);
+ if (defaultContainerSwitchDesc != null) {
+ Map<String, Property> descPropMap = new HashMap<String, Property>();
+ descPropMap.put(Description.propertyName, defaultContainerSwitchDesc);
+ conf = new SwitchConfig(nodeId, descPropMap);
+ updateNodeConfig(conf);
+ propMap.put(Description.propertyName, defaultContainerSwitchDesc);
+ }
+ }
}
}
<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>