<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
org.apache.felix.dm,</Import-Package>
<Export-Package>org.opendaylight.controller.appauth,
org.opendaylight.controller.appauth.authorization</Export-Package>
- <Bundle-Activator></Bundle-Activator>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
* passed and so on.
*/
public class CacheConfigException extends Exception {
+ private static final long serialVersionUID = 1L;
/**
* Instantiates a new cache config exception.
* allocated already exists
*/
public class CacheExistException extends Exception {
+ private static final long serialVersionUID = 1L;
/**
* Instantiates a new cache exist exception.
* Listener being added fails for any reason
*/
public class CacheListenerAddException extends Exception {
+ private static final long serialVersionUID = 1L;
/**
* Instantiates a new cache listener add exception.
* @deprecated for internal use
* The Class ListenRoleChangeAddException.
*/
+@Deprecated
public class ListenRoleChangeAddException extends Exception {
+ private static final long serialVersionUID = 1L;
/**
* Instantiates a new listen role change add exception.
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
!org.hornetq.*,
!org.jboss.*,
javax.transaction,
- *,
org.opendaylight.controller.clustering.services,
- org.opendaylight.controller.sal.core</Import-Package>
+ org.opendaylight.controller.sal.core,*</Import-Package>
<Bundle-Activator>org.opendaylight.controller.clustering.services_implementation.internal.Activator</Bundle-Activator>
<!-- Add in the DynamicImport-Package ONLY the packages that -->
<!-- contains types that MUST be unmarshalled by the -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
import java.io.Serializable;
public class ComplexClass implements IComplex, Serializable {
+ private static final long serialVersionUID = 1L;
private String identity;
public ComplexClass(String i) {
import java.io.Serializable;
public class ComplexClass1 implements IComplex, Serializable {
+ private static final long serialVersionUID = 1L;
private String identity;
public ComplexClass1(String i) {
import java.io.Serializable;
public class ComplexContainer implements Serializable {
- private IComplex f;
- private IComplex f1;
- private Integer state;
+ private static final long serialVersionUID = 1L;
+ private final IComplex f;
+ private final IComplex f1;
+ private final Integer state;
public ComplexContainer(String i, Integer s) {
this.state = s;
import java.io.Serializable;
public class StringContainer implements Serializable {
+ private static final long serialVersionUID = 1L;
private String mystring;
public StringContainer() {
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<asm.version>4.1</asm.version>
<!-- Plugin Versions -->
<bouncycastle.version>1.50</bouncycastle.version>
- <bundle.plugin.version>2.3.7</bundle.plugin.version>
+ <bundle.plugin.version>2.4.0</bundle.plugin.version>
<bundlescanner.version>0.4.2-SNAPSHOT</bundlescanner.version>
<checkstyle.version>2.10</checkstyle.version>
<clustering.services.version>0.5.1-SNAPSHOT</clustering.services.version>
<eclipse.persistence.version>2.5.0</eclipse.persistence.version>
<!-- enforcer version -->
<enforcer.version>1.3.1</enforcer.version>
- <enunciate.version>1.26.2</enunciate.version>
+ <enunciate.version>1.28</enunciate.version>
<exam.version>3.0.0</exam.version>
<!-- OpenEXI third party lib for netconf-->
<configFile>enunciate.xml</configFile>
</configuration>
<dependencies>
+ <dependency>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>enunciate-swagger</artifactId>
+ <version>${enunciate.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.logback_settings</artifactId>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
- <version>${jacoco.version}</version>
<executions>
<execution>
<goals>
package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory;
-import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
+import java.util.LinkedHashMap;
+
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.TypeName;
-import java.util.LinkedHashMap;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
public class ConcreteModuleGeneratedObjectFactory {
}
private static String getNewCtor(FullyQualifiedName fqn) {
- LinkedHashMap<String, String> parameters = new LinkedHashMap<String, String>(){
- {
- put(ModuleIdentifier.class.getCanonicalName(), "identifier");
- put(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
- }
- };
+ LinkedHashMap<String, String> parameters = new LinkedHashMap<>();
+ parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier");
+ parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
+
StringBuilder stringBuilder = getCtor(fqn, parameters);
return stringBuilder.toString();
}
}
private static String getCopyCtor(final FullyQualifiedName fqn) {
- LinkedHashMap<String, String> parameters = new LinkedHashMap<String, String>(){
- {
- put(ModuleIdentifier.class.getCanonicalName(), "identifier");
- put(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
- put(fqn.toString(), "oldModule");
- put(AutoCloseable.class.getCanonicalName(), "oldInstance");
- }
- };
+ LinkedHashMap<String, String> parameters = new LinkedHashMap<>();
+ parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier");
+ parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
+ parameters.put(fqn.toString(), "oldModule");
+ parameters.put(AutoCloseable.class.getCanonicalName(), "oldInstance");
StringBuilder stringBuilder = getCtor(fqn, parameters);
return stringBuilder.toString();
}
import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.List;
import java.util.regex.Pattern;
public static Optional<String> loadCopyright() {
- try (InputStream in = StringUtil.class.getResourceAsStream("/copyright.txt")) {
- if (in != null) {
- return Optional.of(IOUtils.toString(in));
+ /*
+ * FIXME: BUG-980: this is a nice feature, but the copyright needs to come
+ * from the project being processed, not this one.
+ try (InputStream in = StringUtil.class.getResourceAsStream("/copyright.txt")) {
+ if (in != null) {
+ return Optional.of(IOUtils.toString(in));
+ }
+ } catch (IOException e) {
+ logger.warn("Cannot load copyright.txt", e);
}
- } catch (IOException e) {
- logger.warn("Cannot load copyright.txt", e);
- }
+
+ */
return Optional.absent();
}
+++ /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.config.yangjmxgenerator.plugin.util;
+import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName;
}
@Test
+ @Ignore
public void testCopyright() throws IOException {
assertTrue(StringUtil.loadCopyright().isPresent());
}
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-impl</artifactId>
- <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-spi</artifactId>
- <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-util</artifactId>
- <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-type-provider</artifactId>
- <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-api</artifactId>
- <version>${yangtools.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-impl</artifactId>
- <version>${yangtools.version}</version>
</dependency>
<!-- yang model dependencies -->
<dependency>
<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:config:toaster-provider:impl">
- prefix:toaster-provider-impl
+ <type xmlns:toaster="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+ toaster:toaster-provider-impl
</type>
<name>toaster-provider-impl</name>
<name>binding-rpc-broker</name>
</rpc-registry>
+ <data-broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <name>binding-data-broker</name>
+ </data-broker>
+
<notification-service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
binding:binding-notification-service
</module>
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl">
- prefix:toaster-consumer-impl
+ <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+ kitchen:kitchen-service-impl
</type>
- <name>toaster-consumer-impl</name>
+ <name>kitchen-service-impl</name>
<rpc-registry>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
</notification-service>
</module>
</modules>
-
+
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<service>
- <type xmlns:toaster="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider">toaster:toaster-provider</type>
- <instance>
- <name>toaster-provider</name>
- <provider>/modules/module[type='toaster-provider-impl'][name='toaster-provider-impl']</provider>
- </instance>
- </service>
- <service>
- <type xmlns:toaster="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer">toaster:toaster-consumer</type>
+ <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+ kitchen:kitchen-service
+ </type>
<instance>
- <name>toaster-consumer</name>
- <provider>/modules/module[type='toaster-consumer-impl'][name='toaster-consumer-impl']</provider>
+ <name>kitchen-service</name>
+ <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
</instance>
</service>
</services>
</configuration>
<required-capabilities>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer?module=toaster-consumer&revision=2014-01-31</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl?module=toaster-consumer-impl&revision=2014-01-31</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider?module=toaster-provider&revision=2014-01-31</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&revision=2014-01-31</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&revision=2014-01-31</capability>
</required-capabilities>
########################################
# Now add to classpath the OSGi JAR
########################################
-CLASSPATH="${basedir}"/lib/org.eclipse.osgi-3.8.1.v20120830-144521.jar
+CLASSPATH=${CLASSPATH}:${basedir}/lib/org.eclipse.osgi-3.8.1.v20120830-144521.jar
FWCLASSPATH=file:"${basedir}"/lib/org.eclipse.osgi-3.8.1.v20120830-144521.jar
########################################
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<instructions>
<Import-Package>*</Import-Package>
<Export-Package>org.eclipse.osgi.framework.console</Export-Package>
- <Bundle-Activator></Bundle-Activator>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
+ *
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.controller.sal.compatibility;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import org.eclipse.xtext.xbase.lib.Exceptions;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+
import org.opendaylight.controller.sal.common.util.Arguments;
import org.opendaylight.controller.sal.core.AdvertisedBandwidth;
import org.opendaylight.controller.sal.core.Bandwidth;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
-@SuppressWarnings("all")
-public class NodeMapping {
+public final class NodeMapping {
public final static String MD_SAL_TYPE = "MD_SAL";
-
+
private final static Class<Node> NODE_CLASS = Node.class;
-
+
private final static Class<NodeConnector> NODECONNECTOR_CLASS = NodeConnector.class;
-
+
private NodeMapping() {
throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
}
-
+
public static org.opendaylight.controller.sal.core.Node toADNode(final InstanceIdentifier<? extends Object> node) throws ConstructionException {
NodeId nodeId = NodeMapping.toNodeId(node);
return NodeMapping.toADNode(nodeId);
}
-
- public static org.opendaylight.controller.sal.core.Node toADNode(final NodeId id) {
- try {
+
+ public static org.opendaylight.controller.sal.core.Node toADNode(final NodeId id) throws ConstructionException {
String aDNodeId = NodeMapping.toADNodeId(id);
return new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, aDNodeId);
- } catch (Throwable e) {
- throw Exceptions.sneakyThrow(e);
- }
}
-
+
public static NodeId toNodeId(final InstanceIdentifier<? extends Object> node) {
Preconditions.<InstanceIdentifier<? extends Object>>checkNotNull(node);
List<PathArgument> path = node.getPath();
Preconditions.checkArgument(size >= 2);
final PathArgument arg = path.get(1);
final IdentifiableItem item = Arguments.<IdentifiableItem>checkInstanceOf(arg, IdentifiableItem.class);
- Identifier key = item.getKey();
+ Identifier<?> key = item.getKey();
final NodeKey nodeKey = Arguments.<NodeKey>checkInstanceOf(key, NodeKey.class);
return nodeKey.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());
final NodeConnectorKey connectorKey = Arguments.<NodeConnectorKey>checkInstanceOf(item.getKey(), NodeConnectorKey.class);
return NodeMapping.toADNodeConnector(connectorKey.getId(), NodeMapping.toNodeId(path));
}
-
- public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorId ncid, final NodeId nid) {
- try {
- String nodeConnectorType = NodeMapping.toNodeConnectorType(ncid, nid);
- Object aDNodeConnectorId = NodeMapping.toADNodeConnectorId(ncid, nid);
- org.opendaylight.controller.sal.core.Node aDNode = NodeMapping.toADNode(nid);
- return new org.opendaylight.controller.sal.core.NodeConnector(nodeConnectorType, aDNodeConnectorId, aDNode);
- } catch (Throwable e) {
- throw Exceptions.sneakyThrow(e);
- }
+
+ public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorId ncid, final NodeId nid) throws ConstructionException {
+ String nodeConnectorType = NodeMapping.toNodeConnectorType(ncid, nid);
+ Object aDNodeConnectorId = NodeMapping.toADNodeConnectorId(ncid, nid);
+ org.opendaylight.controller.sal.core.Node aDNode = NodeMapping.toADNode(nid);
+ return new org.opendaylight.controller.sal.core.NodeConnector(nodeConnectorType, aDNodeConnectorId, aDNode);
}
-
+
public static String toNodeConnectorType(final NodeConnectorId ncId, final NodeId nodeId) {
if (ncId.equals(toLocalNodeConnectorId(nodeId))) {
return NodeConnectorIDType.SWSTACK;
}
return nodeConnectorId.getValue();
}
-
+
public static NodeConnectorId toControllerNodeConnectorId(final NodeId node) {
return new NodeConnectorId(node.getValue() + ":" + 4294967293L);
}
-
+
public static NodeConnectorId toLocalNodeConnectorId(final NodeId node) {
return new NodeConnectorId(node.getValue() + ":" + 4294967294L);
}
-
+
public static NodeConnectorId toNormalNodeConnectorId(final NodeId node) {
return new NodeConnectorId(node.getValue() + ":" + 4294967290L);
}
-
+
public static NodeRef toNodeRef(final org.opendaylight.controller.sal.core.Node node) {
Preconditions.checkArgument(MD_SAL_TYPE.equals(node.getType()));
final String nodeId = Arguments.<String>checkInstanceOf(node.getID(), String.class);
final InstanceIdentifier<Node> nodePath = InstanceIdentifier.builder(Nodes.class).child(NODE_CLASS, nodeKey).toInstance();
return new NodeRef(nodePath);
}
-
+
public static NodeConnectorRef toNodeConnectorRef(final org.opendaylight.controller.sal.core.NodeConnector nodeConnector) {
final NodeRef node = NodeMapping.toNodeRef(nodeConnector.getNode());
nodeConnectorId = new NodeConnectorId(Arguments.<String>checkInstanceOf(nodeConnector.getID(), String.class));
}
final NodeConnectorKey connectorKey = new NodeConnectorKey(nodeConnectorId);
- final InstanceIdentifier<NodeConnector> path = InstanceIdentifier.builder(nodePath).child(NODECONNECTOR_CLASS, connectorKey).toInstance();
+ final InstanceIdentifier<NodeConnector> path = nodePath.child(NODECONNECTOR_CLASS, connectorKey);
return new NodeConnectorRef(path);
}
-
+
public static org.opendaylight.controller.sal.core.Node toADNode(final NodeRef node) throws ConstructionException {
return NodeMapping.toADNode(node.getValue());
}
-
+
public static HashSet<Property> toADNodeConnectorProperties(final NodeConnectorUpdated nc) {
final FlowCapableNodeConnectorUpdated fcncu = nc.<FlowCapableNodeConnectorUpdated>getAugmentation(FlowCapableNodeConnectorUpdated.class);
if (!Objects.equal(fcncu, null)) {
}
return new HashSet<Property>();
}
-
+
public static HashSet<Property> toADNodeConnectorProperties(final NodeConnector nc) {
final FlowCapableNodeConnector fcnc = nc.<FlowCapableNodeConnector>getAugmentation(FlowCapableNodeConnector.class);
if (!Objects.equal(fcnc, null)) {
}
return new HashSet<Property>();
}
-
+
public static HashSet<Property> toADNodeConnectorProperties(final FlowNodeConnector fcncu) {
final HashSet<org.opendaylight.controller.sal.core.Property> props = new HashSet<>();
}
return props;
}
-
+
public static Name toAdName(final String name) {
return new Name(name);
}
-
+
public static Config toAdConfig(final PortConfig pc) {
Config config = null;
if (pc.isPORTDOWN()) {
}
return config;
}
-
+
public static org.opendaylight.controller.sal.core.State toAdState(final State s) {
org.opendaylight.controller.sal.core.State state = null;
}
return state;
}
-
+
public static Bandwidth toAdBandwidth(final PortFeatures pf) {
Bandwidth bw = null;
if (pf.isTenMbHd() || pf.isTenMbFd()) {
}
return bw;
}
-
+
public static AdvertisedBandwidth toAdAdvertizedBandwidth(final PortFeatures pf) {
AdvertisedBandwidth abw = null;
final Bandwidth bw = toAdBandwidth(pf);
}
return abw;
}
-
+
public static SupportedBandwidth toAdSupportedBandwidth(final PortFeatures pf) {
SupportedBandwidth sbw = null;
final Bandwidth bw = toAdBandwidth(pf);
}
return sbw;
}
-
+
public static PeerBandwidth toAdPeerBandwidth(final PortFeatures pf) {
PeerBandwidth pbw = null;
final Bandwidth bw = toAdBandwidth(pf);
}
return pbw;
}
-
+
public static HashSet<Property> toADNodeProperties(final NodeUpdated nu) {
final FlowCapableNodeUpdated fcnu = nu.getAugmentation(FlowCapableNodeUpdated.class);
if (fcnu != null) {
}
return new HashSet<org.opendaylight.controller.sal.core.Property>();
}
-
+
public static HashSet<Property> toADNodeProperties(final FlowNode fcnu, final NodeId id) {
final HashSet<org.opendaylight.controller.sal.core.Property> props = new HashSet<>();
}
return props;
}
-
+
public static TimeStamp toADTimestamp() {
final Date date = new Date();
final TimeStamp timestamp = new TimeStamp(date.getTime(), "connectedSince");
return timestamp;
}
-
+
public static MacAddress toADMacAddress(final NodeId id) {
final String nodeId = id.getValue().replaceAll("openflow:", "");
long lNodeId = Long.parseLong(nodeId);
byte[] bytesFromDpid = ToSalConversionsUtils.bytesFromDpid(lNodeId);
return new MacAddress(bytesFromDpid);
}
-
+
public static Tables toADTables(final Short tables) {
return new Tables(tables.byteValue());
}
-
+
public static Capabilities toADCapabiliities(final List<Class<? extends FeatureCapability>> capabilities) {
int b = 0;
}
return new Capabilities(b);
}
-
+
public static Buffers toADBuffers(final Long buffers) {
return new Buffers(buffers.intValue());
}
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <version>${yangtools.version}</version>
<dependencies>
<dependency>
<groupId>org.opendaylight.controller</groupId>
*/
package org.opendaylight.controller.config.yang.md.sal.binding.impl;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import java.util.Hashtable;
import java.util.Map.Entry;
import java.util.Set;
+
import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
/**
*
*/
@Override
public java.lang.AutoCloseable createInstance() {
-
+
RuntimeGeneratedMappingServiceProxy potential = tryToReuseGlobalInstance();
if(potential != null) {
return potential;
}
- RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl();
- service.setPool(SingletonHolder.CLASS_POOL);
- service.init();
+
+ final RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl(SingletonHolder.CLASS_POOL);
bundleContext.registerService(SchemaServiceListener.class, service, new Hashtable<String,String>());
return service;
}
BindingIndependentMappingService, //
Delegator<BindingIndependentMappingService>, //
AutoCloseable {
-
+
private BindingIndependentMappingService delegate;
private ServiceReference<BindingIndependentMappingService> reference;
private BundleContext bundleContext;
this.delegate = Preconditions.checkNotNull(delegate);
}
+ @Override
public CodecRegistry getCodecRegistry() {
return delegate.getCodecRegistry();
}
+ @Override
public CompositeNode toDataDom(DataObject data) {
return delegate.toDataDom(data);
}
+ @Override
public Entry<InstanceIdentifier, CompositeNode> toDataDom(
Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> entry) {
return delegate.toDataDom(entry);
}
+ @Override
public InstanceIdentifier toDataDom(
org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path) {
return delegate.toDataDom(path);
}
+ @Override
public DataObject dataObjectFromDataDom(
org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path,
CompositeNode result) throws DeserializationException {
return delegate.dataObjectFromDataDom(path, result);
}
+ @Override
public org.opendaylight.yangtools.yang.binding.InstanceIdentifier<?> fromDataDom(InstanceIdentifier entry)
throws DeserializationException {
return delegate.fromDataDom(entry);
}
+ @Override
public Set<QName> getRpcQNamesFor(Class<? extends RpcService> service) {
return delegate.getRpcQNamesFor(service);
}
return delegate.getRpcServiceClassFor(namespace,revision);
}
+ @Override
public DataContainer dataObjectFromDataDom(Class<? extends DataContainer> inputClass, CompositeNode domInput) {
return delegate.dataObjectFromDataDom(inputClass, domInput);
}
-
+
@Override
public void close() throws Exception {
if(delegate != null) {
for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : normalized
.entrySet()) {
try {
- Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = getCodec().toBinding(entry);
- newMap.put(binding.getKey(), binding.getValue());
+ Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> potential = getCodec().toBinding(
+ entry);
+ if (potential.isPresent()) {
+ Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = potential.get();
+ newMap.put(binding.getKey(), binding.getValue());
+ }
} catch (DeserializationException e) {
- LOG.debug("Omitting {}", entry, e);
+ LOG.warn("Failed to transform {}, omitting it", entry, e);
}
}
return newMap;
Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath : normalized) {
try {
- InstanceIdentifier<? extends DataObject> binding = getCodec().toBinding(normalizedPath);
- hashSet.add(binding);
+ Optional<InstanceIdentifier<? extends DataObject>> potential = getCodec().toBinding(normalizedPath);
+ if (potential.isPresent()) {
+ InstanceIdentifier<? extends DataObject> binding = potential.get();
+ hashSet.add(binding);
+ }
} catch (DeserializationException e) {
- LOG.debug("Omitting {}", normalizedPath, e);
+ LOG.warn("Failed to transform {}, omitting it", normalizedPath, e);
}
}
return hashSet;
}
protected Optional<DataObject> toBindingData(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> data) {
- if(path.isWildcarded()) {
+ if (path.isWildcarded()) {
return Optional.absent();
}
@Override
public DataObject getOriginalSubtree() {
if (originalDataCache == null) {
- originalDataCache = toBindingData(path, domEvent.getOriginalSubtree());
+ if(domEvent.getOriginalSubtree() != null) {
+ originalDataCache = toBindingData(path, domEvent.getOriginalSubtree());
+ } else {
+ originalDataCache = Optional.absent();
+ }
}
return originalDataCache.orNull();
}
@Override
public DataObject getUpdatedSubtree() {
if (updatedDataCache == null) {
- updatedDataCache = toBindingData(path, domEvent.getUpdatedSubtree());
+ if(domEvent.getUpdatedSubtree() != null) {
+ updatedDataCache = toBindingData(path, domEvent.getUpdatedSubtree());
+ } else {
+ updatedDataCache = Optional.absent();
+ }
}
-
return updatedDataCache.orNull();
}
@Override
public String toString() {
return Objects.toStringHelper(TranslatedDataChangeEvent.class) //
- .add("created", getCreatedData()) //
- .add("updated", getUpdatedData()) //
- .add("removed", getRemovedPaths()) //
- .add("dom", domEvent) //
- .toString();
+ .add("created", getCreatedData()) //
+ .add("updated", getUpdatedData()) //
+ .add("removed", getRemovedPaths()) //
+ .add("dom", domEvent) //
+ .toString();
}
}
import javax.annotation.Nullable;
-import org.eclipse.xtext.xbase.lib.Exceptions;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@Nullable
@Override
public Optional<DataObject> apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
- try {
- final DataObject dataObject = normalizedNode.isPresent() ? codec.toBinding(path,
- normalizedNode.get()) : null;
+ if (normalizedNode.isPresent()) {
+ final DataObject dataObject;
+ try {
+ dataObject = codec.toBinding(path, normalizedNode.get());
+ } catch (DeserializationException e) {
+ LOG.warn("Failed to create dataobject from node {}", normalizedNode.get(), e);
+ throw new IllegalStateException("Failed to create dataobject", e);
+ }
+
if (dataObject != null) {
updateCache(store, path, dataObject);
+ return Optional.of(dataObject);
}
- return Optional.fromNullable(dataObject);
- } catch (DeserializationException e) {
- Exceptions.sneakyThrow(e);
}
- return null;
+ return Optional.absent();
}
});
}
final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
.toNormalizedNode(path, data);
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
- ensureParentsByMerge(writeTransaction, store, normalized.getKey(), path);
- LOG.debug("Tx: {} : Putting data {}",getDelegate().getIdentifier(),normalized.getKey());
- writeTransaction.put(store, normalized.getKey(), normalized.getValue());
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+ ensureParentsByMerge(writeTransaction, store, normalizedPath, path);
+ LOG.debug("Tx: {} : Putting data {}", getDelegate().getIdentifier(), normalizedPath);
+ writeTransaction.put(store, normalizedPath, normalized.getValue());
}
protected void doMergeWithEnsureParents(final DOMDataReadWriteTransaction writeTransaction,
final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalized = codec
.toNormalizedNode(path, data);
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
- ensureParentsByMerge(writeTransaction, store, normalized.getKey(), path);
- LOG.debug("Tx: {} : Merge data {}",getDelegate().getIdentifier(),normalized.getKey());
- writeTransaction.merge(store, normalized.getKey(), normalized.getValue());
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
+ ensureParentsByMerge(writeTransaction, store, normalizedPath, path);
+ LOG.debug("Tx: {} : Merge data {}",getDelegate().getIdentifier(),normalizedPath);
+ writeTransaction.merge(store, normalizedPath, normalized.getValue());
}
private void ensureParentsByMerge(final DOMDataReadWriteTransaction writeTransaction,
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalized(
final InstanceIdentifier<? extends DataObject> binding) {
- // Used instance-identifier codec do not support serialization of last path
+ // Used instance-identifier codec do not support serialization of last
+ // path
// argument if it is Augmentation (behaviour expected by old datastore)
// in this case, we explicitly check if last argument is augmentation
// to process it separately
}
- public InstanceIdentifier<? extends DataObject> toBinding(
+ /**
+ *
+ * Returns a Binding-Aware instance identifier from normalized
+ * instance-identifier if it is possible to create representation.
+ *
+ * Returns Optional.absent for cases where target is mixin node except
+ * augmentation.
+ *
+ */
+ public Optional<InstanceIdentifier<? extends DataObject>> toBinding(
final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
throws DeserializationException {
PathArgument lastArgument = Iterables.getLast(normalized.getPath());
- // Used instance-identifier codec do not support serialization of last path
- // argument if it is AugmentationIdentifier (behaviour expected by old datastore)
+ // Used instance-identifier codec do not support serialization of last
+ // path
+ // argument if it is AugmentationIdentifier (behaviour expected by old
+ // datastore)
// in this case, we explicitly check if last argument is augmentation
// to process it separately
if (lastArgument instanceof AugmentationIdentifier) {
return toBindingImpl(normalized);
}
- private InstanceIdentifier<? extends DataObject> toBindingAugmented(
- final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) throws DeserializationException {
- InstanceIdentifier<? extends DataObject> potential = toBindingImpl(normalized);
+ private Optional<InstanceIdentifier<? extends DataObject>> toBindingAugmented(
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+ throws DeserializationException {
+ Optional<InstanceIdentifier<? extends DataObject>> potential = toBindingImpl(normalized);
// Shorthand check, if codec already supports deserialization
// of AugmentationIdentifier we will return
- if(isAugmentationIdentifier(potential)) {
+ if (potential.isPresent() && isAugmentationIdentifier(potential.get())) {
return potential;
}
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.
+ // 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.
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());
+ ImmutableList.<PathArgument> builder().addAll(normalized.getPath()).add(new NodeIdentifier(child))
+ .build());
try {
-
- InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(toBindingImpl(childPath));
- return potentialPath;
+ if (!isChoiceOrCasePath(childPath)) {
+ InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(toBindingImpl(
+ childPath).get());
+ return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
+ }
} catch (Exception e) {
- LOG.trace("Unable to deserialize aug. child path for {}",childPath,e);
+ LOG.trace("Unable to deserialize aug. child path for {}", childPath, e);
}
}
return toBindingImpl(normalized);
}
- private InstanceIdentifier<? extends DataObject> toBindingImpl(
+ private Optional<InstanceIdentifier<? extends DataObject>> toBindingImpl(
final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
throws DeserializationException {
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath;
+
try {
+ if (isChoiceOrCasePath(normalized)) {
+ return Optional.absent();
+ }
legacyPath = legacyToNormalized.toLegacy(normalized);
} catch (DataNormalizationException e) {
throw new IllegalStateException("Could not denormalize path.", e);
}
LOG.trace("InstanceIdentifier Path Deserialization: Legacy representation {}, Normalized representation: {}",
legacyPath, normalized);
- return bindingToLegacy.fromDataDom(legacyPath);
+ return Optional.<InstanceIdentifier<? extends DataObject>> of(bindingToLegacy.fromDataDom(legacyPath));
+ }
+
+ private boolean isChoiceOrCasePath(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+ throws DataNormalizationException {
+ DataNormalizationOperation<?> op = findNormalizationOperation(normalized);
+ return op.isMixin() && op.getIdentifier() instanceof NodeIdentifier;
+ }
+
+ private DataNormalizationOperation<?> findNormalizationOperation(
+ final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+ throws DataNormalizationException {
+ DataNormalizationOperation<?> current = legacyToNormalized.getRootOperation();
+ for (PathArgument arg : normalized.getPath()) {
+ current = current.getChild(arg);
+ }
+ return current;
}
private static final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toEntry(
public DataObject toBinding(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> normalizedNode)
throws DeserializationException {
CompositeNode legacy = null;
- if(isAugmentationIdentifier(path) && normalizedNode instanceof AugmentationNode) {
+ if (isAugmentationIdentifier(path) && normalizedNode instanceof AugmentationNode) {
QName augIdentifier = BindingReflections.findQName(path.getTargetType());
ContainerNode virtualNode = Builders.containerBuilder() //
.withNodeIdentifier(new NodeIdentifier(augIdentifier)) //
return legacyToNormalized;
}
- public Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toBinding(
+ public Optional<Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>> toBinding(
final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
throws DeserializationException {
- InstanceIdentifier<? extends DataObject> bindingPath = toBinding(normalized.getKey());
- DataObject bindingData = toBinding(bindingPath, normalized.getValue());
- return toEntry(bindingPath, bindingData);
+ Optional<InstanceIdentifier<? extends DataObject>> potentialPath = toBinding(normalized.getKey());
+ if (potentialPath.isPresent()) {
+ InstanceIdentifier<? extends DataObject> bindingPath = potentialPath.get();
+ DataObject bindingData = toBinding(bindingPath, normalized.getValue());
+ if (bindingData == null) {
+ LOG.warn("Failed to deserialize {} to Binding format. Binding path is: {}", normalized, bindingPath);
+ }
+ return Optional.of(toEntry(bindingPath, bindingData));
+ } else {
+ return Optional.absent();
+ }
}
@Override
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed = toNormalizedImpl(augPath);
// If used instance identifier codec added supports for deserialization
// of last AugmentationIdentifier we will just reuse it
- if(isAugmentationIdentifier(processed)) {
+ if (isAugmentationIdentifier(processed)) {
return processed;
}
- // Here we employ small trick - DataNormalizer injecst augmentation identifier if child is
- // also part of the path (since using a child we can safely identify augmentation)
+ // Here we employ small trick - DataNormalizer injecst augmentation
+ // identifier if child is
+ // also part of the path (since using a child we can safely identify
+ // augmentation)
// so, we scan augmentation for children add it to path
// and use original algorithm, then shorten it to last augmentation
- for (@SuppressWarnings("rawtypes") Class augChild : getAugmentationChildren(augPath.getTargetType())) {
+ for (@SuppressWarnings("rawtypes")
+ Class augChild : getAugmentationChildren(augPath.getTargetType())) {
@SuppressWarnings("unchecked")
InstanceIdentifier<?> childPath = augPath.child(augChild);
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = toNormalizedImpl(childPath);
return processed;
}
-
-
private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier shortenToLastAugmentation(
final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) {
int position = 0;
final InstanceIdentifier<? extends DataObject> binding) {
int position = 0;
int foundPosition = -1;
- for(org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : binding.getPathArguments()) {
+ for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : binding.getPathArguments()) {
position++;
if (isAugmentation(arg.getType())) {
foundPosition = position;
return InstanceIdentifier.create(Iterables.limit(binding.getPathArguments(), foundPosition));
}
-
-
private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalizedImpl(
final InstanceIdentifier<? extends DataObject> binding) {
final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath = bindingToLegacy
return InstanceIdentifier.create(wildArgs);
}
-
private static boolean isAugmentation(final Class<? extends DataObject> type) {
return Augmentation.class.isAssignableFrom(type);
}
- private static boolean isAugmentationIdentifier(final InstanceIdentifier<?> path) {
- return Augmentation.class.isAssignableFrom(path.getTargetType());
+ private static boolean isAugmentationIdentifier(final InstanceIdentifier<?> potential) {
+ return Augmentation.class.isAssignableFrom(potential.getTargetType());
}
private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed) {
*/
package org.opendaylight.controller.sal.binding.codegen;
-import com.google.common.base.Objects;
import java.lang.reflect.Field;
import java.util.Map;
-import org.eclipse.xtext.xbase.lib.Exceptions;
-import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification;
+
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
-@SuppressWarnings("all")
-public class RuntimeCodeHelper {
- /**
- * Helper method to return delegate from ManagedDirectedProxy with use of reflection.
- *
- * Note: This method uses reflection, but access to delegate field should be
- * avoided and called only if neccessary.
- */
- public static <T extends RpcService> T getDelegate(final RpcService proxy) {
- try {
- Class<? extends RpcService> _class = proxy.getClass();
- final Field field = _class.getField(RuntimeCodeSpecification.DELEGATE_FIELD);
- boolean _equals = Objects.equal(field, null);
- if (_equals) {
- UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Unable to get delegate from proxy");
- throw _unsupportedOperationException;
- }
- try {
- Object _get = field.get(proxy);
- return ((T) _get);
- } catch (Throwable _e) {
- throw Exceptions.sneakyThrow(_e);
- }
- } catch (Throwable _e_1) {
- throw Exceptions.sneakyThrow(_e_1);
+public final class RuntimeCodeHelper {
+ private RuntimeCodeHelper() {
+ throw new UnsupportedOperationException("Utility class should never be instantiated");
+ }
+
+ private static Field getField(final Class<?> cls, final String name) {
+ try {
+ return cls.getField(name);
+ } catch (NoSuchFieldException e) {
+ throw new IllegalArgumentException(
+ String.format("Class %s is missing field %s", cls, name), e);
+ } catch (SecurityException e) {
+ throw new IllegalStateException(String.format("Failed to examine class %s", cls), e);
+ }
}
- }
- /**
- * Helper method to set delegate to ManagedDirectedProxy with use of reflection.
- *
- * Note: This method uses reflection, but setting delegate field should not occur too much
- * to introduce any significant performance hits.
- */
- public static void setDelegate(final RpcService proxy, final RpcService delegate) {
- try {
- Class<? extends RpcService> _class = proxy.getClass();
- final Field field = _class.getField(RuntimeCodeSpecification.DELEGATE_FIELD);
- boolean _equals = Objects.equal(field, null);
- if (_equals) {
- UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Unable to set delegate to proxy");
- throw _unsupportedOperationException;
- }
- boolean _or = false;
- boolean _equals_1 = Objects.equal(delegate, null);
- if (_equals_1) {
- _or = true;
- } else {
- Class<? extends Object> _type = field.getType();
- Class<? extends RpcService> _class_1 = delegate.getClass();
- boolean _isAssignableFrom = _type.isAssignableFrom(_class_1);
- _or = (_equals_1 || _isAssignableFrom);
- }
- if (_or) {
- field.set(proxy, delegate);
- } else {
- IllegalArgumentException _illegalArgumentException = new IllegalArgumentException("delegate class is not assignable to proxy");
- throw _illegalArgumentException;
- }
- } catch (Throwable _e) {
- throw Exceptions.sneakyThrow(_e);
+ private static Field getDelegateField(final Class<?> cls) {
+ return getField(cls, RuntimeCodeSpecification.DELEGATE_FIELD);
}
- }
- /**
- * Helper method to set delegate to ManagedDirectedProxy with use of reflection.
- *
- * Note: This method uses reflection, but setting delegate field should not occur too much
- * to introduce any significant performance hits.
- */
- public static void setDelegate(final Object proxy, final Object delegate) {
- try {
- Class<? extends Object> _class = proxy.getClass();
- final Field field = _class.getField(RuntimeCodeSpecification.DELEGATE_FIELD);
- boolean _equals = Objects.equal(field, null);
- if (_equals) {
- UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Unable to set delegate to proxy");
- throw _unsupportedOperationException;
- }
- boolean _or = false;
- boolean _equals_1 = Objects.equal(delegate, null);
- if (_equals_1) {
- _or = true;
- } else {
- Class<? extends Object> _type = field.getType();
- Class<? extends Object> _class_1 = delegate.getClass();
- boolean _isAssignableFrom = _type.isAssignableFrom(_class_1);
- _or = (_equals_1 || _isAssignableFrom);
- }
- if (_or) {
- field.set(proxy, delegate);
- } else {
- IllegalArgumentException _illegalArgumentException = new IllegalArgumentException("delegate class is not assignable to proxy");
- throw _illegalArgumentException;
- }
- } catch (Throwable _e) {
- throw Exceptions.sneakyThrow(_e);
+ private static Object getFieldValue(final Field field, final Object obj) {
+ try {
+ return field.get(obj);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(String.format("Failed to get field %s of object %s", field, obj), e);
+ }
+ }
+
+ private static void setFieldValue(final Field field, final Object obj, final Object value) {
+ try {
+ field.set(obj, value);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(String.format("Failed to set field %s to %s", field, value), e);
+ }
+ }
+
+ /**
+ * Helper method to return delegate from ManagedDirectedProxy with use of reflection.
+ *
+ * Note: This method uses reflection, but access to delegate field should be
+ * avoided and called only if necessary.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends RpcService> T getDelegate(final RpcService proxy) {
+ return (T)getFieldValue(getDelegateField(proxy.getClass()), proxy);
+ }
+
+ /**
+ * Helper method to set delegate to ManagedDirectedProxy with use of reflection.
+ *
+ * Note: This method uses reflection, but setting delegate field should not occur too much
+ * to introduce any significant performance hits.
+ */
+ public static void setDelegate(final Object proxy, final Object delegate) {
+ final Field field = getDelegateField(proxy.getClass());
+
+ if (delegate != null) {
+ final Class<?> ft = field.getType();
+ if (!ft.isAssignableFrom(delegate.getClass())) {
+ throw new IllegalArgumentException(
+ String.format("Field %s type %s is not compatible with delegate type %s",
+ field, ft, delegate.getClass()));
+ }
+ }
+
+ setFieldValue(field, proxy, delegate);
}
- }
- public static Map<InstanceIdentifier<? extends Object>,? extends RpcService> getRoutingTable(final RpcService target, final Class<? extends BaseIdentity> tableClass) {
- try {
- Class<? extends RpcService> _class = target.getClass();
- String _routingTableField = RuntimeCodeSpecification.getRoutingTableField(tableClass);
- final Field field = _class.getField(_routingTableField);
- boolean _equals = Objects.equal(field, null);
- if (_equals) {
- UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException(
- "Unable to get routing table. Table field does not exists");
- throw _unsupportedOperationException;
- }
- try {
- Object _get = field.get(target);
- return ((Map<InstanceIdentifier<? extends Object>,? extends RpcService>) _get);
- } catch (Throwable _e) {
- throw Exceptions.sneakyThrow(_e);
- }
- } catch (Throwable _e_1) {
- throw Exceptions.sneakyThrow(_e_1);
+ @SuppressWarnings("unchecked")
+ public static Map<InstanceIdentifier<? extends Object>,? extends RpcService> getRoutingTable(final RpcService target, final Class<? extends BaseIdentity> tableClass) {
+ final Field field = getField(target.getClass(), RuntimeCodeSpecification.getRoutingTableField(tableClass));
+ return (Map<InstanceIdentifier<? extends Object>,? extends RpcService>) getFieldValue(field, target);
}
- }
- public static void setRoutingTable(final RpcService target, final Class<? extends BaseIdentity> tableClass, final Map<InstanceIdentifier<? extends Object>,? extends RpcService> routingTable) {
- try {
- Class<? extends RpcService> _class = target.getClass();
- String _routingTableField = RuntimeCodeSpecification.getRoutingTableField(tableClass);
- final Field field = _class.getField(_routingTableField);
- boolean _equals = Objects.equal(field, null);
- if (_equals) {
- UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException(
- "Unable to set routing table. Table field does not exists");
- throw _unsupportedOperationException;
- }
- field.set(target, routingTable);
- } catch (Throwable _e) {
- throw Exceptions.sneakyThrow(_e);
+ public static void setRoutingTable(final RpcService target, final Class<? extends BaseIdentity> tableClass, final Map<InstanceIdentifier<? extends Object>,? extends RpcService> routingTable) {
+ final Field field = getField(target.getClass(), RuntimeCodeSpecification.getRoutingTableField(tableClass));
+ setFieldValue(field, target, routingTable);
}
- }
-}
\ No newline at end of file
+}
class RuntimeCodeGenerator implements org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator, NotificationInvokerFactory {
val CtClass BROKER_NOTIFICATION_LISTENER;
- val ClassPool classPool;
val extension JavassistUtils utils;
val Map<Class<? extends NotificationListener>, RuntimeGeneratedInvokerPrototype> invokerClasses;
new(ClassPool pool) {
- classPool = pool;
utils = new JavassistUtils(pool);
invokerClasses = new WeakHashMap();
BROKER_NOTIFICATION_LISTENER = org.opendaylight.controller.sal.binding.api.NotificationListener.asCtClass;
*/
package org.opendaylight.controller.sal.binding.codegen.impl;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+
import javassist.ClassPool;
+
import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator;
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
public class SingletonHolder {
private static final Logger logger = LoggerFactory.getLogger(SingletonHolder.class);
// occurs in RejectedExecutionHandler.
// This impl saturates threadpool first, then queue. When both are full caller will get blocked.
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(queueSize) {
+ private static final long serialVersionUID = 1L;
+
@Override
public boolean offer(Runnable r) {
// ThreadPoolExecutor will spawn a new thread after core size is reached only if the queue.offer returns false.
Provider, //
AutoCloseable {
-
-
private final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
-
private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
.builder().toInstance();
private DataModificationTransaction createBindingToDomTransaction(
final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
DataModificationTransaction target = biDataService.beginTransaction();
- LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(),source.getIdentifier());
+ LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(), source.getIdentifier());
for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
target.removeConfigurationData(biEntry);
- LOG.debug("Delete of Binding Configuration Data {} is translated to {}",entry,biEntry);
+ LOG.debug("Delete of Binding Configuration Data {} is translated to {}", entry, biEntry);
}
for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
target.removeOperationalData(biEntry);
- LOG.debug("Delete of Binding Operational Data {} is translated to {}",entry,biEntry);
+ LOG.debug("Delete of Binding Operational Data {} is translated to {}", entry, biEntry);
}
for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
.entrySet()) {
Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
.toDataDom(entry);
target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
- LOG.debug("Update of Binding Configuration Data {} is translated to {}",entry,biEntry);
+ LOG.debug("Update of Binding Configuration Data {} is translated to {}", entry, biEntry);
}
for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
.entrySet()) {
Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
.toDataDom(entry);
target.putOperationalData(biEntry.getKey(), biEntry.getValue());
- LOG.debug("Update of Binding Operational Data {} is translated to {}",entry,biEntry);
+ LOG.debug("Update of Binding Operational Data {} is translated to {}", entry, biEntry);
}
return target;
return biDataService;
}
- protected void setDomDataService(final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
+ protected void setDomDataService(
+ final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
this.biDataService = biDataService;
}
}
public void startDataForwarding() {
- if(baDataService instanceof AbstractForwardedDataBroker) {
+ if (baDataService instanceof AbstractForwardedDataBroker) {
dataForwarding = true;
return;
}
final DataProviderService baData;
if (baDataService instanceof BindingMountPointImpl) {
- baData = ((BindingMountPointImpl)baDataService).getDataBrokerImpl();
+ baData = ((BindingMountPointImpl) baDataService).getDataBrokerImpl();
LOG.debug("Extracted BA Data provider {} from mount point {}", baData, baDataService);
} else {
baData = baDataService;
}
DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
- LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
- domTransaction.getIdentifier());
+ LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .",
+ bindingTransaction.getIdentifier(), domTransaction.getIdentifier());
return wrapped;
}
}
DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
@Override
- public void onRegister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+ public void onRegister(
+ final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
.getPath());
}
@Override
- public void onUnregister(final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+ public void onUnregister(
+ final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
// NOOP for now
// FIXME: do registration based on only active commit handlers.
}
*
*/
private class DomToBindingRpcForwardingManager implements
- RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>,
- RouterInstantiationListener,
+ RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>, RouterInstantiationListener,
GlobalRpcRegistrationListener {
private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
}
} catch (Exception e) {
- LOG.error("Could not forward Rpcs of type {}", service.getName(),e);
+ LOG.error("Could not forward Rpcs of type {}", service.getName(), e);
}
registrations = ImmutableSet.of();
}
* @param service
* @param context
*/
- public DomToBindingRpcForwarder(final Class<? extends RpcService> service, final Class<? extends BaseIdentity> context) {
+ public DomToBindingRpcForwarder(final Class<? extends RpcService> service,
+ final Class<? extends BaseIdentity> context) {
this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
this.supportedRpcs = mappingService.getRpcQNamesFor(service);
Builder<RoutedRpcRegistration> registrationsBuilder = ImmutableSet
registrations = registrationsBuilder.build();
}
- public void registerPaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
- final Set<InstanceIdentifier<?>> set) {
+ public void registerPaths(final Class<? extends BaseIdentity> context,
+ final Class<? extends RpcService> service, final Set<InstanceIdentifier<?>> set) {
QName ctx = BindingReflections.findQName(context);
for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
toDOMInstanceIdentifier)) {
}
}
-
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
if (EQUALS_METHOD.equals(method)) {
}
}
-
@Override
public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode domInput) {
checkArgument(rpc != null);
strategy = new DefaultInvocationStrategy(rpc, targetMethod, outputClass.get(), inputClass
.get());
} else {
- strategy = new NoInputNoOutputInvocationStrategy(rpc, targetMethod);
+ strategy = new NoInputInvocationStrategy(rpc, targetMethod, outputClass.get());
}
- } else if(inputClass.isPresent()){
- strategy = new NoOutputInvocationStrategy(rpc,targetMethod, inputClass.get());
+ } else if (inputClass.isPresent()) {
+ strategy = new NoOutputInvocationStrategy(rpc, targetMethod, inputClass.get());
} else {
- strategy = new NoInputNoOutputInvocationStrategy(rpc,targetMethod);
+ strategy = new NoInputNoOutputInvocationStrategy(rpc, targetMethod);
}
return strategy;
}
public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
throws Exception;
- public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+ public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput)
+ throws Exception {
return uncheckedInvoke(rpcService, domInput);
}
}
@SuppressWarnings("unchecked")
@Override
- public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+ 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) {
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());
+ 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) {
+ 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(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());
- }
- });
+ 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));
+ }
}
}
}
@Override
- public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+ 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();
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);
+ super(rpc, targetMethod);
this.inputClass = new WeakReference(inputClass);
}
-
@Override
- public RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
+ 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) {
@Override
public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
- if(biRpcRegistry == null) {
+ if (biRpcRegistry == null) {
return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
}
CompositeNode xml = mappingService.toDataDom(input);
- CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.<Node<?>>of(xml));
+ 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(RpcResult<CompositeNode> input) {
- return Rpcs.<Void>getRpcResult(input.isSuccessful(), null, input.getErrors());
- }
- });
+ 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());
+ }
+ });
}
}
private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
.toInstance();
- private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier
- .builder(NODES_INSTANCE_ID_BA) //
- .child(Node.class, NODE_KEY).toInstance();
+ private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA =
+ NODES_INSTANCE_ID_BA.child(Node.class, NODE_KEY);
private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
/**
* Test for Bug 148
- *
+ *
* @throws Exception
*/
@Test
// Node meterStatsNodeWithDuration = createTestNode(NodeMeterStatistics.class, nodeMeterStatistics(5, true));
// commitNodeAndVerifyTransaction(meterStatsNodeWithDuration);
//
-//
+//
// Node nodeWithUpdatedList = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
// AugmentationVerifier.from(nodeWithUpdatedList) //
// .assertHasAugmentation(FlowCapableNode.class) //
// .assertHasAugmentation(NodeMeterStatistics.class);
-//
+//
// List<MeterStats> meterStats = nodeWithUpdatedList.getAugmentation(NodeMeterStatistics.class).getMeterStatistics().getMeterStats();
// assertNotNull(meterStats);
// assertFalse(meterStats.isEmpty());
public void startBindingToDomMappingService() {
checkState(classPool != null, "ClassPool needs to be present");
- mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
- mappingServiceImpl.setPool(classPool);
- mappingServiceImpl.init();
+ mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
}
public void updateYangSchema(final String[] files) {
private static final NodeKey NODE_FOO_KEY = new NodeKey(new NodeId("foo"));
private static final NodeKey NODE_BAR_KEY = new NodeKey(new NodeId("foo"));
private static InstanceIdentifier<Nodes> NODES_PATH = InstanceIdentifier.builder(Nodes.class).build();
- private static InstanceIdentifier<Node> NODE_FOO_PATH = InstanceIdentifier.builder(NODES_PATH)
- .child(Node.class, NODE_FOO_KEY).build();
- private static InstanceIdentifier<Node> NODE_BAR_PATH = InstanceIdentifier.builder(NODES_PATH)
- .child(Node.class, NODE_FOO_KEY).build();
+ private static InstanceIdentifier<Node> NODE_FOO_PATH = NODES_PATH.child(Node.class, NODE_FOO_KEY);
+ private static InstanceIdentifier<Node> NODE_BAR_PATH = NODES_PATH.child(Node.class, NODE_FOO_KEY);
@Test
public void testConcurrentCreate() throws InterruptedException, ExecutionException {
private static final UnorderedListKey UNORDERED_FOO_KEY = new UnorderedListKey("foo");
private static final UnorderedListKey UNORDERED_BAR_KEY = new UnorderedListKey("bar");
- private static final InstanceIdentifier<UnorderedList> UNORDERED_FOO_PATH = InstanceIdentifier.builder(UNORDERED_CONTAINER_PATH).child(UnorderedList.class,UNORDERED_FOO_KEY).build();
- private static final InstanceIdentifier<UnorderedList> UNORDERED_BAR_PATH = InstanceIdentifier.builder(UNORDERED_CONTAINER_PATH).child(UnorderedList.class,UNORDERED_BAR_KEY).build();
+ private static final InstanceIdentifier<UnorderedList> UNORDERED_FOO_PATH = UNORDERED_CONTAINER_PATH.child(UnorderedList.class,UNORDERED_FOO_KEY);
+ private static final InstanceIdentifier<UnorderedList> UNORDERED_BAR_PATH = UNORDERED_CONTAINER_PATH.child(UnorderedList.class,UNORDERED_BAR_KEY);
private static final OrderedListKey ORDERED_FOO_KEY = new OrderedListKey("foo");
private static final OrderedListKey ORDERED_BAR_KEY = new OrderedListKey("bar");
- private static final InstanceIdentifier<OrderedList> ORDERED_FOO_PATH = InstanceIdentifier.builder(ORDERED_CONTAINER_PATH).child(OrderedList.class,ORDERED_FOO_KEY).build();
- private static final InstanceIdentifier<OrderedList> ORDERED_BAR_PATH = InstanceIdentifier.builder(ORDERED_CONTAINER_PATH).child(OrderedList.class,ORDERED_BAR_KEY).build();
+ private static final InstanceIdentifier<OrderedList> ORDERED_FOO_PATH = ORDERED_CONTAINER_PATH.child(OrderedList.class,ORDERED_FOO_KEY);
+ private static final InstanceIdentifier<OrderedList> ORDERED_BAR_PATH = ORDERED_CONTAINER_PATH.child(OrderedList.class,ORDERED_BAR_KEY);
@Test
private static final FlowKey FLOW_KEY = new FlowKey(new FlowId("test"));
- private static final InstanceIdentifier<Flow> NODE_0_FLOW_PATH = InstanceIdentifier.builder(NODE_0_TABLE_PATH)
- .child(Flow.class, FLOW_KEY).build();
+ private static final InstanceIdentifier<Flow> NODE_0_FLOW_PATH = NODE_0_TABLE_PATH.child(Flow.class, FLOW_KEY);
- private static final InstanceIdentifier<Flow> NODE_1_FLOW_PATH = InstanceIdentifier.builder(NODE_1_TABLE_PATH)
- .child(Flow.class, FLOW_KEY).build();
+ private static final InstanceIdentifier<Flow> NODE_1_FLOW_PATH = NODE_1_TABLE_PATH.child(Flow.class, FLOW_KEY);
- private static final InstanceIdentifier<TableFeatures> NODE_0_TABLE_FEATURES_PATH = InstanceIdentifier
- .builder(NODE_0_TABLE_PATH).child(TableFeatures.class, TABLE_FEATURES_KEY).build();
+ private static final InstanceIdentifier<TableFeatures> NODE_0_TABLE_FEATURES_PATH =
+ NODE_0_TABLE_PATH.child(TableFeatures.class, TABLE_FEATURES_KEY);
private static final TableFeatures TABLE_FEATURES = new TableFeaturesBuilder()//
.setKey(TABLE_FEATURES_KEY) //
.toInstance();
- private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier//
- .builder(NODES_INSTANCE_ID_BA) //
- .child(Node.class, NODE_KEY).toInstance();
+ private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = NODES_INSTANCE_ID_BA.child(Node.class, NODE_KEY);
- private static final InstanceIdentifier<SupportedActions> SUPPORTED_ACTIONS_INSTANCE_ID_BA = InstanceIdentifier//
- .builder(NODES_INSTANCE_ID_BA) //
+ private static final InstanceIdentifier<SupportedActions> SUPPORTED_ACTIONS_INSTANCE_ID_BA = //
+ NODES_INSTANCE_ID_BA.builder() //
.child(Node.class, NODE_KEY) //
.augmentation(FlowCapableNode.class) //
.child(SupportedActions.class)
NodeConnectorId ncId = new NodeConnectorId("openflow:1:bar");
NodeConnectorKey nodeKey = new NodeConnectorKey(ncId );
- InstanceIdentifier<NodeConnector> ncInstanceId = InstanceIdentifier.builder(NODE_INSTANCE_ID_BA).child(NodeConnector.class, nodeKey).toInstance();
+ InstanceIdentifier<NodeConnector> ncInstanceId = NODE_INSTANCE_ID_BA.child(NodeConnector.class, nodeKey);
NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder();
ncBuilder.setId(ncId);
ncBuilder.setKey(nodeKey);
*/
package org.opendaylight.controller.sal.binding.test.bugfix;
-import com.google.common.collect.ImmutableSet;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+import com.google.common.collect.ImmutableSet;
public class FlagsSerializationTest extends AbstractDataServiceTest {
private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
private static final FlowKey FLOW_KEY = new FlowKey(new FlowId(FLOW_ID));
private static final TableKey TABLE_KEY = new TableKey(TABLE_ID);
-
+
private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
NODE_ID);
// private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier FLOW_INSTANCE_ID_BI = //
// org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
-//
+//
// .node(Flows.QNAME) //
// .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
// .toInstance();
private static final InstanceIdentifier<? extends DataObject> FLOW_INSTANCE_ID_BA = //
- InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) //
+ NODE_INSTANCE_ID_BA.builder() //
.augmentation(FlowCapableNode.class)
.child(Table.class,TABLE_KEY)
.child(Flow.class, FLOW_KEY) //
FlowModFlags checkOverlapFlags = new FlowModFlags(true,false,false,false,false);
ImmutableSet<String> domCheckOverlapFlags = ImmutableSet.<String>of("CHECK_OVERLAP");
testFlags(checkOverlapFlags,domCheckOverlapFlags);
-
-
-
+
+
+
FlowModFlags allFalseFlags = new FlowModFlags(false,false,false,false,false);
ImmutableSet<String> domAllFalseFlags = ImmutableSet.<String>of();
testFlags(allFalseFlags,domAllFalseFlags);
-
+
FlowModFlags allTrueFlags = new FlowModFlags(true,true,true,true,true);
ImmutableSet<String> domAllTrueFlags = ImmutableSet.<String>of("CHECK_OVERLAP","NO_BYT_COUNTS", "NO_PKT_COUNTS", "RESET_COUNTS", "SEND_FLOW_REM");
testFlags(allTrueFlags,domAllTrueFlags);
-
+
FlowModFlags nullFlags = null;
ImmutableSet<String> domNullFlags = null;
testFlags(null,null);
-
-
+
+
}
private void testFlags(FlowModFlags flagsToTest, ImmutableSet<String> domFlags) throws Exception {
Flow flow = createFlow(flagsToTest);
assertNotNull(flow);
-
+
CompositeNode domFlow = biDataService.readConfigurationData(mappingService.toDataDom(FLOW_INSTANCE_ID_BA));
-
+
assertNotNull(domFlow);
org.opendaylight.yangtools.yang.data.api.Node<?> readedFlags = domFlow.getFirstSimpleByName(FLOW_FLAGS_QNAME);
-
+
if(domFlags != null) {
assertNotNull(readedFlags);
assertEquals(domFlags,readedFlags.getValue());
assertNull(readedFlags);
}
assertEquals(flagsToTest, flow.getFlags());
-
+
DataModificationTransaction transaction = baDataService.beginTransaction();
transaction.removeConfigurationData(FLOW_INSTANCE_ID_BA);
RpcResult<TransactionStatus> result = transaction.commit().get();
assertEquals(TransactionStatus.COMMITED, result.getResult());
-
+
}
private Flow createFlow(FlowModFlags flagsToTest) throws Exception {
flow.setKey(FLOW_KEY);
flow.setMatch(match.build());
-
+
flow.setFlags(flagsToTest);
-
+
InstructionsBuilder instructions = new InstructionsBuilder();
InstructionBuilder instruction = new InstructionBuilder();
-
+
instruction.setOrder(10);
ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
List<Action> actionList = new ArrayList<>();
private static final InstanceIdentifier<Nodes> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
.toInstance();
- private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier//
- .builder(NODES_INSTANCE_ID_BA) //
+ private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = //
+ NODES_INSTANCE_ID_BA.builder() //
.child(Node.class, NODE_KEY).toInstance();
- private static final InstanceIdentifier<SupportedActions> SUPPORTED_ACTIONS_INSTANCE_ID_BA = InstanceIdentifier//
- .builder(NODES_INSTANCE_ID_BA) //
+ private static final InstanceIdentifier<SupportedActions> SUPPORTED_ACTIONS_INSTANCE_ID_BA = //
+ NODES_INSTANCE_ID_BA.builder() //
.child(Node.class, NODE_KEY) //
.augmentation(FlowCapableNode.class) //
.child(SupportedActions.class).toInstance();
- private static final InstanceIdentifier<FlowCapableNode> ALL_FLOW_CAPABLE_NODES = InstanceIdentifier //
- .builder(NODES_INSTANCE_ID_BA) //
+ private static final InstanceIdentifier<FlowCapableNode> ALL_FLOW_CAPABLE_NODES = //
+ NODES_INSTANCE_ID_BA.builder() //
.child(Node.class) //
.augmentation(FlowCapableNode.class) //
.build();
.nodeWithKey(Node.QNAME, NODE_KEY_BI) //
.node(SUPPORTED_ACTIONS_QNAME) //
.toInstance();
- private static final InstanceIdentifier<FlowCapableNode> FLOW_AUGMENTATION_PATH = InstanceIdentifier //
- .builder(NODE_INSTANCE_ID_BA) //
+ private static final InstanceIdentifier<FlowCapableNode> FLOW_AUGMENTATION_PATH =
+ NODE_INSTANCE_ID_BA.builder() //
.augmentation(FlowCapableNode.class) //
.build();
fnub.setDescription("Description Foo");
fnub.setSoftware("JUnit emulated");
FlowCapableNode fnu = fnub.build();
- InstanceIdentifier<FlowCapableNode> augmentIdentifier = InstanceIdentifier.builder(NODE_INSTANCE_ID_BA)
- .augmentation(FlowCapableNode.class).toInstance();
+ InstanceIdentifier<FlowCapableNode> augmentIdentifier = NODE_INSTANCE_ID_BA
+ .augmentation(FlowCapableNode.class);
DataModificationTransaction augmentedTransaction = baDataService.beginTransaction();
augmentedTransaction.putOperationalData(augmentIdentifier, fnu);
lastReceivedChangeEvent = SettableFuture.create();
assertEquals(TransactionStatus.COMMITED, result.getResult());
- FlowCapableNode readedAugmentation = (FlowCapableNode) baDataService.readOperationalData(InstanceIdentifier
- .builder(NODE_INSTANCE_ID_BA).augmentation(FlowCapableNode.class).toInstance());
+ FlowCapableNode readedAugmentation = (FlowCapableNode) baDataService.readOperationalData(
+ NODE_INSTANCE_ID_BA.augmentation(FlowCapableNode.class));
assertNotNull(readedAugmentation);
assertEquals(fnu.getHardware(), readedAugmentation.getHardware());
private void testPutNodeConnectorWithAugmentation() throws Exception {
NodeConnectorKey ncKey = new NodeConnectorKey(new NodeConnectorId("test:0:0"));
- InstanceIdentifier<NodeConnector> ncPath = InstanceIdentifier.builder(NODE_INSTANCE_ID_BA)
- .child(NodeConnector.class, ncKey).toInstance();
- InstanceIdentifier<FlowCapableNodeConnector> ncAugmentPath = InstanceIdentifier.builder(ncPath)
- .augmentation(FlowCapableNodeConnector.class).toInstance();
+ InstanceIdentifier<NodeConnector> ncPath = NODE_INSTANCE_ID_BA
+ .child(NodeConnector.class, ncKey);
+ InstanceIdentifier<FlowCapableNodeConnector> ncAugmentPath = ncPath
+ .augmentation(FlowCapableNodeConnector.class);
NodeConnectorBuilder nc = new NodeConnectorBuilder();
nc.setKey(ncKey);
.child(Node.class, NODE_KEY).toInstance();
private static final InstanceIdentifier<Table> TABLE_INSTANCE_ID_BA = //
- InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) //
+ NODE_INSTANCE_ID_BA.builder() //
.augmentation(FlowCapableNode.class).child(Table.class, TABLE_KEY).build();
private static final InstanceIdentifier<? extends DataObject> FLOW_INSTANCE_ID_BA = //
- InstanceIdentifier.builder(TABLE_INSTANCE_ID_BA) //
- .child(Flow.class, FLOW_KEY) //
- .toInstance();
+ TABLE_INSTANCE_ID_BA.child(Flow.class, FLOW_KEY);
/**
*
* The scenario tests writing parent node, which also contains child items
DataObject readedTable = baDataService.readConfigurationData(TABLE_INSTANCE_ID_BA);
assertNotNull("Readed table should not be nul.", readedTable);
assertTrue(readedTable instanceof Table);
-
+
DataObject readedFlow = baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA);
assertNotNull("Readed flow should not be null.",readedFlow);
assertTrue(readedFlow instanceof Flow);
assertEquals(flow, readedFlow);
}
-}
\ No newline at end of file
+}
private static final TableKey TABLE_KEY_BA = new TableKey((short) 0);
private static final InstanceIdentifier<Flow> FLOWS_PATH_BA = //
- InstanceIdentifier.builder(NODE_INSTANCE_ID_BA) //
+ NODE_INSTANCE_ID_BA.builder() //
.augmentation(FlowCapableNode.class) //
.child(Table.class, TABLE_KEY_BA) //
.child(Flow.class) //
.toInstance();
private static final InstanceIdentifier<Flow> FLOW_INSTANCE_ID_BA = //
- InstanceIdentifier.builder(FLOWS_PATH_BA.firstIdentifierOf(Table.class)) //
- .child(Flow.class, FLOW_KEY) //
- .toInstance();
+ FLOWS_PATH_BA.firstIdentifierOf(Table.class).child(Flow.class, FLOW_KEY);
@Test
public void simpleModifyOperation() throws Exception {
.child(Node.class, NODE_KEY).toInstance();
private static GroupKey GROUP_KEY = new GroupKey(new GroupId(0L));
- private static final InstanceIdentifier<GroupStatistics> GROUP_STATISTICS_ID_BA = InstanceIdentifier
- .builder(NODE_INSTANCE_ID_BA).augmentation(FlowCapableNode.class) //
+ private static final InstanceIdentifier<GroupStatistics> GROUP_STATISTICS_ID_BA = NODE_INSTANCE_ID_BA
+ .builder().augmentation(FlowCapableNode.class) //
.child(Group.class, GROUP_KEY) //
.augmentation(NodeGroupStatistics.class) //
.child(GroupStatistics.class) //
void registerPath(C context, P path);
void unregisterPath(C context, P path);
+ @Override
+ void close();
}
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import org.eclipse.xtext.xbase.lib.Exceptions;
import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
}
protected ImmutableList<DataCommitHandler<P, D>> affectedCommitHandlers(final Set<P> paths) {
- final Callable<ImmutableList<DataCommitHandler<P, D>>> _function = new Callable<ImmutableList<DataCommitHandler<P, D>>>() {
+ final Supplier<ImmutableList<DataCommitHandler<P, D>>> _function = new Supplier<ImmutableList<DataCommitHandler<P, D>>>() {
@Override
- public ImmutableList<DataCommitHandler<P, D>> call() throws Exception {
+ public ImmutableList<DataCommitHandler<P, D>> get() {
Map<P, Collection<DataCommitHandlerRegistrationImpl<P, D>>> _asMap = commitHandlers.asMap();
Set<Entry<P, Collection<DataCommitHandlerRegistrationImpl<P, D>>>> _entrySet = _asMap.entrySet();
FluentIterable<Entry<P, Collection<DataCommitHandlerRegistrationImpl<P, D>>>> _from = FluentIterable
}
protected ImmutableList<DataCommitHandler<P, D>> probablyAffectedCommitHandlers(final HashSet<P> paths) {
- final Callable<ImmutableList<DataCommitHandler<P, D>>> _function = new Callable<ImmutableList<DataCommitHandler<P, D>>>() {
+ final Supplier<ImmutableList<DataCommitHandler<P, D>>> _function = new Supplier<ImmutableList<DataCommitHandler<P, D>>>() {
@Override
- public ImmutableList<DataCommitHandler<P, D>> call() throws Exception {
+ public ImmutableList<DataCommitHandler<P, D>> get() {
Map<P, Collection<DataCommitHandlerRegistrationImpl<P, D>>> _asMap = commitHandlers.asMap();
Set<Entry<P, Collection<DataCommitHandlerRegistrationImpl<P, D>>>> _entrySet = _asMap.entrySet();
FluentIterable<Entry<P, Collection<DataCommitHandlerRegistrationImpl<P, D>>>> _from = FluentIterable
return _dataReadRouter.readOperationalData(path);
}
- private static <T extends Object> T withLock(final Lock lock, final Callable<T> method) {
+ private static <T extends Object> T withLock(final Lock lock, final Supplier<T> method) {
lock.lock();
try {
- return method.call();
- } catch (Exception e) {
- throw Exceptions.sneakyThrow(e);
+ return method.get();
} finally {
lock.unlock();
}
+/*
+ * 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.common.api.data.AsyncDataChangeEvent;
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
package org.opendaylight.controller.md.sal.dom.store.impl;
import java.util.Collections;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import com.google.common.base.Optional;
-import com.google.common.primitives.UnsignedLong;
class DataAndMetadataSnapshot {
public static DataAndMetadataSnapshot createEmpty(final NodeIdentifier rootNode) {
NormalizedNode<?, ?> data = Builders.containerBuilder().withNodeIdentifier(rootNode).build();
- StoreMetadataNode metadata = StoreMetadataNode.builder()
- .setNodeVersion(UnsignedLong.ZERO)
- .setSubtreeVersion(UnsignedLong.ZERO)
- .setData(data)
- .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.builder()
- .setData(data)
- .setNodeVersion(UnsignedLong.ZERO)
- .setSubtreeVersion(UnsignedLong.ZERO)
- .build();
+ StoreMetadataNode metadata = StoreMetadataNode.createEmpty(data);
return new DataAndMetadataSnapshot(metadata, Optional.of(ctx));
}
+/*
+ * 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.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-public interface DataChangeListenerRegistration<L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>>
-extends ListenerRegistration<L> {
-
-
+public interface DataChangeListenerRegistration<L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> extends ListenerRegistration<L> {
@Override
- public L getInstance();
+ L getInstance();
InstanceIdentifier getPath();
DataChangeScope getScope();
-
-
-
}
--- /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;
+ }
+
+}
private static final Logger LOG = LoggerFactory.getLogger(InMemoryDOMDataStore.class);
private static final InstanceIdentifier PUBLIC_ROOT_PATH = InstanceIdentifier.builder().build();
-
private final ListeningExecutorService executor;
private final String name;
private final AtomicLong txCounter = new AtomicLong(0);
final InstanceIdentifier path, final L listener, final DataChangeScope scope) {
/*
- * Make sure commit is not occurring right now. Listener has to be registered and its
- * state capture enqueued at a consistent point.
+ * Make sure commit is not occurring right now. Listener has to be
+ * registered and its state capture enqueued at a consistent point.
*
- * FIXME: improve this to read-write lock, such that multiple listener registrations
- * can occur simultaneously
+ * FIXME: improve this to read-write lock, such that multiple listener
+ * registrations can occur simultaneously
*/
final DataChangeListenerRegistration<L> reg;
synchronized (this) {
- LOG.debug("{}: Registering data change listener {} for {}",name,listener,path);
+ LOG.debug("{}: Registering data change listener {} for {}", name, listener, path);
reg = listenerTree.registerDataChangeListener(path, listener, scope);
};
}
- private synchronized DOMStoreThreePhaseCommitCohort submit(
- final SnapshotBackedWriteTransaction writeTx) {
- LOG.debug("Tx: {} is submitted. Modifications: {}",writeTx.getIdentifier(),writeTx.getMutatedView());
+ private synchronized DOMStoreThreePhaseCommitCohort submit(final SnapshotBackedWriteTransaction writeTx) {
+ LOG.debug("Tx: {} is submitted. Modifications: {}", writeTx.getIdentifier(), writeTx.getMutatedView());
return new ThreePhaseCommitImpl(writeTx);
}
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());
+ 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));
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Data Tree is {}", StoreUtils.toStringTree(newDataTree));
}
final DataAndMetadataSnapshot newSnapshot = DataAndMetadataSnapshot.builder() //
.build();
/*
- * The commit has to occur atomically with regard to listener registrations.
+ * 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);
+ LOG.trace("Scheduling invocation of listeners: {}", task);
executor.submit(task);
}
}
/**
* Add class-specific toString attributes.
*
- * @param toStringHelper ToStringHelper instance
+ * @param toStringHelper
+ * ToStringHelper instance
* @return ToStringHelper instance which was passed in
*/
protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
}
}
- private static class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements DOMStoreReadTransaction {
+ private static class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction implements
+ DOMStoreReadTransaction {
private DataAndMetadataSnapshot stableSnapshot;
public SnapshotBackedReadTransaction(final Object identifier, final DataAndMetadataSnapshot 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.getMetadataTree()
+ .getSubtreeVersion());
}
@Override
}
}
- private static class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements DOMStoreWriteTransaction {
+ private static class SnapshotBackedWriteTransaction extends AbstractDOMStoreTransaction implements
+ DOMStoreWriteTransaction {
private MutableDataTree mutableTree;
private InMemoryDOMDataStore store;
private boolean ready = false;
super(identifier);
mutableTree = MutableDataTree.from(snapshot, applyOper);
this.store = store;
- LOG.debug("Write Tx: {} allocated with snapshot {}",identifier,snapshot.getMetadataTree().getSubtreeVersion());
+ LOG.debug("Write Tx: {} allocated with snapshot {}", identifier, snapshot.getMetadataTree()
+ .getSubtreeVersion());
}
@Override
public void write(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
checkNotReady();
try {
- LOG.trace("Tx: {} Write: {}:{}",getIdentifier(),path,data);
+ LOG.trace("Tx: {} Write: {}:{}", getIdentifier(), path, data);
mutableTree.write(path, data);
- // FIXME: Add checked exception
+ // FIXME: Add checked exception
} catch (Exception e) {
- LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e);
+ LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, mutableTree, e);
}
}
public void merge(final InstanceIdentifier path, final NormalizedNode<?, ?> data) {
checkNotReady();
try {
- LOG.trace("Tx: {} Merge: {}:{}",getIdentifier(),path,data);
+ LOG.trace("Tx: {} Merge: {}:{}", getIdentifier(), path, data);
mutableTree.merge(path, data);
- // FIXME: Add checked exception
+ // FIXME: Add checked exception
} catch (Exception e) {
- LOG.error("Tx: {}, failed to write {}:{} in {}",getIdentifier(),path,data,mutableTree,e);
+ LOG.error("Tx: {}, failed to write {}:{} in {}", getIdentifier(), path, data, mutableTree, e);
}
}
public void delete(final InstanceIdentifier path) {
checkNotReady();
try {
- LOG.trace("Tx: {} Delete: {}",getIdentifier(),path);
+ LOG.trace("Tx: {} Delete: {}", getIdentifier(), path);
mutableTree.delete(path);
- // FIXME: Add checked exception
+ // FIXME: Add checked exception
} catch (Exception e) {
- LOG.error("Tx: {}, failed to delete {} in {}",getIdentifier(),path,mutableTree,e);
+ LOG.error("Tx: {}, failed to delete {} in {}", getIdentifier(), path, mutableTree, e);
}
}
@Override
public ListenableFuture<Optional<NormalizedNode<?, ?>>> read(final InstanceIdentifier path) {
- LOG.trace("Tx: {} Read: {}",getIdentifier(),path);
+ LOG.trace("Tx: {} Read: {}", getIdentifier(), path);
try {
return Futures.immediateFuture(getMutatedView().read(path));
} catch (Exception e) {
- LOG.error("Tx: {} Failed Read of {}",getIdentifier(),path,e);
+ LOG.error("Tx: {} Failed Read of {}", getIdentifier(), path, e);
throw e;
}
}
@Override
public Boolean call() throws Exception {
- boolean applicable = snapshotOperation.isApplicable(modification,
+ Boolean applicable = false;
+ try {
+ snapshotOperation.checkApplicable(PUBLIC_ROOT_PATH, modification,
Optional.of(snapshotCapture.getMetadataTree()));
- LOG.debug("Store Transcation: {} : canCommit : {}", transaction.getIdentifier(), applicable);
+ applicable = true;
+ } catch (DataPreconditionFailedException e) {
+ LOG.warn("Store Tx: {} Data Precondition failed for {}.",transaction.getIdentifier(),e.getPath(),e);
+ applicable = false;
+ }
+ LOG.debug("Store Transaction: {} : canCommit : {}", transaction.getIdentifier(), applicable);
return applicable;
}
});
@Override
public ListenableFuture<Void> preCommit() {
storeSnapshot = snapshot.get();
- if(modification.getModificationType() == ModificationType.UNMODIFIED) {
+ 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();
@Override
public ListenableFuture<Void> commit() {
- if(modification.getModificationType() == ModificationType.UNMODIFIED) {
+ if (modification.getModificationType() == ModificationType.UNMODIFIED) {
return Futures.immediateFuture(null);
}
- checkState(proposedSubtree != null,"Proposed subtree must be computed");
- checkState(storeSnapshot != null,"Proposed subtree must be computed");
+ 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);
+ InMemoryDOMDataStore.this.commit(storeSnapshot, proposedSubtree.get(), listenerResolver);
return Futures.<Void> immediateFuture(null);
}
}
@Override
- public boolean isApplicable(final NodeModification modification, final Optional<StoreMetadataNode> storeMetadata) {
+ public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> storeMetadata) {
throw new IllegalStateException("Schema Context is not available.");
}
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.StoreTreeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import com.google.common.base.Optional;
*/
Optional<StoreMetadataNode> apply(NodeModification modification, Optional<StoreMetadataNode> storeMeta, UnsignedLong subtreeVersion);
- /**
- *
- * 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
- */
- boolean isApplicable(NodeModification modification, Optional<StoreMetadataNode> current);
-
/**
*
* Performs structural verification of NodeModification, such as writen values / types
* if suboperation is not supported for specified tree node.
*/
@Override
- public Optional<ModificationApplyOperation> getChild(PathArgument child);
-
-
+ 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
+ * @throws DataPreconditionFailedException
+ */
+ void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
}
+/*
+ * 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.NodeModification;
return applyOperation;
}
- public boolean isApplicable(final Optional<StoreMetadataNode> data) {
- return applyOperation.isApplicable(modification, data);
- }
-
public Optional<StoreMetadataNode> apply(final Optional<StoreMetadataNode> data, final UnsignedLong subtreeVersion) {
return applyOperation.apply(modification, data, subtreeVersion);
}
Optional<ModificationApplyOperation> childOp = applyOperation.getChild(childId);
return from(childOp.get(),childMod);
}
-}
\ No newline at end of file
+}
final Collection<Node> listeners, final NormalizedNode<?, ?> beforeData,
final NormalizedNode<?, ?> afterData) {
- if (beforeData instanceof NormalizedNodeContainer<?, ?, ?> && !listeners.isEmpty()) {
+ if (beforeData instanceof NormalizedNodeContainer<?, ?, ?>) {
// Node is container (contains child) and we have interested
// listeners registered for it, that means we need to do
// resolution of changes on children level and can not
// shortcut resolution.
-
+ LOG.trace("Resolving subtree replace event for {} before {}, after {}",path,beforeData,afterData);
@SuppressWarnings("unchecked")
NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) beforeData;
@SuppressWarnings("unchecked")
// Node is either of Leaf type (does not contain child nodes)
// or we do not have listeners, so normal equals method is
// sufficient for determining change.
-
+ LOG.trace("Resolving leaf replace event for {} , before {}, after {}",path,beforeData,afterData);
DOMImmutableDataChangeEvent event = builder(DataChangeScope.BASE).setBefore(beforeData).setAfter(afterData)
.addUpdated(path, beforeData, afterData).build();
addPartialTask(listeners, event);
private DOMImmutableDataChangeEvent resolveSameEventRecursivelly(final InstanceIdentifier path,
final Collection<Node> listeners, final NormalizedNode<PathArgument, ?> node,
final SimpleEventFactory eventFactory) {
-
final DOMImmutableDataChangeEvent event = eventFactory.create(path, node);
DOMImmutableDataChangeEvent propagateEvent = event;
- // We have listeners for this node or it's children, so we will try
+ // We have listeners for this node or it's children, so we will try
// to do additional processing
if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
+ LOG.trace("Resolving subtree recursive event for {}, type {}", path, eventFactory);
+
Builder eventBuilder = builder(DataChangeScope.BASE);
eventBuilder.merge(event);
eventBuilder.setBefore(event.getOriginalSubtree());
NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> container = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) node;
for (NormalizedNode<PathArgument, ?> child : container.getValue()) {
PathArgument childId = child.getIdentifier();
+ LOG.trace("Resolving event for child {}", childId);
Collection<Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
eventBuilder.merge(resolveSameEventRecursivelly(append(path, childId), childListeners, child, eventFactory));
}
propagateEvent = builder(DataChangeScope.BASE).build();
}
if (!listeners.isEmpty()) {
- addPartialTask(listeners, event);
+ addPartialTask(listeners, propagateEvent);
}
return propagateEvent;
}
private DOMImmutableDataChangeEvent addPartialTask(final Collection<ListenerTree.Node> listeners,
final DOMImmutableDataChangeEvent event) {
-
for (ListenerTree.Node listenerNode : listeners) {
if (!listenerNode.getListeners().isEmpty()) {
+ LOG.trace("Adding event {} for listeners {}",event,listenerNode);
events.put(listenerNode, event);
}
}
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
package org.opendaylight.controller.md.sal.dom.store.impl;
import static com.google.common.base.Preconditions.checkArgument;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreNodeCompositeBuilder;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.primitives.UnsignedLong;
public abstract class SchemaAwareApplyOperation implements ModificationApplyOperation {
protected abstract void verifyWritenStructure(NormalizedNode<?, ?> writenValue);
@Override
- public boolean isApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
+ public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
switch (modification.getModificationType()) {
case DELETE:
- return isDeleteApplicable(modification, current);
+ checkDeleteApplicable(modification, current);
case SUBTREE_MODIFIED:
- return isSubtreeModificationApplicable(modification, current);
+ checkSubtreeModificationApplicable(path,modification, current);
+ return;
case WRITE:
- return isWriteApplicable(modification, current);
+ checkWriteApplicable(path,modification, current);
+ return;
case MERGE:
- return isMergeApplicable(modification,current);
+ checkMergeApplicable(path,modification,current);
+ return;
case UNMODIFIED:
- return true;
+ return;
default:
- return false;
+ throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported.");
}
+
}
- private boolean isMergeApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
+ 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()) {
- return isNotConflicting(original.get(), current.get());
- } else if (current.isPresent()) {
- return true;
+ checkNotConflicting(path,original.get(), current.get());
}
- return true;
}
- protected boolean isWriteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
+ protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
Optional<StoreMetadataNode> original = modification.getOriginal();
if (original.isPresent() && current.isPresent()) {
- return isNotConflicting(original.get(), current.get());
- } else if (current.isPresent()) {
- return false;
+ checkNotConflicting(path,original.get(), current.get());
+ } else if(original.isPresent()) {
+ throw new DataPreconditionFailedException(path,"Node was deleted by other transaction.");
}
- return true;
-
}
- protected final boolean isNotConflicting(final StoreMetadataNode original, final StoreMetadataNode current) {
- return original.getNodeVersion().equals(current.getNodeVersion())
- && original.getSubtreeVersion().equals(current.getSubtreeVersion());
+ protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException {
+ checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction.");
+ checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction");
}
- protected abstract boolean isSubtreeModificationApplicable(final NodeModification modification,
- final Optional<StoreMetadataNode> current);
+ protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification,
+ final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException;
- private boolean isDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
- // FiXME: Add delete conflict detection.
- return true;
+ private void checkDeleteApplicable(final NodeModification modification, final Optional<StoreMetadataNode> current) {
}
@Override
}
@Override
- protected boolean isSubtreeModificationApplicable(final NodeModification modification,
- final Optional<StoreMetadataNode> current) {
- return false;
+ protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
+ final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+ throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
}
}
}
}
+ @Override
+ protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification,
+ final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+ // FIXME: Implement proper write check for replacement of node container
+ // prerequisite is to have transaction chain available for clients
+ // otherwise this will break chained writes to same node.
+ }
+
@SuppressWarnings("rawtypes")
@Override
protected void verifyWritenStructure(final NormalizedNode<?, ?> writenValue) {
@Override
protected StoreMetadataNode applyWrite(final NodeModification modification,
final Optional<StoreMetadataNode> currentMeta, final UnsignedLong subtreeVersion) {
- //
+
NormalizedNode<?, ?> newValue = modification.getWritenValue();
- UnsignedLong nodeVersion = subtreeVersion;
+ final UnsignedLong nodeVersion;
if (currentMeta.isPresent()) {
nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion());
+ } else {
+ nodeVersion = subtreeVersion;
}
- StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
+ final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion, nodeVersion);
if (!modification.hasAdditionalModifications()) {
return newValueMeta;
}
+
@SuppressWarnings("rawtypes")
- NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier());
+ NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue);
StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder) //
.setNodeVersion(nodeVersion) //
.setSubtreeVersion(subtreeVersion);
- Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification, newValueMeta.getChildren(),
- builder, nodeVersion);
- applyNewChildren(modification, processedPreexisting, builder, nodeVersion);
-
- return builder.build();
-
+ return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion);
}
@Override
@Override
public StoreMetadataNode applySubtreeChange(final NodeModification modification,
final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) {
+ // Bump subtree version to its new target
+ final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
- UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion());
@SuppressWarnings("rawtypes")
- NormalizedNodeContainerBuilder dataBuilder = createBuilder(modification.getIdentifier());
- StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder)
+ NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData());
+ StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.from(dataBuilder, currentMeta)
.setIdentifier(modification.getIdentifier()).setNodeVersion(currentMeta.getNodeVersion())
.setSubtreeVersion(updatedSubtreeVersion);
- // We process preexisting nodes
- Set<PathArgument> processedPreexisting = applyPreexistingChildren(modification, currentMeta.getChildren(),
- builder, updatedSubtreeVersion);
- applyNewChildren(modification, processedPreexisting, builder, updatedSubtreeVersion);
- return builder.build();
+
+ return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion);
}
- private void applyNewChildren(final NodeModification modification, final Set<PathArgument> ignore,
- final StoreNodeCompositeBuilder builder, final UnsignedLong subtreeVersion) {
- for (NodeModification childModification : modification.getModifications()) {
- PathArgument childIdentifier = childModification.getIdentifier();
- // We skip allready processed modifications
- if (ignore.contains(childIdentifier)) {
- continue;
- }
+ private StoreMetadataNode mutateChildren(final Iterable<NodeModification> modifications, final StoreMetadataNode meta,
+ final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) {
- builder.addIfPresent(resolveChildOperation(childIdentifier) //
- .apply(childModification, Optional.<StoreMetadataNode> absent(), subtreeVersion));
- }
- }
+ for (NodeModification mod : modifications) {
+ final PathArgument id = mod.getIdentifier();
+ final Optional<StoreMetadataNode> cm = meta.getChild(id);
- private Set<PathArgument> applyPreexistingChildren(final NodeModification modification,
- final Iterable<StoreMetadataNode> children, final StoreNodeCompositeBuilder nodeBuilder,
- final UnsignedLong subtreeVersion) {
- Builder<PathArgument> processedModifications = ImmutableSet.<PathArgument> builder();
- for (StoreMetadataNode childMeta : children) {
- PathArgument childIdentifier = childMeta.getIdentifier();
- // We retrieve Child modification metadata
- Optional<NodeModification> childModification = modification.getChild(childIdentifier);
- // Node is modified
- if (childModification.isPresent()) {
- processedModifications.add(childIdentifier);
- Optional<StoreMetadataNode> result = resolveChildOperation(childIdentifier) //
- .apply(childModification.get(), Optional.of(childMeta), subtreeVersion);
- nodeBuilder.addIfPresent(result);
+ Optional<StoreMetadataNode> result = resolveChildOperation(id).apply(mod, cm, nodeVersion);
+ if (result.isPresent()) {
+ builder.add(result.get());
} else {
- // Child is unmodified - reuse existing metadata and data
- // snapshot
- nodeBuilder.add(childMeta);
+ builder.remove(id);
}
}
- return processedModifications.build();
+
+ return builder.build();
}
@Override
- protected boolean isSubtreeModificationApplicable(final NodeModification modification,
- final Optional<StoreMetadataNode> current) {
- if (false == current.isPresent()) {
- return false;
- }
- boolean result = true;
+ protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
+ final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+ checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction.");
+ checkChildPreconditions(path,modification,current);
+
+ }
+
+ private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
StoreMetadataNode currentMeta = current.get();
for (NodeModification childMod : modification.getModifications()) {
PathArgument childId = childMod.getIdentifier();
Optional<StoreMetadataNode> childMeta = currentMeta.getChild(childId);
- result &= resolveChildOperation(childId).isApplicable(childMod, childMeta);
+ InstanceIdentifier childPath = StoreUtils.append(path, childId);
+ resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta);
+ }
+ }
+
+ @Override
+ protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification,
+ final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+ if(current.isPresent()) {
+ checkChildPreconditions(path,modification,current);
}
- return result;
}
@SuppressWarnings("rawtypes")
- protected abstract NormalizedNodeContainerBuilder createBuilder(PathArgument identifier);
+ protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode<?, ?> original);
}
public static abstract class DataNodeContainerModificationStrategy<T extends DataNodeContainer> extends
@Override
@SuppressWarnings("rawtypes")
- protected abstract DataContainerNodeBuilder createBuilder(PathArgument identifier);
+ protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original);
@Override
public String toString() {
@Override
@SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
- // TODO Auto-generated method stub
- checkArgument(identifier instanceof NodeIdentifier);
- return ImmutableContainerNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof ContainerNode);
+ return ImmutableContainerNodeBuilder.create((ContainerNode) original);
}
-
}
public static class UnkeyedListItemModificationStrategy extends
@Override
@SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
- checkArgument(identifier instanceof NodeIdentifier);
- return ImmutableUnkeyedListEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof UnkeyedListEntryNode);
+ return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original);
}
-
}
public static class AugmentationModificationStrategy extends
protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) {
super(createAugmentProxy(schema,resolved), AugmentationNode.class);
- // FIXME: Use resolved children instead of unresolved.
-
}
@Override
- protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
- return Builders.augmentationBuilder().withNodeIdentifier((AugmentationIdentifier) identifier);
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof AugmentationNode);
+ return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
}
-
}
public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy {
@Override
@SuppressWarnings("rawtypes")
- protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
- checkArgument(identifier instanceof NodeIdentifier);
- return ImmutableChoiceNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ protected DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode);
+ return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original);
}
-
}
public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy<ListSchemaNode> {
@Override
@SuppressWarnings("rawtypes")
- protected final DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
- return ImmutableMapEntryNodeBuilder.create().withNodeIdentifier((NodeIdentifierWithPredicates) identifier);
+ protected final DataContainerNodeBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof MapEntryNode);
+ return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original);
}
-
}
public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
@SuppressWarnings("rawtypes")
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
- return ImmutableLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof LeafSetNode<?>);
+ return ImmutableLeafSetNodeBuilder.create((LeafSetNode<?>) original);
}
@Override
}
return Optional.absent();
}
-
}
public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy {
@SuppressWarnings("rawtypes")
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
- return ImmutableOrderedLeafSetNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof OrderedLeafSetNode<?>);
+ return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode<?>) original);
}
@Override
}
return Optional.absent();
}
-
}
public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation {
}
@Override
- protected boolean isSubtreeModificationApplicable(final NodeModification modification,
- final Optional<StoreMetadataNode> current) {
- return false;
+ protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification,
+ final Optional<StoreMetadataNode> current) throws DataPreconditionFailedException {
+ throw new DataPreconditionFailedException(path, "Subtree modification is not allowed.");
}
}
@SuppressWarnings("rawtypes")
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
- return ImmutableMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof MapNode);
+ return ImmutableMapNodeBuilder.create((MapNode) original);
}
@Override
@SuppressWarnings("rawtypes")
@Override
- protected NormalizedNodeContainerBuilder createBuilder(final PathArgument identifier) {
- return ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
+ protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode<?, ?> original) {
+ checkArgument(original instanceof OrderedMapNode);
+ return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original);
}
@Override
return new AugmentationSchemaProxy(schema, realChildSchemas);
}
+ public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException {
+ if(!condition) {
+ throw new DataPreconditionFailedException(path, message);
+ }
+ return condition;
+ }
+
}
*/
package org.opendaylight.controller.md.sal.dom.store.impl;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public class SchemaAwareApplyOperationRoot extends SchemaAwareApplyOperation.DataNodeContainerModificationStrategy<ContainerSchemaNode> {
-
private final SchemaContext context;
public SchemaAwareApplyOperationRoot(final SchemaContext context) {
this.context = context;
}
- @Override
- protected DataContainerNodeBuilder createBuilder(final PathArgument identifier) {
- return ImmutableContainerNodeBuilder.create().withNodeIdentifier((NodeIdentifier) identifier);
- }
-
public SchemaContext getContext() {
return context;
}
return "SchemaAwareApplyOperationRoot [context=" + context + "]";
}
+ @Override
+ @SuppressWarnings("rawtypes")
+ protected DataContainerNodeBuilder createBuilder(NormalizedNode<?, ?> original) {
+ return ImmutableContainerNodeBuilder.create((ContainerNode) original);
+ }
}
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
package org.opendaylight.controller.md.sal.dom.store.impl;
import java.util.Collections;
import static com.google.common.base.Preconditions.checkState;
+import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
this.children = Preconditions.checkNotNull(children);
}
+ public static StoreMetadataNode createEmpty(final NormalizedNode<?, ?> data) {
+ return new StoreMetadataNode(data, UnsignedLong.ZERO, UnsignedLong.ZERO,
+ Collections.<PathArgument, StoreMetadataNode>emptyMap());
+ }
+
+ public StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
+ final UnsignedLong subtreeVersion) {
+ this(data, nodeVersion, subtreeVersion, Collections.<PathArgument, StoreMetadataNode>emptyMap());
+ }
+
public static Builder builder() {
return new Builder();
}
+ public static Builder builder(StoreMetadataNode node) {
+ return new Builder(node);
+ }
+
public UnsignedLong getNodeVersion() {
return this.nodeVersion;
}
private UnsignedLong nodeVersion;
private UnsignedLong subtreeVersion;
private NormalizedNode<?, ?> data;
- private Map<PathArgument, StoreMetadataNode> children = new LinkedHashMap<>();
+ private Map<PathArgument, StoreMetadataNode> children;
private boolean dirty = false;
- private Builder() {}
+ private Builder() {
+ children = new LinkedHashMap<>();
+ }
+ public Builder(StoreMetadataNode node) {
+ children = new LinkedHashMap<>(node.children);
+ }
public UnsignedLong getVersion() {
return nodeVersion;
return this;
}
+ public Builder remove(final PathArgument id) {
+ if (dirty) {
+ children = new LinkedHashMap<>(children);
+ dirty = false;
+ }
+ children.remove(id);
+ return this;
+ }
+
public StoreMetadataNode build() {
checkState(data != null, "Data node should not be null.");
checkState(subtreeVersion.compareTo(nodeVersion) >= 0,
public static StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node, final UnsignedLong version) {
return createRecursively(node, version, version);
}
-
}
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
-import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.primitives.UnsignedLong;
/**
private StoreNodeCompositeBuilder(final NormalizedNodeContainerBuilder nodeBuilder) {
this.metadata = StoreMetadataNode.builder();
- this.data = nodeBuilder;
+ this.data = Preconditions.checkNotNull(nodeBuilder);
+ }
+
+ public StoreNodeCompositeBuilder(NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) {
+ this.metadata = StoreMetadataNode.builder(currentMeta);
+ this.data = Preconditions.checkNotNull(nodeBuilder);
}
@SuppressWarnings("unchecked")
}
@SuppressWarnings("unchecked")
- public StoreNodeCompositeBuilder addIfPresent(final Optional<StoreMetadataNode> potential) {
- if (potential.isPresent()) {
- StoreMetadataNode node = potential.get();
- metadata.add(node);
- data.addChild(node.getData());
- }
+ public StoreNodeCompositeBuilder remove(PathArgument id) {
+ metadata.remove(id);
+ data.removeChild(id);
return this;
}
return new StoreNodeCompositeBuilder(nodeBuilder);
}
+ public static StoreNodeCompositeBuilder from(final NormalizedNodeContainerBuilder nodeBuilder, StoreMetadataNode currentMeta) {
+ return new StoreNodeCompositeBuilder(nodeBuilder, currentMeta);
+ }
+
@SuppressWarnings("unchecked")
public StoreNodeCompositeBuilder setIdentifier(final PathArgument identifier) {
data.withNodeIdentifier(identifier);
metadata.setSubtreeVersion(updatedSubtreeVersion);
return this;
}
-
}
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
-public class TreeNodeUtils {
+public final class TreeNodeUtils {
+ private TreeNodeUtils() {
+ throw new UnsupportedOperationException("Utility class should not be instantiated");
+ }
/**
* Finds a node in tree
return current;
}
-
public static <T extends StoreTreeNode<T>> T findNodeChecked(final T tree, final InstanceIdentifier path) {
T current = tree;
List<PathArgument> nested = new ArrayList<>(path.getPath().size());
try {
listener.onRouteChange(initial);
} catch (Exception e) {
- LOG.error("Unhandled exception during sending initial route change event {} to {}",initial,listener);
+ LOG.error("Unhandled exception during sending initial route change event {} to {}",initial,listener, e);
}
return reg;
}
InstanceIdentifier normalizedPath = normalizer.toNormalized(LEAF_TWO_PATH_LEGACY);
- Node<?> outerListLegacy = normalizer.toLegacy(OUTER_LIST_WITH_CHOICE);
+ Node<?> outerListLegacy = DataNormalizer.toLegacy(OUTER_LIST_WITH_CHOICE);
assertNotNull(outerListLegacy);
-
-
-
-
}
}
import java.util.concurrent.ExecutionException;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
}
@Test
+ @Ignore
public void testTransactionConflict() throws InterruptedException, ExecutionException {
DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction();
DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction();
<dependencies>
<dependency>
+
<groupId>${project.groupId}</groupId>
<artifactId>netconf-client</artifactId>
<version>${netconf.version}</version>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netconf-client</artifactId>
- <version>${netconf.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netty-threadgroup-config</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>threadpool-config-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkCondition;
import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkNotNull;
+import com.google.common.net.InetAddresses;
import io.netty.util.HashedWheelTimer;
import io.netty.util.concurrent.GlobalEventExecutor;
-
import java.io.File;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-
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.sal.binding.api.data.DataProviderService;
import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceListener;
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;
+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.model.util.repo.AbstractCachingSchemaSourceProvider;
import org.opendaylight.yangtools.yang.model.util.repo.FilesystemSchemaCachingProvider;
import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProviders;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.net.InetAddresses;
-
/**
*
*/
@Override
public java.lang.AutoCloseable createInstance() {
+ ServiceReference<DataProviderService> serviceReference = bundleContext.getServiceReference(DataProviderService.class);
+
+ DataProviderService dataProviderService =
+ bundleContext.getService(serviceReference);
getDomRegistryDependency();
NetconfDevice device = new NetconfDevice(getIdentifier().getInstanceName());
device.setEventExecutor(getEventExecutorDependency());
device.setDispatcher(getClientDispatcher() == null ? createDispatcher() : getClientDispatcherDependency());
device.setSchemaSourceProvider(getGlobalNetconfSchemaProvider(bundleContext));
-
+ device.setDataProviderService(dataProviderService);
getDomRegistryDependency().registerProvider(device, bundleContext);
device.start();
return device;
this.bundleContext = bundleContext;
}
- public NetconfClientConfiguration getClientConfig(final NetconfDevice device) {
+ public NetconfReconnectingClientConfiguration getClientConfig(final NetconfDevice device) {
InetSocketAddress socketAddress = getSocketAddress();
ReconnectStrategy strategy = getReconnectStrategy();
long clientConnectionTimeoutMillis = getConnectionTimeoutMillis();
- return NetconfClientConfigurationBuilder.create()
+ return NetconfReconnectingClientConfigurationBuilder.create()
.withAddress(socketAddress)
.withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
.withReconnectStrategy(strategy)
.withProtocol(getTcpOnly() ?
NetconfClientConfiguration.NetconfClientProtocol.TCP :
NetconfClientConfiguration.NetconfClientProtocol.SSH)
+ .withConnectStrategyFactory(new ReconnectStrategyFactory() {
+ @Override
+ public ReconnectStrategy createReconnectStrategy() {
+ return getReconnectStrategy();
+ }
+ })
.build();
}
logger.trace("Setting {} on {} to infinity", maxConnectionAttemptsJmxAttribute, this);
connectionAttempts = null;
}
- double sleepFactor = 1.0;
+ double sleepFactor = 1.5;
int minSleep = 1000;
Long maxSleep = null;
Long deadline = null;
import org.opendaylight.controller.md.sal.common.api.data.DataReader;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
+import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
import org.opendaylight.controller.sal.core.api.Provider;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
SchemaSourceProvider<InputStream> remoteSourceProvider;
- DataBrokerService dataBroker;
+ private volatile DataBrokerService dataBroker;
NetconfDeviceListener listener;
private boolean rollbackSupported;
- private NetconfClientConfiguration clientConfig;
+ private NetconfReconnectingClientConfiguration clientConfig;
+ private volatile DataProviderService dataProviderService;
public NetconfDevice(String name) {
this.name = name;
logger.info("Starting NETCONF Client {} for address {}", name, socketAddress);
- dispatcher.createClient(clientConfig);
+ dispatcher.createReconnectingClient(clientConfig);
}
Optional<SchemaContext> getSchemaContext() {
}
private void updateDeviceState(boolean up, Set<QName> capabilities) {
+ checkDataStoreState();
+
DataModificationTransaction transaction = dataBroker.beginTransaction();
CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder();
public void onSessionInitiated(ProviderSession session) {
dataBroker = session.getService(DataBrokerService.class);
+ processingExecutor.submit(new Runnable() {
+ @Override
+ public void run() {
+ updateInitialState();
+ }
+ });
+
+ mountService = session.getService(MountProvisionService.class);
+ if (mountService != null) {
+ mountInstance = mountService.createOrGetMountPoint(path);
+ }
+ }
+
+ private void updateInitialState() {
+ checkDataStoreState();
+
DataModificationTransaction transaction = dataBroker.beginTransaction();
if (operationalNodeNotExisting(transaction)) {
transaction.putOperationalData(path, getNodeWithId());
} catch (ExecutionException e) {
throw new RuntimeException("Read configuration data " + path + " failed", e);
}
-
- mountService = session.getService(MountProvisionService.class);
- if (mountService != null) {
- mountInstance = mountService.createOrGetMountPoint(path);
- }
}
+ private void checkDataStoreState() {
+ // read data from Nodes/Node in order to wait with write until schema for Nodes/Node is present in datastore
+ dataProviderService.readOperationalData(org.opendaylight.yangtools.yang.binding.InstanceIdentifier.builder(
+ Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class).augmentation(NetconfNode.class).build()); }
+
CompositeNode getNodeWithId() {
SimpleNodeTOImpl id = new SimpleNodeTOImpl(INVENTORY_ID, null, name);
return new CompositeNodeTOImpl(INVENTORY_NODE, null, Collections.<Node<?>> singletonList(id));
this.dispatcher = dispatcher;
}
- public void setClientConfig(final NetconfClientConfiguration clientConfig) {
+ public void setClientConfig(final NetconfReconnectingClientConfiguration clientConfig) {
this.clientConfig = clientConfig;
}
+ public void setDataProviderService(final DataProviderService dataProviderService) {
+ this.dataProviderService = dataProviderService;
+ }
}
class NetconfDeviceSchemaContextProvider {
for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument component : Lists
.reverse(identifier.getPath())) {
- previous = toNode(component, previous);
+ if (component instanceof NodeIdentifierWithPredicates) {
+ previous = toNode((NodeIdentifierWithPredicates)component, previous);
+ } else {
+ previous = toNode(component, previous);
+ }
}
return filter("subtree", previous);
}
package org.opendaylight.controller.sal.connector.remoterpc;
-import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
import java.util.Collection;
import java.util.Collections;
Optional<RoutingTable<RpcRouter.RouteIdentifier, String>> routingTable =
routingTableProvider.getRoutingTable();
- checkNotNull(routingTable.isPresent(), "Routing table is null");
+ checkState(routingTable.isPresent(), "Routing table is null");
return routingTable.get();
}
package org.opendaylight.controller.sal.connector.remoterpc.dto;
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
-import java.io.*;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
public class Message implements Serializable {
+ private static final long serialVersionUID = 1L;
public static enum MessageType {
PING((byte) 0),
}
public static class Response extends Message implements RpcRouter.RpcReply {
+ private static final long serialVersionUID = 1L;
private ResponseCode code; // response code
public static enum ResponseCode {
SUCCESS(200), BADREQUEST(400), TIMEOUT(408), GONE(410), SERVERERROR(500), SERVICEUNAVAILABLE(503);
- private int code;
+ private final int code;
ResponseCode(int code) {
this.code = code;
*/
public static class MessageBuilder{
- private Message message;
+ private final Message message;
public MessageBuilder(){
message = new Message();
*/
package org.opendaylight.controller.sal.connector.remoterpc.dto;
+import java.io.Serializable;
+
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import java.io.Serializable;
-
public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>,Serializable {
+ private static final long serialVersionUID = 1L;
private QName context;
private QName type;
*/
package org.opendaylight.controller.sal.connector.remoterpc;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
import junit.framework.Assert;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import org.zeromq.ZMQ;
-import java.io.IOException;
-import java.util.concurrent.*;
-
/**
*
*/
serverThread.execute(MessagingUtil.startReplyServer(context, serverAddress, 1));
threadPool.execute(createEmptyMessageTaskAndHandle(handler, serverAddress));
}
- Thread.currentThread().sleep(5000);//wait for all messages to get processed
+ Thread.sleep(5000);//wait for all messages to get processed
//should be connected to 5 remote server
Assert.assertEquals(5, handler.getWorkerCount());
}
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</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.impl,
- org.eclipse.xtend2.lib,
- org.eclipse.xtend.lib,
- org.eclipse.xtext.xbase.*,</Private-Package>
+ org.opendaylight.controller.sal.restconf.impl,</Private-Package>
<Import-Package>*,
com.sun.jersey.spi.container.servlet</Import-Package>
<Bundle-Activator>org.opendaylight.controller.sal.rest.impl.RestconfProvider</Bundle-Activator>
</instructions>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
</plugins>
</build>
<scm>
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.restconf.impl;
+
+import 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.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.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;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
+ private final static Logger LOG = LoggerFactory.getLogger( BrokerFacade.class );
+
+ private final static BrokerFacade INSTANCE = new BrokerFacade();
+
+ private volatile DataBrokerService dataService;
+ private volatile ConsumerSession context;
+
+ private BrokerFacade() {
+ }
+
+ public void setContext( final ConsumerSession context ) {
+ this.context = context;
+ }
+
+ public void setDataService( final DataBrokerService dataService ) {
+ this.dataService = dataService;
+ }
+
+ public static BrokerFacade getInstance() {
+ return BrokerFacade.INSTANCE;
+ }
+
+ private void checkPreconditions() {
+ if( context == null || dataService == null ) {
+ ResponseException _responseException = new ResponseException( Status.SERVICE_UNAVAILABLE,
+ RestconfProvider.NOT_INITALIZED_MSG );
+ throw _responseException;
+ }
+ }
+
+ @Override
+ public CompositeNode readConfigurationData( final InstanceIdentifier path ) {
+ this.checkPreconditions();
+
+ LOG.trace( "Read Configuration via Restconf: {}", path );
+
+ return dataService.readConfigurationData( path );
+ }
+
+ public CompositeNode readConfigurationDataBehindMountPoint( final MountInstance mountPoint,
+ final InstanceIdentifier path ) {
+ this.checkPreconditions();
+
+ LOG.trace( "Read Configuration via Restconf: {}", path );
+
+ return mountPoint.readConfigurationData( path );
+ }
+
+ @Override
+ public CompositeNode readOperationalData( final InstanceIdentifier path ) {
+ this.checkPreconditions();
+
+ BrokerFacade.LOG.trace( "Read Operational via Restconf: {}", path );
+
+ return dataService.readOperationalData( path );
+ }
+
+ public CompositeNode readOperationalDataBehindMountPoint( final MountInstance mountPoint,
+ final InstanceIdentifier path ) {
+ this.checkPreconditions();
+
+ BrokerFacade.LOG.trace( "Read Operational via Restconf: {}", path );
+
+ return mountPoint.readOperationalData( path );
+ }
+
+ public RpcResult<CompositeNode> invokeRpc( final QName type, final CompositeNode payload ) {
+ this.checkPreconditions();
+
+ final Future<RpcResult<CompositeNode>> future = context.rpc( type, payload );
+
+ try {
+ return future.get();
+ }
+ catch( Exception e ) {
+ throw new ResponseException( e, "Error invoking RPC " + type );
+ }
+ }
+
+ public Future<RpcResult<TransactionStatus>> commitConfigurationDataPut( final InstanceIdentifier path,
+ final CompositeNode payload ) {
+ this.checkPreconditions();
+
+ final DataModificationTransaction transaction = dataService.beginTransaction();
+ BrokerFacade.LOG.trace( "Put Configuration via Restconf: {}", path );
+ transaction.putConfigurationData( path, payload );
+ return transaction.commit();
+ }
+
+ public Future<RpcResult<TransactionStatus>> commitConfigurationDataPutBehindMountPoint(
+ final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload ) {
+ this.checkPreconditions();
+
+ final DataModificationTransaction transaction = mountPoint.beginTransaction();
+ BrokerFacade.LOG.trace( "Put Configuration via Restconf: {}", path );
+ transaction.putConfigurationData( path, payload );
+ return transaction.commit();
+ }
+
+ public Future<RpcResult<TransactionStatus>> commitConfigurationDataPost( final InstanceIdentifier path,
+ 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();
+ }
+
+ LOG.trace( "Post Configuration via Restconf was not executed because data already exists: {}",
+ path );
+ return null;
+ }
+
+ public Future<RpcResult<TransactionStatus>> commitConfigurationDataPostBehindMountPoint(
+ final MountInstance mountPoint, final InstanceIdentifier path, final CompositeNode payload ) {
+ 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();
+ }
+
+ LOG.trace( "Post Configuration via Restconf was not executed because data already exists: {}",
+ path );
+ return null;
+ }
+
+ public Future<RpcResult<TransactionStatus>> commitConfigurationDataDelete( final InstanceIdentifier path ) {
+ this.checkPreconditions();
+
+ final DataModificationTransaction transaction = dataService.beginTransaction();
+ LOG.info( "Delete Configuration via Restconf: {}", path );
+ transaction.removeConfigurationData( path );
+ return transaction.commit();
+ }
+
+ public Future<RpcResult<TransactionStatus>> commitConfigurationDataDeleteBehindMountPoint(
+ final MountInstance mountPoint, final InstanceIdentifier path ) {
+ this.checkPreconditions();
+
+ final DataModificationTransaction transaction = mountPoint.beginTransaction();
+ LOG.info( "Delete Configuration via Restconf: {}", path );
+ transaction.removeConfigurationData( path );
+ return transaction.commit();
+ }
+
+ public void registerToListenDataChanges( final ListenerAdapter listener ) {
+ this.checkPreconditions();
+
+ if( listener.isListening() ) {
+ return;
+ }
+
+ InstanceIdentifier path = listener.getPath();
+ final ListenerRegistration<DataChangeListener> registration =
+ dataService.registerDataChangeListener( path, listener );
+
+ listener.setRegistration( registration );
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.restconf.impl
-
-import javax.ws.rs.core.Response
-import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.core.api.mount.MountInstance
-import org.opendaylight.controller.sal.rest.impl.RestconfProvider
-import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter
-import org.opendaylight.yangtools.yang.common.QName
-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.LoggerFactory
-
-class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
-
-
- val static LOG = LoggerFactory.getLogger(BrokerFacade)
- val static BrokerFacade INSTANCE = new BrokerFacade
-
- @Property
- private ConsumerSession context;
-
- @Property
- private DataBrokerService dataService;
-
- private new() {
- if (INSTANCE !== null) {
- throw new IllegalStateException("Already instantiated");
- }
- }
-
- def static BrokerFacade getInstance() {
- return INSTANCE
- }
-
- private def void checkPreconditions() {
- if (context === null || dataService === null) {
- throw new ResponseException(Response.Status.SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
- }
- }
-
- override readConfigurationData(InstanceIdentifier path) {
- checkPreconditions
- LOG.trace("Read Configuration via Restconf: {}", path)
- return dataService.readConfigurationData(path);
- }
-
- def readConfigurationDataBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path) {
- checkPreconditions
- LOG.trace("Read Configuration via Restconf: {}", path)
- return mountPoint.readConfigurationData(path);
- }
-
- override readOperationalData(InstanceIdentifier path) {
- checkPreconditions
- LOG.trace("Read Operational via Restconf: {}", path)
- return dataService.readOperationalData(path);
- }
-
- def readOperationalDataBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path) {
- checkPreconditions
- LOG.trace("Read Operational via Restconf: {}", path)
- return mountPoint.readOperationalData(path);
- }
-
- def RpcResult<CompositeNode> invokeRpc(QName type, CompositeNode payload) {
- checkPreconditions
- val future = context.rpc(type, payload);
- return future.get;
- }
-
- def commitConfigurationDataPut(InstanceIdentifier path, CompositeNode payload) {
- checkPreconditions
- val transaction = dataService.beginTransaction;
- LOG.trace("Put Configuration via Restconf: {}", path)
- transaction.putConfigurationData(path, payload);
- return transaction.commit
- }
-
- def commitConfigurationDataPutBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path, CompositeNode payload) {
- checkPreconditions
- val transaction = mountPoint.beginTransaction;
- LOG.trace("Put Configuration via Restconf: {}", path)
- transaction.putConfigurationData(path, payload);
- return transaction.commit
- }
-
- def commitConfigurationDataPost(InstanceIdentifier path, CompositeNode payload) {
- checkPreconditions
- val transaction = dataService.beginTransaction;
- transaction.putConfigurationData(path, payload);
- if (payload == transaction.createdConfigurationData.get(path)) {
- LOG.trace("Post Configuration via Restconf: {}", path)
- return transaction.commit
- }
- LOG.trace("Post Configuration via Restconf was not executed because data already exists: {}", path)
- return null;
- }
-
- def commitConfigurationDataPostBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path, CompositeNode payload) {
- checkPreconditions
- val transaction = mountPoint.beginTransaction;
- transaction.putConfigurationData(path, payload);
- if (payload == transaction.createdConfigurationData.get(path)) {
- LOG.trace("Post Configuration via Restconf: {}", path)
- return transaction.commit
- }
- LOG.trace("Post Configuration via Restconf was not executed because data already exists: {}", path)
- return null;
- }
-
- def commitConfigurationDataDelete(InstanceIdentifier path) {
- checkPreconditions
- val transaction = dataService.beginTransaction;
- LOG.info("Delete Configuration via Restconf: {}", path)
- transaction.removeConfigurationData(path)
- return transaction.commit
- }
-
- def commitConfigurationDataDeleteBehindMountPoint(MountInstance mountPoint, InstanceIdentifier path) {
- checkPreconditions
- val transaction = mountPoint.beginTransaction;
- LOG.info("Delete Configuration via Restconf: {}", path)
- transaction.removeConfigurationData(path)
- return transaction.commit
- }
-
- def registerToListenDataChanges(ListenerAdapter listener) {
- checkPreconditions
- if (listener.listening) {
- return;
- }
- val registration = dataService.registerDataChangeListener(listener.path, listener)
- listener.setRegistration(registration)
- }
-
-}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.restconf.impl;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+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.BiMap;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.sal.rest.impl.RestUtil;
+import org.opendaylight.controller.sal.rest.impl.RestconfProvider;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.restconf.impl.RestCodec;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ControllerContext implements SchemaContextListener {
+ private final static Logger LOG = LoggerFactory.getLogger( ControllerContext.class );
+
+ private final static ControllerContext INSTANCE = new ControllerContext();
+
+ private final static String NULL_VALUE = "null";
+
+ private final static String MOUNT_MODULE = "yang-ext";
+
+ private final static String MOUNT_NODE = "mount";
+
+ public final static String MOUNT = "yang-ext:mount";
+
+ private final static String URI_ENCODING_CHAR_SET = "ISO-8859-1";
+
+ private final BiMap<URI, String> uriToModuleName = HashBiMap.<URI, String> create();
+
+ private final Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
+
+ private final Map<QName, RpcDefinition> qnameToRpc = new ConcurrentHashMap<>();
+
+ private volatile SchemaContext globalSchema;
+ private volatile MountService mountService;
+
+ public void setGlobalSchema( final SchemaContext globalSchema ) {
+ this.globalSchema = globalSchema;
+ }
+
+ public void setMountService( final MountService mountService ) {
+ this.mountService = mountService;
+ }
+
+ private ControllerContext() {
+ }
+
+ public static ControllerContext getInstance() {
+ return ControllerContext.INSTANCE;
+ }
+
+ private void checkPreconditions() {
+ if( globalSchema == null ) {
+ throw new ResponseException( Status.SERVICE_UNAVAILABLE, RestconfProvider.NOT_INITALIZED_MSG );
+ }
+ }
+
+ public void setSchemas( final SchemaContext schemas ) {
+ this.onGlobalContextUpdated( schemas );
+ }
+
+ public InstanceIdWithSchemaNode toInstanceIdentifier( final String restconfInstance ) {
+ return this.toIdentifier( restconfInstance, false );
+ }
+
+ public InstanceIdWithSchemaNode toMountPointIdentifier( final String restconfInstance ) {
+ return this.toIdentifier( restconfInstance, true );
+ }
+
+ private InstanceIdWithSchemaNode toIdentifier( final String restconfInstance,
+ final boolean toMountPointIdentifier ) {
+ this.checkPreconditions();
+
+ Iterable<String> split = Splitter.on( "/" ).split( restconfInstance );
+ final ArrayList<String> encodedPathArgs = Lists.<String> newArrayList( split );
+ final List<String> pathArgs = this.urlPathArgsDecode( encodedPathArgs );
+ this.omitFirstAndLastEmptyString( pathArgs );
+ if( pathArgs.isEmpty() ) {
+ return null;
+ }
+
+ String first = pathArgs.iterator().next();
+ final String startModule = ControllerContext.toModuleName( first );
+ if( startModule == null ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "First node in URI has to be in format \"moduleName:nodeName\"" );
+ }
+
+ InstanceIdentifierBuilder builder = InstanceIdentifier.builder();
+ Module latestModule = this.getLatestModule( globalSchema, startModule );
+ InstanceIdWithSchemaNode iiWithSchemaNode = this.collectPathArguments( builder, pathArgs,
+ latestModule, null, toMountPointIdentifier );
+
+ if( iiWithSchemaNode == null ) {
+ throw new ResponseException( Status.BAD_REQUEST, "URI has bad format" );
+ }
+
+ return iiWithSchemaNode;
+ }
+
+ private List<String> omitFirstAndLastEmptyString( final List<String> list ) {
+ if( list.isEmpty() ) {
+ return list;
+ }
+
+ String head = list.iterator().next();
+ if( head.isEmpty() ) {
+ list.remove( 0 );
+ }
+
+ if( list.isEmpty() ) {
+ return list;
+ }
+
+ String last = list.get( list.size() - 1 );
+ if( last.isEmpty() ) {
+ list.remove( list.size() - 1 );
+ }
+
+ return list;
+ }
+
+ private Module getLatestModule( final SchemaContext schema, final String moduleName ) {
+ Preconditions.checkArgument( schema != null );
+ Preconditions.checkArgument( moduleName != null && !moduleName.isEmpty() );
+
+ Predicate<Module> filter = new Predicate<Module>() {
+ @Override
+ public boolean apply( Module m ) {
+ return Objects.equal( m.getName(), moduleName );
+ }
+ };
+
+ Iterable<Module> modules = Iterables.filter( schema.getModules(), filter );
+ return this.filterLatestModule( modules );
+ }
+
+ private Module filterLatestModule( final Iterable<Module> modules ) {
+ Module latestModule = modules.iterator().hasNext() ? modules.iterator().next() : null;
+ for( final Module module : modules ) {
+ if( module.getRevision().after( latestModule.getRevision() ) ) {
+ latestModule = module;
+ }
+ }
+ return latestModule;
+ }
+
+ public Module findModuleByName( final String moduleName ) {
+ this.checkPreconditions();
+ Preconditions.checkArgument( moduleName != null && !moduleName.isEmpty() );
+ return this.getLatestModule( globalSchema, moduleName );
+ }
+
+ public Module findModuleByName( final MountInstance mountPoint, final String moduleName ) {
+ Preconditions.checkArgument( moduleName != null && mountPoint != null );
+
+ final SchemaContext mountPointSchema = mountPoint.getSchemaContext();
+ return mountPointSchema == null ? null : this.getLatestModule( mountPointSchema, moduleName );
+ }
+
+ public Module findModuleByNamespace( final URI namespace ) {
+ this.checkPreconditions();
+ Preconditions.checkArgument( namespace != null );
+
+ final Set<Module> moduleSchemas = globalSchema.findModuleByNamespace( namespace );
+ return moduleSchemas == null ? null : this.filterLatestModule( moduleSchemas );
+ }
+
+ public Module findModuleByNamespace( final MountInstance mountPoint, final URI namespace ) {
+ Preconditions.checkArgument( namespace != null && mountPoint != null );
+
+ final SchemaContext mountPointSchema = mountPoint.getSchemaContext();
+ Set<Module> moduleSchemas = mountPointSchema == null ? null :
+ mountPointSchema.findModuleByNamespace( namespace );
+ return moduleSchemas == null ? null : this.filterLatestModule( moduleSchemas );
+ }
+
+ public Module findModuleByNameAndRevision( final QName module ) {
+ this.checkPreconditions();
+ Preconditions.checkArgument( module != null && module.getLocalName() != null &&
+ module.getRevision() != null );
+
+ return globalSchema.findModuleByName( module.getLocalName(), module.getRevision() );
+ }
+
+ public Module findModuleByNameAndRevision( final MountInstance mountPoint, final QName module ) {
+ this.checkPreconditions();
+ Preconditions.checkArgument( module != null && module.getLocalName() != null &&
+ module.getRevision() != null && mountPoint != null );
+
+ SchemaContext schemaContext = mountPoint.getSchemaContext();
+ return schemaContext == null ? null :
+ schemaContext.findModuleByName( module.getLocalName(), module.getRevision() );
+ }
+
+ public DataNodeContainer getDataNodeContainerFor( final InstanceIdentifier path ) {
+ this.checkPreconditions();
+
+ final List<PathArgument> elements = path.getPath();
+ PathArgument head = elements.iterator().next();
+ final QName startQName = head.getNodeType();
+ final Module initialModule = globalSchema.findModuleByNamespaceAndRevision(
+ startQName.getNamespace(), startQName.getRevision() );
+ DataNodeContainer node = initialModule;
+ for( final PathArgument element : elements ) {
+ QName _nodeType = element.getNodeType();
+ final DataSchemaNode potentialNode = ControllerContext.childByQName( node, _nodeType );
+ if( potentialNode == null || !this.isListOrContainer( potentialNode ) ) {
+ return null;
+ }
+ node = (DataNodeContainer) potentialNode;
+ }
+
+ return node;
+ }
+
+ public String toFullRestconfIdentifier( final InstanceIdentifier path ) {
+ this.checkPreconditions();
+
+ final List<PathArgument> elements = path.getPath();
+ final StringBuilder builder = new StringBuilder();
+ PathArgument head = elements.iterator().next();
+ final QName startQName = head.getNodeType();
+ final Module initialModule = globalSchema.findModuleByNamespaceAndRevision(
+ startQName.getNamespace(), startQName.getRevision() );
+ DataNodeContainer node = initialModule;
+ for( final PathArgument element : elements ) {
+ QName _nodeType = element.getNodeType();
+ final DataSchemaNode potentialNode = ControllerContext.childByQName( node, _nodeType );
+ if( !this.isListOrContainer( potentialNode ) ) {
+ return null;
+ }
+ node = ((DataNodeContainer) potentialNode);
+ builder.append( this.convertToRestconfIdentifier( element, node ) );
+ }
+
+ return builder.toString();
+ }
+
+ public String findModuleNameByNamespace( final URI namespace ) {
+ this.checkPreconditions();
+
+ String moduleName = this.uriToModuleName.get( namespace );
+ if( moduleName == null ) {
+ final Module module = this.findModuleByNamespace( namespace );
+ if( module != null ) {
+ moduleName = module.getName();
+ this.uriToModuleName.put( namespace, moduleName );
+ }
+ }
+
+ return moduleName;
+ }
+
+ public String findModuleNameByNamespace( final MountInstance mountPoint, final URI namespace ) {
+ final Module module = this.findModuleByNamespace( mountPoint, namespace );
+ return module == null ? null : module.getName();
+ }
+
+ public URI findNamespaceByModuleName( final String moduleName ) {
+ URI namespace = this.moduleNameToUri.get( moduleName );
+ if( namespace == null ) {
+ Module module = this.findModuleByName( moduleName );
+ if( module != null ) {
+ URI _namespace = module.getNamespace();
+ namespace = _namespace;
+ this.uriToModuleName.put( namespace, moduleName );
+ }
+ }
+ return namespace;
+ }
+
+ public URI findNamespaceByModuleName( final MountInstance mountPoint, final String moduleName ) {
+ final Module module = this.findModuleByName( mountPoint, moduleName );
+ return module == null ? null : module.getNamespace();
+ }
+
+ public Set<Module> getAllModules( final MountInstance mountPoint ) {
+ this.checkPreconditions();
+
+ SchemaContext schemaContext = mountPoint == null ? null : mountPoint.getSchemaContext();
+ return schemaContext == null ? null : schemaContext.getModules();
+ }
+
+ public Set<Module> getAllModules() {
+ this.checkPreconditions();
+ return globalSchema.getModules();
+ }
+
+ public CharSequence toRestconfIdentifier( final QName qname ) {
+ this.checkPreconditions();
+
+ String module = this.uriToModuleName.get( qname.getNamespace() );
+ if( module == null ) {
+ final Module moduleSchema = globalSchema.findModuleByNamespaceAndRevision(
+ qname.getNamespace(), qname.getRevision() );
+ if( moduleSchema == null ) {
+ return null;
+ }
+
+ this.uriToModuleName.put( qname.getNamespace(), moduleSchema.getName() );
+ module = moduleSchema.getName();
+ }
+
+ StringBuilder builder = new StringBuilder();
+ builder.append( module );
+ builder.append( ":" );
+ builder.append( qname.getLocalName() );
+ return builder.toString();
+ }
+
+ public CharSequence toRestconfIdentifier( final MountInstance mountPoint, final QName qname ) {
+ if( mountPoint == null ) {
+ return null;
+ }
+
+ SchemaContext schemaContext = mountPoint.getSchemaContext();
+
+ final Module moduleSchema = schemaContext.findModuleByNamespaceAndRevision(
+ qname.getNamespace(), qname.getRevision() );
+ if( moduleSchema == null ) {
+ return null;
+ }
+
+ StringBuilder builder = new StringBuilder();
+ builder.append( moduleSchema.getName() );
+ builder.append( ":" );
+ builder.append( qname.getLocalName() );
+ return builder.toString();
+ }
+
+ private static DataSchemaNode childByQName( final ChoiceNode container, final QName name ) {
+ for( final ChoiceCaseNode caze : container.getCases() ) {
+ final DataSchemaNode ret = ControllerContext.childByQName( caze, name );
+ if( ret != null ) {
+ return ret;
+ }
+ }
+
+ return null;
+ }
+
+ private static DataSchemaNode childByQName( final ChoiceCaseNode container, final QName name ) {
+ return container.getDataChildByName( name );
+ }
+
+ private static DataSchemaNode childByQName( final ContainerSchemaNode container, final QName name ) {
+ return ControllerContext.dataNodeChildByQName( container, name );
+ }
+
+ private static DataSchemaNode childByQName( final ListSchemaNode container, final QName name ) {
+ return ControllerContext.dataNodeChildByQName( container, name );
+ }
+
+ private static DataSchemaNode childByQName( final Module container, final QName name ) {
+ return ControllerContext.dataNodeChildByQName( container, name );
+ }
+
+ private static DataSchemaNode childByQName( final DataSchemaNode container, final QName name ) {
+ return null;
+ }
+
+ private static DataSchemaNode dataNodeChildByQName( final DataNodeContainer container, final QName name ) {
+ DataSchemaNode ret = container.getDataChildByName( name );
+ if( ret == null ) {
+ for( final DataSchemaNode node : container.getChildNodes() ) {
+ if( (node instanceof ChoiceCaseNode) ) {
+ final ChoiceCaseNode caseNode = ((ChoiceCaseNode) node);
+ DataSchemaNode childByQName = ControllerContext.childByQName( caseNode, name );
+ if( childByQName != null ) {
+ return childByQName;
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
+ private String toUriString( final Object object ) throws UnsupportedEncodingException {
+ return object == null ? "" :
+ URLEncoder.encode( object.toString(), ControllerContext.URI_ENCODING_CHAR_SET );
+ }
+
+ private InstanceIdWithSchemaNode collectPathArguments( final InstanceIdentifierBuilder builder,
+ final List<String> strings, final DataNodeContainer parentNode, final MountInstance mountPoint,
+ final boolean returnJustMountPoint ) {
+ Preconditions.<List<String>> checkNotNull( strings );
+
+ if( parentNode == null ) {
+ return null;
+ }
+
+ if( strings.isEmpty() ) {
+ return new InstanceIdWithSchemaNode( builder.toInstance(),
+ ((DataSchemaNode) parentNode), mountPoint );
+ }
+
+ String head = strings.iterator().next();
+ final String nodeName = this.toNodeName( head );
+ final String moduleName = ControllerContext.toModuleName( head );
+
+ DataSchemaNode targetNode = null;
+ if( !Strings.isNullOrEmpty( moduleName ) ) {
+ if( Objects.equal( moduleName, ControllerContext.MOUNT_MODULE ) &&
+ Objects.equal( nodeName, ControllerContext.MOUNT_NODE ) ) {
+ if( mountPoint != null ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "Restconf supports just one mount point in URI." );
+ }
+
+ if( mountService == null ) {
+ throw new ResponseException( Status.SERVICE_UNAVAILABLE,
+ "MountService was not found. Finding behind mount points does not work." );
+ }
+
+ final InstanceIdentifier partialPath = builder.toInstance();
+ final MountInstance mount = mountService.getMountPoint( partialPath );
+ if( mount == null ) {
+ LOG.debug( "Instance identifier to missing mount point: {}", partialPath );
+ throw new ResponseException( Status.BAD_REQUEST,
+ "Mount point does not exist." );
+ }
+
+ final SchemaContext mountPointSchema = mount.getSchemaContext();
+ if( mountPointSchema == null ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "Mount point does not contain any schema with modules." );
+ }
+
+ if( returnJustMountPoint ) {
+ InstanceIdentifier instance = InstanceIdentifier.builder().toInstance();
+ return new InstanceIdWithSchemaNode( instance, mountPointSchema, mount );
+ }
+
+ if( strings.size() == 1 ) {
+ InstanceIdentifier instance = InstanceIdentifier.builder().toInstance();
+ return new InstanceIdWithSchemaNode( instance, mountPointSchema, mount );
+ }
+
+ final String moduleNameBehindMountPoint = toModuleName( strings.get( 1 ) );
+ if( moduleNameBehindMountPoint == null ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "First node after mount point in URI has to be in format \"moduleName:nodeName\"" );
+ }
+
+ final Module moduleBehindMountPoint = this.getLatestModule( mountPointSchema,
+ moduleNameBehindMountPoint );
+ if( moduleBehindMountPoint == null ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "URI has bad format. \"" + moduleName +
+ "\" module does not exist in mount point." );
+ }
+
+ List<String> subList = strings.subList( 1, strings.size() );
+ return this.collectPathArguments( InstanceIdentifier.builder(), subList, moduleBehindMountPoint,
+ mount, returnJustMountPoint );
+ }
+
+ Module module = null;
+ if( mountPoint == null ) {
+ module = this.getLatestModule( globalSchema, moduleName );
+ if( module == null ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "URI has bad format. \"" + moduleName + "\" module does not exist." );
+ }
+ }
+ else {
+ SchemaContext schemaContext = mountPoint.getSchemaContext();
+ module = schemaContext == null ? null :
+ this.getLatestModule( schemaContext, moduleName );
+ if( module == null ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "URI has bad format. \"" + moduleName +
+ "\" module does not exist in mount point." );
+ }
+ }
+
+ targetNode = this.findInstanceDataChildByNameAndNamespace(
+ parentNode, nodeName, module.getNamespace() );;
+ if( targetNode == null ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "URI has bad format. Possible reasons:\n" +
+ "1. \"" + head + "\" was not found in parent data node.\n" +
+ "2. \"" + head + "\" is behind mount point. Then it should be in format \"/" +
+ MOUNT + "/" + head + "\"." );
+ }
+ } else {
+ final List<DataSchemaNode> potentialSchemaNodes =
+ this.findInstanceDataChildrenByName( parentNode, nodeName );
+ if( potentialSchemaNodes.size() > 1 ) {
+ final StringBuilder strBuilder = new StringBuilder();
+ for( final DataSchemaNode potentialNodeSchema : potentialSchemaNodes ) {
+ strBuilder.append( " " )
+ .append( potentialNodeSchema.getQName().getNamespace() )
+ .append( "\n" );
+ }
+
+ throw new ResponseException( Status.BAD_REQUEST,
+ "URI has bad format. Node \"" + nodeName +
+ "\" is added as augment from more than one module. " +
+ "Therefore the node must have module name and it has to be in format \"moduleName:nodeName\"." +
+ "\nThe node is added as augment from modules with namespaces:\n" +
+ strBuilder.toString() );
+ }
+
+ if( potentialSchemaNodes.isEmpty() ) {
+ throw new ResponseException( Status.BAD_REQUEST, "URI has bad format. \"" + nodeName +
+ "\" was not found in parent data node.\n" );
+ }
+
+ targetNode = potentialSchemaNodes.iterator().next();
+ }
+
+ if( !this.isListOrContainer( targetNode ) ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "URI has bad format. Node \"" + head +
+ "\" must be Container or List yang type." );
+ }
+
+ int consumed = 1;
+ if( (targetNode instanceof ListSchemaNode) ) {
+ final ListSchemaNode listNode = ((ListSchemaNode) targetNode);
+ final int keysSize = listNode.getKeyDefinition().size();
+ if( (strings.size() - consumed) < keysSize ) {
+ throw new ResponseException( Status.BAD_REQUEST, "Missing key for list \"" +
+ listNode.getQName().getLocalName() + "\"." );
+ }
+
+ final List<String> uriKeyValues = strings.subList( consumed, consumed + keysSize );
+ final HashMap<QName, Object> keyValues = new HashMap<QName, Object>();
+ int i = 0;
+ for( final QName key : listNode.getKeyDefinition() ) {
+ {
+ final String uriKeyValue = uriKeyValues.get( i );
+ if( uriKeyValue.equals( NULL_VALUE ) ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "URI has bad format. List \"" + listNode.getQName().getLocalName() +
+ "\" cannot contain \"null\" value as a key." );
+ }
+
+ this.addKeyValue( keyValues, listNode.getDataChildByName( key ),
+ uriKeyValue, mountPoint );
+ i++;
+ }
+ }
+
+ consumed = consumed + i;
+ builder.nodeWithKey( targetNode.getQName(), keyValues );
+ }
+ else {
+ builder.node( targetNode.getQName() );
+ }
+
+ if( (targetNode instanceof DataNodeContainer) ) {
+ final List<String> remaining = strings.subList( consumed, strings.size() );
+ return this.collectPathArguments( builder, remaining,
+ ((DataNodeContainer) targetNode), mountPoint, returnJustMountPoint );
+ }
+
+ return new InstanceIdWithSchemaNode( builder.toInstance(), targetNode, mountPoint );
+ }
+
+ public DataSchemaNode findInstanceDataChildByNameAndNamespace( final DataNodeContainer container,
+ final String name, final URI namespace ) {
+ Preconditions.<URI> checkNotNull( namespace );
+
+ final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName( container, name );
+
+ Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
+ @Override
+ public boolean apply( DataSchemaNode node ) {
+ return Objects.equal( node.getQName().getNamespace(), namespace );
+ }
+ };
+
+ Iterable<DataSchemaNode> result = Iterables.filter( potentialSchemaNodes, filter );
+ return Iterables.getFirst( result, null );
+ }
+
+ public List<DataSchemaNode> findInstanceDataChildrenByName( final DataNodeContainer container,
+ final String name ) {
+ Preconditions.<DataNodeContainer> checkNotNull( container );
+ Preconditions.<String> checkNotNull( name );
+
+ List<DataSchemaNode> instantiatedDataNodeContainers = new ArrayList<DataSchemaNode>();
+ this.collectInstanceDataNodeContainers( instantiatedDataNodeContainers, container, name );
+ return instantiatedDataNodeContainers;
+ }
+
+ private void collectInstanceDataNodeContainers( final List<DataSchemaNode> potentialSchemaNodes,
+ final DataNodeContainer container, final String name ) {
+
+ Set<DataSchemaNode> childNodes = container.getChildNodes();
+
+ Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
+ @Override
+ public boolean apply( DataSchemaNode node ) {
+ return Objects.equal( node.getQName().getLocalName(), name );
+ }
+ };
+
+ Iterable<DataSchemaNode> nodes = Iterables.filter( childNodes, filter );
+
+ // Can't combine this loop with the filter above because the filter is lazily-applied
+ // by Iterables.filter.
+ for( final DataSchemaNode potentialNode : nodes ) {
+ if( this.isInstantiatedDataSchema( potentialNode ) ) {
+ potentialSchemaNodes.add( potentialNode );
+ }
+ }
+
+ Iterable<ChoiceNode> choiceNodes = Iterables.<ChoiceNode> filter( container.getChildNodes(),
+ ChoiceNode.class );
+
+ final Function<ChoiceNode, Set<ChoiceCaseNode>> choiceFunction =
+ new Function<ChoiceNode, Set<ChoiceCaseNode>>() {
+ @Override
+ public Set<ChoiceCaseNode> apply( final ChoiceNode node ) {
+ return node.getCases();
+ }
+ };
+
+ Iterable<Set<ChoiceCaseNode>> map = Iterables.<ChoiceNode, Set<ChoiceCaseNode>> transform(
+ choiceNodes, choiceFunction );
+
+ final Iterable<ChoiceCaseNode> allCases = Iterables.<ChoiceCaseNode> concat( map );
+ for( final ChoiceCaseNode caze : allCases ) {
+ this.collectInstanceDataNodeContainers( potentialSchemaNodes, caze, name );
+ }
+ }
+
+ public boolean isInstantiatedDataSchema( final DataSchemaNode node ) {
+ return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode ||
+ node instanceof ContainerSchemaNode || node instanceof ListSchemaNode;
+ }
+
+ private void addKeyValue( final HashMap<QName, Object> map, final DataSchemaNode node,
+ final String uriValue, final MountInstance mountPoint ) {
+ Preconditions.<String> checkNotNull( uriValue );
+ Preconditions.checkArgument( (node instanceof LeafSchemaNode) );
+
+ final String urlDecoded = urlPathArgDecode( uriValue );
+ final TypeDefinition<? extends Object> typedef = ((LeafSchemaNode) node).getType();
+ Codec<Object, Object> codec = RestCodec.from( typedef, mountPoint );
+
+ Object decoded = codec == null ? null : codec.deserialize( urlDecoded );
+ String additionalInfo = "";
+ if( decoded == null ) {
+ TypeDefinition<? extends Object> baseType = RestUtil.resolveBaseTypeFrom( typedef );
+ if( (baseType instanceof IdentityrefTypeDefinition) ) {
+ decoded = this.toQName( urlDecoded );
+ additionalInfo = "For key which is of type identityref it should be in format module_name:identity_name.";
+ }
+ }
+
+ if( decoded == null ) {
+ throw new ResponseException( Status.BAD_REQUEST, uriValue + " from URI can\'t be resolved. " +
+ additionalInfo );
+ }
+
+ map.put( node.getQName(), decoded );
+ }
+
+ private static String toModuleName( final String str ) {
+ Preconditions.<String> checkNotNull( str );
+ if( str.contains( ":" ) ) {
+ final String[] args = str.split( ":" );
+ if( args.length == 2 ) {
+ return args[0];
+ }
+ }
+ return null;
+ }
+
+ private String toNodeName( final String str ) {
+ if( str.contains( ":" ) ) {
+ final String[] args = str.split( ":" );
+ if( args.length == 2 ) {
+ return args[1];
+ }
+ }
+ return str;
+ }
+
+ private QName toQName( final String name ) {
+ final String module = toModuleName( name );
+ final String node = this.toNodeName( name );
+ Set<Module> modules = globalSchema.getModules();
+
+ final Comparator<Module> comparator = new Comparator<Module>() {
+ @Override
+ public int compare( final Module o1, final Module o2 ) {
+ return o1.getRevision().compareTo( o2.getRevision() );
+ }
+ };
+
+ List<Module> sorted = new ArrayList<Module>( modules );
+ Collections.<Module> sort( new ArrayList<Module>( modules ), comparator );
+
+ final Function<Module, QName> transform = new Function<Module, QName>() {
+ @Override
+ public QName apply( final Module m ) {
+ return QName.create( m.getNamespace(), m.getRevision(), m.getName() );
+ }
+ };
+
+ final Predicate<QName> findFirst = new Predicate<QName>() {
+ @Override
+ public boolean apply( final QName qn ) {
+ return Objects.equal( module, qn.getLocalName() );
+ }
+ };
+
+ Optional<QName> namespace = FluentIterable.from( sorted )
+ .transform( transform )
+ .firstMatch( findFirst );
+ return namespace.isPresent() ? QName.create( namespace.get(), node ) : null;
+ }
+
+ private boolean isListOrContainer( final DataSchemaNode node ) {
+ return node instanceof ListSchemaNode || node instanceof ContainerSchemaNode;
+ }
+
+ public RpcDefinition getRpcDefinition( final String name ) {
+ final QName validName = this.toQName( name );
+ return validName == null ? null : this.qnameToRpc.get( validName );
+ }
+
+ @Override
+ public void onGlobalContextUpdated( final SchemaContext context ) {
+ if( context != null ) {
+ this.qnameToRpc.clear();
+ this.setGlobalSchema( context );
+ Set<RpcDefinition> _operations = context.getOperations();
+ for( final RpcDefinition operation : _operations ) {
+ {
+ this.qnameToRpc.put( operation.getQName(), operation );
+ }
+ }
+ }
+ }
+
+ public List<String> urlPathArgsDecode( final List<String> strings ) {
+ try {
+ List<String> decodedPathArgs = new ArrayList<String>();
+ for( final String pathArg : strings ) {
+ String _decode = URLDecoder.decode( pathArg, URI_ENCODING_CHAR_SET );
+ decodedPathArgs.add( _decode );
+ }
+ return decodedPathArgs;
+ }
+ catch( UnsupportedEncodingException e ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "Invalid URL path '" + strings + "': " + e.getMessage() );
+ }
+ }
+
+ public String urlPathArgDecode( final String pathArg ) {
+ if( pathArg != null ) {
+ try {
+ return URLDecoder.decode( pathArg, URI_ENCODING_CHAR_SET );
+ }
+ catch( UnsupportedEncodingException e ) {
+ throw new ResponseException( Status.BAD_REQUEST,
+ "Invalid URL path arg '" + pathArg + "': " + e.getMessage() );
+ }
+ }
+
+ return null;
+ }
+
+ private CharSequence convertToRestconfIdentifier( final PathArgument argument,
+ final DataNodeContainer node ) {
+ if( argument instanceof NodeIdentifier && node instanceof ContainerSchemaNode ) {
+ return convertToRestconfIdentifier( (NodeIdentifier) argument, (ContainerSchemaNode) node );
+ }
+ else if( argument instanceof NodeIdentifierWithPredicates && node instanceof ListSchemaNode ) {
+ return convertToRestconfIdentifier( (NodeIdentifierWithPredicates) argument, (ListSchemaNode) node );
+ }
+ else if( argument != null && node != null ) {
+ throw new IllegalArgumentException(
+ "Conversion of generic path argument is not supported" );
+ }
+ else {
+ throw new IllegalArgumentException( "Unhandled parameter types: "
+ + Arrays.<Object> asList( argument, node ).toString() );
+ }
+ }
+
+ private CharSequence convertToRestconfIdentifier( final NodeIdentifier argument,
+ final ContainerSchemaNode node ) {
+ StringBuilder builder = new StringBuilder();
+ builder.append( "/" );
+ QName nodeType = argument.getNodeType();
+ builder.append( this.toRestconfIdentifier( nodeType ) );
+ return builder.toString();
+ }
+
+ private CharSequence convertToRestconfIdentifier( final NodeIdentifierWithPredicates argument,
+ final ListSchemaNode node ) {
+ QName nodeType = argument.getNodeType();
+ final CharSequence nodeIdentifier = this.toRestconfIdentifier( nodeType );
+ final Map<QName, Object> keyValues = argument.getKeyValues();
+
+ StringBuilder builder = new StringBuilder();
+ builder.append( "/" );
+ builder.append( nodeIdentifier );
+ builder.append( "/" );
+
+ List<QName> keyDefinition = node.getKeyDefinition();
+ boolean hasElements = false;
+ for( final QName key : keyDefinition ) {
+ if( !hasElements ) {
+ hasElements = true;
+ }
+ else {
+ builder.append( "/" );
+ }
+
+ try {
+ builder.append( this.toUriString( keyValues.get( key ) ) );
+ } catch( UnsupportedEncodingException e ) {
+ LOG.error( "Error parsing URI: " + keyValues.get( key ), e );
+ return null;
+ }
+ }
+
+ return builder.toString();
+ }
+
+ private static DataSchemaNode childByQName( final Object container, final QName name ) {
+ if( container instanceof ChoiceCaseNode ) {
+ return childByQName( (ChoiceCaseNode) container, name );
+ }
+ else if( container instanceof ChoiceNode ) {
+ return childByQName( (ChoiceNode) container, name );
+ }
+ else if( container instanceof ContainerSchemaNode ) {
+ return childByQName( (ContainerSchemaNode) container, name );
+ }
+ else if( container instanceof ListSchemaNode ) {
+ return childByQName( (ListSchemaNode) container, name );
+ }
+ else if( container instanceof DataSchemaNode ) {
+ return childByQName( (DataSchemaNode) container, name );
+ }
+ else if( container instanceof Module ) {
+ return childByQName( (Module) container, name );
+ }
+ else {
+ throw new IllegalArgumentException( "Unhandled parameter types: "
+ + Arrays.<Object> asList( container, name ).toString() );
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.restconf.impl
-
-import com.google.common.base.Preconditions
-import com.google.common.base.Splitter
-import com.google.common.collect.BiMap
-import com.google.common.collect.FluentIterable
-import com.google.common.collect.HashBiMap
-import com.google.common.collect.Lists
-import java.net.URI
-import java.net.URLDecoder
-import java.net.URLEncoder
-import java.util.ArrayList
-import java.util.HashMap
-import java.util.List
-import java.util.Map
-import java.util.concurrent.ConcurrentHashMap
-import org.opendaylight.controller.sal.core.api.mount.MountInstance
-import org.opendaylight.controller.sal.core.api.mount.MountService
-import org.opendaylight.controller.sal.rest.impl.RestUtil
-import org.opendaylight.controller.sal.rest.impl.RestconfProvider
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.Module
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
-import org.slf4j.LoggerFactory
-
-import static com.google.common.base.Preconditions.*
-import static javax.ws.rs.core.Response.Status.*
-
-class ControllerContext implements SchemaContextListener {
- val static LOG = LoggerFactory.getLogger(ControllerContext)
- val static ControllerContext INSTANCE = new ControllerContext
- val static NULL_VALUE = "null"
- val static MOUNT_MODULE = "yang-ext"
- val static MOUNT_NODE = "mount"
- public val static MOUNT = "yang-ext:mount"
- val static URI_ENCODING_CHAR_SET = "ISO-8859-1"
- val static URI_SLASH_PLACEHOLDER = "%2F";
-
- @Property
- var SchemaContext globalSchema;
-
- @Property
- var MountService mountService;
-
- private val BiMap<URI, String> uriToModuleName = HashBiMap.create();
- private val Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
- private val Map<QName, RpcDefinition> qnameToRpc = new ConcurrentHashMap();
-
- private new() {
- if (INSTANCE !== null) {
- throw new IllegalStateException("Already instantiated");
- }
- }
-
- static def getInstance() {
- return INSTANCE
- }
-
- private def void checkPreconditions() {
- if (globalSchema === null) {
- throw new ResponseException(SERVICE_UNAVAILABLE, RestconfProvider::NOT_INITALIZED_MSG)
- }
- }
-
- def setSchemas(SchemaContext schemas) {
- onGlobalContextUpdated(schemas)
- }
-
- def InstanceIdWithSchemaNode toInstanceIdentifier(String restconfInstance) {
- return restconfInstance.toIdentifier(false)
- }
-
- def InstanceIdWithSchemaNode toMountPointIdentifier(String restconfInstance) {
- return restconfInstance.toIdentifier(true)
- }
-
- private def InstanceIdWithSchemaNode toIdentifier(String restconfInstance, boolean toMountPointIdentifier) {
- checkPreconditions
- val encodedPathArgs = Lists.newArrayList(Splitter.on("/").split(restconfInstance))
- val pathArgs = urlPathArgsDecode(encodedPathArgs)
- pathArgs.omitFirstAndLastEmptyString
- if (pathArgs.empty) {
- return null;
- }
- val startModule = pathArgs.head.toModuleName();
- if (startModule === null) {
- throw new ResponseException(BAD_REQUEST, "First node in URI has to be in format \"moduleName:nodeName\"")
- }
- var InstanceIdWithSchemaNode iiWithSchemaNode = null;
- if (toMountPointIdentifier) {
- iiWithSchemaNode = collectPathArguments(InstanceIdentifier.builder(), pathArgs,
- globalSchema.getLatestModule(startModule), null, true);
- } else {
- iiWithSchemaNode = collectPathArguments(InstanceIdentifier.builder(), pathArgs,
- globalSchema.getLatestModule(startModule), null, false);
- }
- if (iiWithSchemaNode === null) {
- throw new ResponseException(BAD_REQUEST, "URI has bad format")
- }
- return iiWithSchemaNode
- }
-
- private def omitFirstAndLastEmptyString(List<String> list) {
- if (list.empty) {
- return list;
- }
- if (list.head.empty) {
- list.remove(0)
- }
- if (list.empty) {
- return list;
- }
- if (list.last.empty) {
- list.remove(list.indexOf(list.last))
- }
- return list;
- }
-
- private def getLatestModule(SchemaContext schema, String moduleName) {
- checkArgument(schema !== null);
- checkArgument(moduleName !== null && !moduleName.empty)
- val modules = schema.modules.filter[m|m.name == moduleName]
- return modules.filterLatestModule
- }
-
- private def filterLatestModule(Iterable<Module> modules) {
- var latestModule = modules.head
- for (module : modules) {
- if (module.revision.after(latestModule.revision)) {
- latestModule = module
- }
- }
- return latestModule
- }
-
- def findModuleByName(String moduleName) {
- checkPreconditions
- checkArgument(moduleName !== null && !moduleName.empty)
- return globalSchema.getLatestModule(moduleName)
- }
-
- def findModuleByName(MountInstance mountPoint, String moduleName) {
- checkArgument(moduleName !== null && mountPoint !== null)
- val mountPointSchema = mountPoint.schemaContext;
- return mountPointSchema?.getLatestModule(moduleName);
- }
-
- def findModuleByNamespace(URI namespace) {
- checkPreconditions
- checkArgument(namespace !== null)
- val moduleSchemas = globalSchema.findModuleByNamespace(namespace)
- return moduleSchemas?.filterLatestModule
- }
-
- def findModuleByNamespace(MountInstance mountPoint, URI namespace) {
- checkArgument(namespace !== null && mountPoint !== null)
- val mountPointSchema = mountPoint.schemaContext;
- val moduleSchemas = mountPointSchema?.findModuleByNamespace(namespace)
- return moduleSchemas?.filterLatestModule
- }
-
- def findModuleByNameAndRevision(QName module) {
- checkPreconditions
- checkArgument(module !== null && module.localName !== null && module.revision !== null)
- return globalSchema.findModuleByName(module.localName, module.revision)
- }
-
- def findModuleByNameAndRevision(MountInstance mountPoint, QName module) {
- checkPreconditions
- checkArgument(module !== null && module.localName !== null && module.revision !== null && mountPoint !== null)
- return mountPoint.schemaContext?.findModuleByName(module.localName, module.revision)
- }
-
- def getDataNodeContainerFor(InstanceIdentifier path) {
- checkPreconditions
- val elements = path.path;
- val startQName = elements.head.nodeType;
- val initialModule = globalSchema.findModuleByNamespaceAndRevision(startQName.namespace, startQName.revision)
- var node = initialModule as DataNodeContainer;
- for (element : elements) {
- val potentialNode = node.childByQName(element.nodeType);
- if (potentialNode === null || !potentialNode.listOrContainer) {
- return null
- }
- node = potentialNode as DataNodeContainer
- }
- return node
- }
-
- def String toFullRestconfIdentifier(InstanceIdentifier path) {
- checkPreconditions
- val elements = path.path;
- val ret = new StringBuilder();
- val startQName = elements.head.nodeType;
- val initialModule = globalSchema.findModuleByNamespaceAndRevision(startQName.namespace, startQName.revision)
- var node = initialModule as DataNodeContainer;
- for (element : elements) {
- val potentialNode = node.childByQName(element.nodeType);
- if (!potentialNode.listOrContainer) {
- return null
- }
- node = potentialNode as DataNodeContainer
- ret.append(element.convertToRestconfIdentifier(node));
- }
- return ret.toString
- }
-
- private def dispatch CharSequence convertToRestconfIdentifier(NodeIdentifier argument, ContainerSchemaNode node) {
- '''/«argument.nodeType.toRestconfIdentifier()»'''
- }
-
- private def dispatch CharSequence convertToRestconfIdentifier(NodeIdentifierWithPredicates argument, ListSchemaNode node) {
- val nodeIdentifier = argument.nodeType.toRestconfIdentifier();
- val keyValues = argument.keyValues;
- return '''/«nodeIdentifier»/«FOR key : node.keyDefinition SEPARATOR "/"»«keyValues.get(key).toUriString»«ENDFOR»'''
- }
-
- private def dispatch CharSequence convertToRestconfIdentifier(PathArgument argument, DataNodeContainer node) {
- throw new IllegalArgumentException("Conversion of generic path argument is not supported");
- }
-
- def findModuleNameByNamespace(URI namespace) {
- checkPreconditions
- var moduleName = uriToModuleName.get(namespace)
- if (moduleName === null) {
- val module = findModuleByNamespace(namespace)
- if (module === null) return null
- moduleName = module.name
- uriToModuleName.put(namespace, moduleName)
- }
- return moduleName
- }
-
- def findModuleNameByNamespace(MountInstance mountPoint, URI namespace) {
- val module = mountPoint.findModuleByNamespace(namespace);
- return module?.name
- }
-
- def findNamespaceByModuleName(String moduleName) {
- var namespace = moduleNameToUri.get(moduleName)
- if (namespace === null) {
- var module = findModuleByName(moduleName)
- if(module === null) return null
- namespace = module.namespace
- uriToModuleName.put(namespace, moduleName)
- }
- return namespace
- }
-
- def findNamespaceByModuleName(MountInstance mountPoint, String moduleName) {
- val module = mountPoint.findModuleByName(moduleName)
- return module?.namespace
- }
-
- def getAllModules(MountInstance mountPoint) {
- checkPreconditions
- return mountPoint?.schemaContext?.modules
- }
-
- def getAllModules() {
- checkPreconditions
- return globalSchema.modules
- }
-
- def CharSequence toRestconfIdentifier(QName qname) {
- checkPreconditions
- var module = uriToModuleName.get(qname.namespace)
- if (module === null) {
- val moduleSchema = globalSchema.findModuleByNamespaceAndRevision(qname.namespace, qname.revision);
- if(moduleSchema === null) return null
- uriToModuleName.put(qname.namespace, moduleSchema.name)
- module = moduleSchema.name;
- }
- return '''«module»:«qname.localName»''';
- }
-
- def CharSequence toRestconfIdentifier(MountInstance mountPoint, QName qname) {
- val moduleSchema = mountPoint?.schemaContext.findModuleByNamespaceAndRevision(qname.namespace, qname.revision);
- if(moduleSchema === null) return null
- val module = moduleSchema.name;
- return '''«module»:«qname.localName»''';
- }
-
- private static dispatch def DataSchemaNode childByQName(ChoiceNode container, QName name) {
- for (caze : container.cases) {
- val ret = caze.childByQName(name)
- if (ret !== null) {
- return ret;
- }
- }
- return null;
- }
-
- private static dispatch def DataSchemaNode childByQName(ChoiceCaseNode container, QName name) {
- val ret = container.getDataChildByName(name);
- return ret;
- }
-
- private static dispatch def DataSchemaNode childByQName(ContainerSchemaNode container, QName name) {
- return container.dataNodeChildByQName(name);
- }
-
- private static dispatch def DataSchemaNode childByQName(ListSchemaNode container, QName name) {
- return container.dataNodeChildByQName(name);
- }
-
- private static dispatch def DataSchemaNode childByQName(Module container, QName name) {
- return container.dataNodeChildByQName(name);
- }
-
- private static dispatch def DataSchemaNode childByQName(DataSchemaNode container, QName name) {
- return null;
- }
-
- private static def DataSchemaNode dataNodeChildByQName(DataNodeContainer container, QName name) {
- var ret = container.getDataChildByName(name);
- if (ret === null) {
-
- // Find in Choice Cases
- for (node : container.childNodes) {
- if (node instanceof ChoiceCaseNode) {
- val caseNode = (node as ChoiceCaseNode);
- ret = caseNode.childByQName(name);
- if (ret !== null) {
- return ret;
- }
- }
- }
- }
- return ret;
- }
-
- private def toUriString(Object object) {
- if(object === null) return "";
- return URLEncoder.encode(object.toString,URI_ENCODING_CHAR_SET)
- }
-
- private def InstanceIdWithSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
- DataNodeContainer parentNode, MountInstance mountPoint, boolean returnJustMountPoint) {
- checkNotNull(strings)
- if (parentNode === null) {
- return null;
- }
- if (strings.empty) {
- return new InstanceIdWithSchemaNode(builder.toInstance, parentNode as DataSchemaNode, mountPoint)
- }
-
- val nodeName = strings.head.toNodeName
- val moduleName = strings.head.toModuleName
- var DataSchemaNode targetNode = null
- if (!moduleName.nullOrEmpty) {
- // if it is mount point
- if (moduleName == MOUNT_MODULE && nodeName == MOUNT_NODE) {
- if (mountPoint !== null) {
- throw new ResponseException(BAD_REQUEST, "Restconf supports just one mount point in URI.")
- }
-
- if (mountService === null) {
- throw new ResponseException(SERVICE_UNAVAILABLE, "MountService was not found. "
- + "Finding behind mount points does not work."
- )
- }
-
- val partialPath = builder.toInstance;
- val mount = mountService.getMountPoint(partialPath)
- if (mount === null) {
- LOG.debug("Instance identifier to missing mount point: {}", partialPath)
- throw new ResponseException(BAD_REQUEST, "Mount point does not exist.")
- }
-
- val mountPointSchema = mount.schemaContext;
- if (mountPointSchema === null) {
- throw new ResponseException(BAD_REQUEST, "Mount point does not contain any schema with modules.")
- }
-
- if (returnJustMountPoint) {
- return new InstanceIdWithSchemaNode(InstanceIdentifier.builder().toInstance, mountPointSchema, mount)
- }
-
- if (strings.size == 1) { // any data node is not behind mount point
- return new InstanceIdWithSchemaNode(InstanceIdentifier.builder().toInstance, mountPointSchema, mount)
- }
-
- val moduleNameBehindMountPoint = strings.get(1).toModuleName()
- if (moduleNameBehindMountPoint === null) {
- throw new ResponseException(BAD_REQUEST,
- "First node after mount point in URI has to be in format \"moduleName:nodeName\"")
- }
-
- val moduleBehindMountPoint = mountPointSchema.getLatestModule(moduleNameBehindMountPoint)
- if (moduleBehindMountPoint === null) {
- throw new ResponseException(BAD_REQUEST,
- "URI has bad format. \"" + moduleName + "\" module does not exist in mount point.")
- }
-
- return collectPathArguments(InstanceIdentifier.builder(), strings.subList(1, strings.size),
- moduleBehindMountPoint, mount, returnJustMountPoint);
- }
-
- var Module module = null;
- if (mountPoint === null) {
- module = globalSchema.getLatestModule(moduleName)
- if (module === null) {
- throw new ResponseException(BAD_REQUEST,
- "URI has bad format. \"" + moduleName + "\" module does not exist.")
- }
- } else {
- module = mountPoint.schemaContext?.getLatestModule(moduleName)
- if (module === null) {
- throw new ResponseException(BAD_REQUEST,
- "URI has bad format. \"" + moduleName + "\" module does not exist in mount point.")
- }
- }
- targetNode = parentNode.findInstanceDataChildByNameAndNamespace(nodeName, module.namespace)
- if (targetNode === null) {
- throw new ResponseException(BAD_REQUEST, "URI has bad format. Possible reasons:\n" +
- "1. \"" + strings.head + "\" was not found in parent data node.\n" +
- "2. \"" + strings.head + "\" is behind mount point. Then it should be in format \"/" + MOUNT + "/" + strings.head + "\".")
- }
- } else { // string without module name
- val potentialSchemaNodes = parentNode.findInstanceDataChildrenByName(nodeName)
- if (potentialSchemaNodes.size > 1) {
- val StringBuilder namespacesOfPotentialModules = new StringBuilder;
- for (potentialNodeSchema : potentialSchemaNodes) {
- namespacesOfPotentialModules.append(" ").append(potentialNodeSchema.QName.namespace.toString).append("\n")
- }
- throw new ResponseException(BAD_REQUEST, "URI has bad format. Node \"" + nodeName + "\" is added as augment from more than one module. "
- + "Therefore the node must have module name and it has to be in format \"moduleName:nodeName\"."
- + "\nThe node is added as augment from modules with namespaces:\n" + namespacesOfPotentialModules)
- }
- targetNode = potentialSchemaNodes.head
- if (targetNode === null) {
- throw new ResponseException(BAD_REQUEST, "URI has bad format. \"" + nodeName + "\" was not found in parent data node.\n")
- }
- }
-
- if (!targetNode.isListOrContainer) {
- throw new ResponseException(BAD_REQUEST,"URI has bad format. Node \"" + strings.head + "\" must be Container or List yang type.")
- }
- // Number of consumed elements
- var consumed = 1;
- if (targetNode instanceof ListSchemaNode) {
- val listNode = targetNode as ListSchemaNode;
- val keysSize = listNode.keyDefinition.size
-
- // every key has to be filled
- if ((strings.length - consumed) < keysSize) {
- throw new ResponseException(BAD_REQUEST,"Missing key for list \"" + listNode.QName.localName + "\".")
- }
- val uriKeyValues = strings.subList(consumed, consumed + keysSize);
- val keyValues = new HashMap<QName, Object>();
- var i = 0;
- for (key : listNode.keyDefinition) {
- val uriKeyValue = uriKeyValues.get(i);
-
- // key value cannot be NULL
- if (uriKeyValue.equals(NULL_VALUE)) {
- throw new ResponseException(BAD_REQUEST, "URI has bad format. List \"" + listNode.QName.localName
- + "\" cannot contain \"null\" value as a key."
- )
- }
- keyValues.addKeyValue(listNode.getDataChildByName(key), uriKeyValue, mountPoint);
- i = i + 1;
- }
- consumed = consumed + i;
- builder.nodeWithKey(targetNode.QName, keyValues);
- } else {
-
- // Only one instance of node is allowed
- builder.node(targetNode.QName);
- }
- if (targetNode instanceof DataNodeContainer) {
- val remaining = strings.subList(consumed, strings.length);
- val result = builder.collectPathArguments(remaining, targetNode as DataNodeContainer, mountPoint, returnJustMountPoint);
- return result
- }
-
- return new InstanceIdWithSchemaNode(builder.toInstance, targetNode, mountPoint)
- }
-
- def DataSchemaNode findInstanceDataChildByNameAndNamespace(DataNodeContainer container,
- String name, URI namespace) {
- Preconditions.checkNotNull(namespace)
- val potentialSchemaNodes = container.findInstanceDataChildrenByName(name)
- return potentialSchemaNodes.filter[n|n.QName.namespace == namespace].head
- }
-
- def List<DataSchemaNode> findInstanceDataChildrenByName(DataNodeContainer container, String name) {
- Preconditions.checkNotNull(container)
- Preconditions.checkNotNull(name)
- val instantiatedDataNodeContainers = new ArrayList
- instantiatedDataNodeContainers.collectInstanceDataNodeContainers(container, name)
- return instantiatedDataNodeContainers
- }
-
- private def void collectInstanceDataNodeContainers(List<DataSchemaNode> potentialSchemaNodes, DataNodeContainer container,
- String name) {
- val nodes = container.childNodes.filter[n|n.QName.localName == name]
- for (potentialNode : nodes) {
- if (potentialNode.isInstantiatedDataSchema) {
- potentialSchemaNodes.add(potentialNode)
- }
- }
- val allCases = container.childNodes.filter(ChoiceNode).map[cases].flatten
- for (caze : allCases) {
- collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name)
- }
- }
-
- def boolean isInstantiatedDataSchema(DataSchemaNode node) {
- switch node {
- LeafSchemaNode: return true
- LeafListSchemaNode: return true
- ContainerSchemaNode: return true
- ListSchemaNode: return true
- default: return false
- }
- }
-
- private def void addKeyValue(HashMap<QName, Object> map, DataSchemaNode node, String uriValue, MountInstance mountPoint) {
- checkNotNull(uriValue);
- checkArgument(node instanceof LeafSchemaNode);
- val urlDecoded = URLDecoder.decode(uriValue);
- val typedef = (node as LeafSchemaNode).type;
-
- var decoded = RestCodec.from(typedef, mountPoint)?.deserialize(urlDecoded)
- var additionalInfo = ""
- if(decoded === null) {
- var baseType = RestUtil.resolveBaseTypeFrom(typedef)
- if(baseType instanceof IdentityrefTypeDefinition) {
- decoded = toQName(urlDecoded)
- additionalInfo = "For key which is of type identityref it should be in format module_name:identity_name."
- }
- }
- if (decoded === null) {
- throw new ResponseException(BAD_REQUEST, uriValue + " from URI can't be resolved. "+ additionalInfo )
- }
-
- map.put(node.QName, decoded);
- }
-
- private static def String toModuleName(String str) {
- checkNotNull(str)
- if (str.contains(":")) {
- val args = str.split(":");
- if (args.size === 2) {
- return args.get(0);
- }
- }
- return null;
- }
-
- private def String toNodeName(String str) {
- if (str.contains(":")) {
- val args = str.split(":");
- if (args.size === 2) {
- return args.get(1);
- }
- }
- return str;
- }
-
- private def QName toQName(String name) {
- val module = name.toModuleName;
- val node = name.toNodeName;
- val namespace = FluentIterable.from(globalSchema.modules.sort[o1,o2 | o1.revision.compareTo(o2.revision)])
- .transform[QName.create(namespace,revision,it.name)].findFirst[module == localName]
- if (namespace === null) {
- return null
- }
- return QName.create(namespace, node);
- }
-
- private def boolean isListOrContainer(DataSchemaNode node) {
- return ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode))
- }
-
- def getRpcDefinition(String name) {
- val validName = name.toQName
- if (validName === null) {
- return null
- }
- return qnameToRpc.get(validName)
- }
-
- override onGlobalContextUpdated(SchemaContext context) {
- if (context !== null) {
- qnameToRpc.clear
- this.globalSchema = context;
- for (operation : context.operations) {
- val qname = operation.QName;
- qnameToRpc.put(qname, operation);
- }
- }
- }
-
-
- def urlPathArgsDecode(List<String> strings) {
- val List<String> decodedPathArgs = new ArrayList();
- for (pathArg : strings) {
- decodedPathArgs.add(URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET))
- }
- return decodedPathArgs
- }
-
- def urlPathArgDecode(String pathArg) {
- if (pathArg !== null) {
- return URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET)
- }
- return null
- }
-
-}
public ResponseException(Status status, String msg) {
super(Response.status(status).type(MediaType.TEXT_PLAIN_TYPE).entity(msg).build());
}
+
+ public ResponseException(Throwable cause, String msg) {
+ super(cause, Response.status(Status.INTERNAL_SERVER_ERROR).
+ type(MediaType.TEXT_PLAIN_TYPE).entity(msg).build());
+ }
}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.restconf.impl;
+
+import 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.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+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.streams.listeners.ListenerAdapter;
+import org.opendaylight.controller.sal.streams.listeners.Notificator;
+import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.EmptyType;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
+
+@SuppressWarnings("all")
+public class RestconfImpl implements RestconfService {
+ private final static RestconfImpl INSTANCE = new RestconfImpl();
+
+ private final static String MOUNT_POINT_MODULE_NAME = "ietf-netconf";
+
+ private final static SimpleDateFormat REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
+
+ private final static String RESTCONF_MODULE_DRAFT02_REVISION = "2013-10-19";
+
+ private final static String RESTCONF_MODULE_DRAFT02_NAME = "ietf-restconf";
+
+ private final static String RESTCONF_MODULE_DRAFT02_NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-restconf";
+
+ private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE = "restconf";
+
+ private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE = "restconf";
+
+ private final static String RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE = "modules";
+
+ private final static String RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE = "module";
+
+ private final static String RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE = "streams";
+
+ private final static String RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE = "stream";
+
+ private final static String RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE = "operations";
+
+ private final static String SAL_REMOTE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote";
+
+ private final static String SAL_REMOTE_RPC_SUBSRCIBE = "create-data-change-event-subscription";
+
+ private BrokerFacade broker;
+
+ private ControllerContext controllerContext;
+
+ public void setBroker(final BrokerFacade broker) {
+ this.broker = broker;
+ }
+
+ public void setControllerContext(final ControllerContext controllerContext) {
+ this.controllerContext = controllerContext;
+ }
+
+ private RestconfImpl() {
+ }
+
+ public static RestconfImpl getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public StructuredData getModules() {
+ final Module restconfModule = this.getRestconfModule();
+
+ final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
+ final DataSchemaNode moduleSchemaNode =
+ this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+
+ Set<Module> allModules = this.controllerContext.getAllModules();
+ for (final Module module : allModules) {
+ CompositeNode moduleCompositeNode = this.toModuleCompositeNode(module, moduleSchemaNode);
+ modulesAsData.add(moduleCompositeNode);
+ }
+
+ final DataSchemaNode modulesSchemaNode =
+ this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+ QName qName = modulesSchemaNode.getQName();
+ final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
+ return new StructuredData(modulesNode, modulesSchemaNode, null);
+ }
+
+ @Override
+ public StructuredData getAvailableStreams() {
+ Set<String> availableStreams = Notificator.getStreamNames();
+
+ final List<Node<?>> streamsAsData = new ArrayList<Node<?>>();
+ Module restconfModule = this.getRestconfModule();
+ final DataSchemaNode streamSchemaNode =
+ this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
+ for (final String streamName : availableStreams) {
+ streamsAsData.add(this.toStreamCompositeNode(streamName, streamSchemaNode));
+ }
+
+ final DataSchemaNode streamsSchemaNode =
+ this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
+ QName qName = streamsSchemaNode.getQName();
+ final CompositeNode streamsNode = NodeFactory.createImmutableCompositeNode(qName, null, streamsAsData);
+ return new StructuredData(streamsNode, streamsSchemaNode, null);
+ }
+
+ @Override
+ public StructuredData getModules(final String identifier) {
+ Set<Module> modules = null;
+ MountInstance mountPoint = null;
+ if (identifier.contains(ControllerContext.MOUNT)) {
+ InstanceIdWithSchemaNode mountPointIdentifier =
+ this.controllerContext.toMountPointIdentifier(identifier);
+ mountPoint = mountPointIdentifier.getMountPoint();
+ modules = this.controllerContext.getAllModules(mountPoint);
+ }
+ else {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "URI has bad format. If modules behind mount point should be showed, URI has to end with " +
+ ControllerContext.MOUNT);
+ }
+
+ final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
+ Module restconfModule = this.getRestconfModule();
+ final DataSchemaNode moduleSchemaNode =
+ this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+
+ for (final Module module : modules) {
+ modulesAsData.add(this.toModuleCompositeNode(module, moduleSchemaNode));
+ }
+
+ final DataSchemaNode modulesSchemaNode =
+ this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+ QName qName = modulesSchemaNode.getQName();
+ final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
+ return new StructuredData(modulesNode, modulesSchemaNode, mountPoint);
+ }
+
+ @Override
+ public StructuredData getModule(final String identifier) {
+ final QName moduleNameAndRevision = this.getModuleNameAndRevision(identifier);
+ Module module = null;
+ MountInstance mountPoint = null;
+ if (identifier.contains(ControllerContext.MOUNT)) {
+ InstanceIdWithSchemaNode mountPointIdentifier =
+ this.controllerContext.toMountPointIdentifier(identifier);
+ mountPoint = mountPointIdentifier.getMountPoint();
+ module = this.controllerContext.findModuleByNameAndRevision(mountPoint, moduleNameAndRevision);
+ }
+ else {
+ module = this.controllerContext.findModuleByNameAndRevision(moduleNameAndRevision);
+ }
+
+ if (module == null) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Module with name '" + moduleNameAndRevision.getLocalName() + "' and revision '" +
+ moduleNameAndRevision.getRevision() + "' was not found.");
+ }
+
+ Module restconfModule = this.getRestconfModule();
+ final DataSchemaNode moduleSchemaNode =
+ this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+ final CompositeNode moduleNode = this.toModuleCompositeNode(module, moduleSchemaNode);
+ return new StructuredData(moduleNode, moduleSchemaNode, mountPoint);
+ }
+
+ @Override
+ public StructuredData getOperations() {
+ Set<Module> allModules = this.controllerContext.getAllModules();
+ return this.operationsFromModulesToStructuredData(allModules, null);
+ }
+
+ @Override
+ public StructuredData getOperations(final String identifier) {
+ Set<Module> modules = null;
+ MountInstance mountPoint = null;
+ if (identifier.contains(ControllerContext.MOUNT)) {
+ InstanceIdWithSchemaNode mountPointIdentifier =
+ this.controllerContext.toMountPointIdentifier(identifier);
+ mountPoint = mountPointIdentifier.getMountPoint();
+ modules = this.controllerContext.getAllModules(mountPoint);
+ }
+ else {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "URI has bad format. If operations behind mount point should be showed, URI has to end with " +
+ ControllerContext.MOUNT);
+ }
+
+ return this.operationsFromModulesToStructuredData(modules, mountPoint);
+ }
+
+ private StructuredData operationsFromModulesToStructuredData(final Set<Module> modules,
+ final MountInstance mountPoint) {
+ final List<Node<?>> operationsAsData = new ArrayList<Node<?>>();
+ Module restconfModule = this.getRestconfModule();
+ final DataSchemaNode operationsSchemaNode =
+ this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
+ QName qName = operationsSchemaNode.getQName();
+ SchemaPath path = operationsSchemaNode.getPath();
+ ContainerSchemaNodeBuilder containerSchemaNodeBuilder =
+ new ContainerSchemaNodeBuilder(RESTCONF_MODULE_DRAFT02_NAME, 0, qName, path);
+ final ContainerSchemaNodeBuilder fakeOperationsSchemaNode = containerSchemaNodeBuilder;
+ for (final Module module : modules) {
+ Set<RpcDefinition> rpcs = module.getRpcs();
+ for (final RpcDefinition rpc : rpcs) {
+ QName rpcQName = rpc.getQName();
+ SimpleNode<Object> immutableSimpleNode =
+ NodeFactory.<Object>createImmutableSimpleNode(rpcQName, null, null);
+ operationsAsData.add(immutableSimpleNode);
+
+ String name = module.getName();
+ LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder(name, 0, rpcQName, null);
+ final LeafSchemaNodeBuilder fakeRpcSchemaNode = leafSchemaNodeBuilder;
+ fakeRpcSchemaNode.setAugmenting(true);
+
+ EmptyType instance = EmptyType.getInstance();
+ fakeRpcSchemaNode.setType(instance);
+ fakeOperationsSchemaNode.addChildNode(fakeRpcSchemaNode.build());
+ }
+ }
+
+ final CompositeNode operationsNode =
+ NodeFactory.createImmutableCompositeNode(qName, null, operationsAsData);
+ ContainerSchemaNode schemaNode = fakeOperationsSchemaNode.build();
+ return new StructuredData(operationsNode, schemaNode, mountPoint);
+ }
+
+ private Module getRestconfModule() {
+ QName qName = QName.create(RESTCONF_MODULE_DRAFT02_NAMESPACE, RESTCONF_MODULE_DRAFT02_REVISION,
+ RESTCONF_MODULE_DRAFT02_NAME);
+ final Module restconfModule = this.controllerContext.findModuleByNameAndRevision(qName);
+ if (restconfModule == null) {
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Restconf module was not found.");
+ }
+
+ return restconfModule;
+ }
+
+ private QName getModuleNameAndRevision(final String identifier) {
+ final int mountIndex = identifier.indexOf(ControllerContext.MOUNT);
+ String moduleNameAndRevision = "";
+ if (mountIndex >= 0) {
+ moduleNameAndRevision = identifier.substring(mountIndex + ControllerContext.MOUNT.length());
+ }
+ else {
+ moduleNameAndRevision = identifier;
+ }
+
+ Splitter splitter = Splitter.on("/").omitEmptyStrings();
+ Iterable<String> split = splitter.split(moduleNameAndRevision);
+ final List<String> pathArgs = Lists.<String>newArrayList(split);
+ if (pathArgs.size() < 2) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "URI has bad format. End of URI should be in format \'moduleName/yyyy-MM-dd\'");
+ }
+
+ try {
+ final String moduleName = pathArgs.get( 0 );
+ String revision = pathArgs.get(1);
+ final Date moduleRevision = REVISION_FORMAT.parse(revision);
+ return QName.create(null, moduleRevision, moduleName);
+ }
+ catch (ParseException e) {
+ throw new ResponseException(Status.BAD_REQUEST, "URI has bad format. It should be \'moduleName/yyyy-MM-dd\'");
+ }
+ }
+
+ private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
+ final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
+ List<DataSchemaNode> instanceDataChildrenByName =
+ this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) streamSchemaNode),
+ "name");
+ final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+ streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(), null,
+ streamName));
+
+ instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ ((DataNodeContainer) streamSchemaNode), "description");
+ final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+ streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
+ "DESCRIPTION_PLACEHOLDER"));
+
+ instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ ((DataNodeContainer) streamSchemaNode), "replay-support");
+ final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+ streamNodeValues.add(NodeFactory.<Boolean>createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
+ Boolean.valueOf(true)));
+
+ instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ ((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
+ final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+ streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
+ null, ""));
+
+ instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ ((DataNodeContainer) streamSchemaNode), "events");
+ final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+ streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(eventsSchemaNode.getQName(),
+ null, ""));
+
+ return NodeFactory.createImmutableCompositeNode(streamSchemaNode.getQName(), null, streamNodeValues);
+ }
+
+ private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
+ final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
+ List<DataSchemaNode> instanceDataChildrenByName =
+ this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) moduleSchemaNode), "name");
+ final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+ moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(),
+ null, module.getName()));
+
+ instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ ((DataNodeContainer) moduleSchemaNode), "revision");
+ final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+ Date _revision = module.getRevision();
+ moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
+ REVISION_FORMAT.format(_revision)));
+
+ instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ ((DataNodeContainer) moduleSchemaNode), "namespace");
+ final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+ moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
+ module.getNamespace().toString()));
+
+ instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ ((DataNodeContainer) moduleSchemaNode), "feature");
+ final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
+ for (final FeatureDefinition feature : module.getFeatures()) {
+ moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(featureSchemaNode.getQName(), null,
+ feature.getQName().getLocalName()));
+ }
+
+ return NodeFactory.createImmutableCompositeNode(moduleSchemaNode.getQName(), null, moduleNodeValues);
+ }
+
+ private DataSchemaNode getSchemaNode(final Module restconfModule, final String schemaNodeName) {
+ Set<GroupingDefinition> groupings = restconfModule.getGroupings();
+
+ final Predicate<GroupingDefinition> filter = new Predicate<GroupingDefinition>() {
+ @Override
+ public boolean apply(final GroupingDefinition g) {
+ return Objects.equal(g.getQName().getLocalName(),
+ RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE);
+ }
+ };
+
+ Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
+
+ final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
+
+ List<DataSchemaNode> instanceDataChildrenByName =
+ this.controllerContext.findInstanceDataChildrenByName(restconfGrouping,
+ RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
+
+ if (Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+ else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+ else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode modules = Iterables.getFirst(instances, null);
+ instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+ RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+ else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+ else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)) {
+ List<DataSchemaNode> instances =
+ this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
+ RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
+ final DataSchemaNode modules = Iterables.getFirst(instances, null);
+ instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+ RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
+ return Iterables.getFirst(instances, null);
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object getRoot() {
+ return null;
+ }
+
+ @Override
+ public StructuredData invokeRpc(final String identifier, final CompositeNode payload) {
+ final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
+ if (Objects.equal(rpc.getQName().getNamespace().toString(), SAL_REMOTE_NAMESPACE) &&
+ Objects.equal(rpc.getQName().getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
+
+ final 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 (!(pathValue instanceof InstanceIdentifier)) {
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+ "Instance identifier was not normalized correctly.");
+ }
+
+ final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
+ String streamName = null;
+ if (!Iterables.isEmpty(pathIdentifier.getPath())) {
+ String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
+ streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
+ }
+
+ 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.");
+ }
+
+ 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);
+
+ if (!Notificator.existListenerFor(pathIdentifier)) {
+ Notificator.createListener(pathIdentifier, streamName);
+ }
+
+ return new StructuredData(responseData, rpc.getOutput(), null);
+ }
+
+ RpcDefinition rpcDefinition = this.controllerContext.getRpcDefinition(identifier);
+ return this.callRpc(rpcDefinition, payload);
+ }
+
+ @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.");
+ }
+
+ final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
+ return this.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;
+ }
+
+ 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);
+
+ throw new ResponseException(Status.NOT_FOUND, slashErrorMsg);
+ }
+
+ private StructuredData callRpc(final RpcDefinition rpc, final CompositeNode payload) {
+ if (rpc == null) {
+ throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
+ }
+
+ CompositeNode rpcRequest = null;
+ if (payload == null) {
+ rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), 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);
+ }
+
+ final RpcResult<CompositeNode> rpcResult = broker.invokeRpc(rpc.getQName(), rpcRequest);
+
+ if (!rpcResult.isSuccessful()) {
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Operation failed");
+ }
+
+ CompositeNode result = rpcResult.getResult();
+ if (result == null) {
+ return null;
+ }
+
+ return new StructuredData(result, rpc.getOutput(), null);
+ }
+
+ @Override
+ public StructuredData readConfigurationData(final String identifier) {
+ final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+ CompositeNode data = null;
+ MountInstance mountPoint = iiWithData.getMountPoint();
+ if (mountPoint != null) {
+ data = broker.readConfigurationDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
+ }
+ else {
+ data = broker.readConfigurationData(iiWithData.getInstanceIdentifier());
+ }
+
+ return new StructuredData(data, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
+ }
+
+ @Override
+ public StructuredData readOperationalData(final String identifier) {
+ final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+ CompositeNode data = null;
+ MountInstance mountPoint = iiWithData.getMountPoint();
+ if (mountPoint != null) {
+ data = broker.readOperationalDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
+ }
+ else {
+ data = broker.readOperationalData(iiWithData.getInstanceIdentifier());
+ }
+
+ return new StructuredData(data, iiWithData.getSchemaNode(), mountPoint);
+ }
+
+ @Override
+ public Response updateConfigurationData(final String identifier, final CompositeNode payload) {
+ final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+ MountInstance mountPoint = iiWithData.getMountPoint();
+ final CompositeNode value = this.normalizeNode(payload, iiWithData.getSchemaNode(), mountPoint);
+ RpcResult<TransactionStatus> status = null;
+
+ try {
+ if (mountPoint != null) {
+ status = broker.commitConfigurationDataPutBehindMountPoint(
+ mountPoint, iiWithData.getInstanceIdentifier(), value).get();
+ } else {
+ status = broker.commitConfigurationDataPut(iiWithData.getInstanceIdentifier(), value).get();
+ }
+ }
+ catch( Exception e ) {
+ throw new ResponseException( e, "Error updating data" );
+ }
+
+ if( status.getResult() == TransactionStatus.COMMITED )
+ return Response.status(Status.OK).build();
+
+ return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+ }
+
+ @Override
+ public Response createConfigurationData(final String identifier, final CompositeNode payload) {
+ URI payloadNS = this.namespace(payload);
+ if (payloadNS == null) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
+ }
+
+ InstanceIdWithSchemaNode iiWithData = null;
+ CompositeNode value = null;
+ if (this.representsMountPointRootData(payload)) {
+ // payload represents mount point data and URI represents path to the mount point
+
+ if (this.endsWithMountPoint(identifier)) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "URI has bad format. URI should be without \"" + ControllerContext.MOUNT +
+ "\" for POST operation.");
+ }
+
+ final String completeIdentifier = this.addMountPointIdentifier(identifier);
+ iiWithData = this.controllerContext.toInstanceIdentifier(completeIdentifier);
+
+ value = this.normalizeNode(payload, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
+ }
+ else {
+ final InstanceIdWithSchemaNode incompleteInstIdWithData =
+ this.controllerContext.toInstanceIdentifier(identifier);
+ final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode();
+ MountInstance mountPoint = incompleteInstIdWithData.getMountPoint();
+ final Module module = this.findModule(mountPoint, payload);
+ if (module == null) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Module was not found for \"" + payloadNS + "\"");
+ }
+
+ String payloadName = this.getName(payload);
+ final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
+ parentSchema, payloadName, module.getNamespace());
+ value = this.normalizeNode(payload, schemaNode, mountPoint);
+
+ iiWithData = this.addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode);
+ }
+
+ RpcResult<TransactionStatus> status = null;
+ MountInstance mountPoint = iiWithData.getMountPoint();
+ try {
+ if (mountPoint != null) {
+ Future<RpcResult<TransactionStatus>> future =
+ broker.commitConfigurationDataPostBehindMountPoint(
+ mountPoint, iiWithData.getInstanceIdentifier(), value);
+ status = future == null ? null : future.get();
+ }
+ else {
+ Future<RpcResult<TransactionStatus>> future =
+ broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
+ status = future == null ? null : future.get();
+ }
+ }
+ catch( Exception e ) {
+ throw new ResponseException( e, "Error creating data" );
+ }
+
+ if (status == null) {
+ return Response.status(Status.ACCEPTED).build();
+ }
+
+ if( status.getResult() == TransactionStatus.COMMITED )
+ return Response.status(Status.NO_CONTENT).build();
+
+ return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+ }
+
+ @Override
+ public Response createConfigurationData(final CompositeNode payload) {
+ URI payloadNS = this.namespace(payload);
+ if (payloadNS == null) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
+ }
+
+ final Module module = this.findModule(null, payload);
+ if (module == null) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)");
+ }
+
+ String payloadName = this.getName(payload);
+ final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
+ module, payloadName, module.getNamespace());
+ final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
+ final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode);
+ RpcResult<TransactionStatus> status = null;
+ MountInstance mountPoint = iiWithData.getMountPoint();
+
+ try {
+ if (mountPoint != null) {
+ Future<RpcResult<TransactionStatus>> future =
+ broker.commitConfigurationDataPostBehindMountPoint(
+ mountPoint, iiWithData.getInstanceIdentifier(), value);
+ status = future == null ? null : future.get();
+ }
+ else {
+ Future<RpcResult<TransactionStatus>> future =
+ broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
+ status = future == null ? null : future.get();
+ }
+ }
+ catch( Exception e ) {
+ throw new ResponseException( e, "Error creating data" );
+ }
+
+ if (status == null) {
+ return Response.status(Status.ACCEPTED).build();
+ }
+
+ if( status.getResult() == TransactionStatus.COMMITED )
+ return Response.status(Status.NO_CONTENT).build();
+
+ return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+ }
+
+ @Override
+ public Response deleteConfigurationData(final String identifier) {
+ final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+ RpcResult<TransactionStatus> status = null;
+ MountInstance mountPoint = iiWithData.getMountPoint();
+
+ try {
+ if (mountPoint != null) {
+ status = broker.commitConfigurationDataDeleteBehindMountPoint(
+ mountPoint, iiWithData.getInstanceIdentifier()).get();
+ }
+ else {
+ status = broker.commitConfigurationDataDelete(iiWithData.getInstanceIdentifier()).get();
+ }
+ }
+ catch( Exception e ) {
+ throw new ResponseException( e, "Error creating data" );
+ }
+
+ if( status.getResult() == TransactionStatus.COMMITED )
+ return Response.status(Status.OK).build();
+
+ return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+ }
+
+ @Override
+ public Response subscribeToStream(final String identifier, final UriInfo uriInfo) {
+ final String streamName = Notificator.createStreamNameFromUri(identifier);
+ if (Strings.isNullOrEmpty(streamName)) {
+ throw new ResponseException(Status.BAD_REQUEST, "Stream name is empty.");
+ }
+
+ final ListenerAdapter listener = Notificator.getListenerFor(streamName);
+ if (listener == null) {
+ throw new ResponseException(Status.BAD_REQUEST, "Stream was not found.");
+ }
+
+ broker.registerToListenDataChanges(listener);
+
+ final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
+ UriBuilder port = uriBuilder.port(WebSocketServer.PORT);
+ final URI uriToWebsocketServer = port.replacePath(streamName).build();
+
+ return Response.status(Status.OK).location(uriToWebsocketServer).build();
+ }
+
+ private Module findModule(final MountInstance mountPoint, final CompositeNode data) {
+ if (data instanceof CompositeNodeWrapper) {
+ return findModule(mountPoint, (CompositeNodeWrapper)data);
+ }
+ else if (data != null) {
+ URI namespace = data.getNodeType().getNamespace();
+ if (mountPoint != null) {
+ return this.controllerContext.findModuleByNamespace(mountPoint, namespace);
+ }
+ else {
+ return this.controllerContext.findModuleByNamespace(namespace);
+ }
+ }
+ else {
+ throw new IllegalArgumentException("Unhandled parameter types: " +
+ Arrays.<Object>asList(mountPoint, data).toString());
+ }
+ }
+
+ private Module findModule(final MountInstance mountPoint, final CompositeNodeWrapper data) {
+ URI namespace = data.getNamespace();
+ Preconditions.<URI>checkNotNull(namespace);
+
+ Module module = null;
+ if (mountPoint != null) {
+ module = this.controllerContext.findModuleByNamespace(mountPoint, namespace);
+ if (module == null) {
+ module = this.controllerContext.findModuleByName(mountPoint, namespace.toString());
+ }
+ }
+ else {
+ module = this.controllerContext.findModuleByNamespace(namespace);
+ if (module == null) {
+ module = this.controllerContext.findModuleByName(namespace.toString());
+ }
+ }
+
+ return module;
+ }
+
+ private InstanceIdWithSchemaNode addLastIdentifierFromData(
+ final InstanceIdWithSchemaNode identifierWithSchemaNode,
+ final CompositeNode data, final DataSchemaNode schemaOfData) {
+ InstanceIdentifier instanceIdentifier = null;
+ if (identifierWithSchemaNode != null) {
+ instanceIdentifier = identifierWithSchemaNode.getInstanceIdentifier();
+ }
+
+ final InstanceIdentifier iiOriginal = instanceIdentifier;
+ InstanceIdentifierBuilder iiBuilder = null;
+ if (iiOriginal == null) {
+ iiBuilder = InstanceIdentifier.builder();
+ }
+ else {
+ iiBuilder = InstanceIdentifier.builder(iiOriginal);
+ }
+
+ if ((schemaOfData instanceof ListSchemaNode)) {
+ HashMap<QName,Object> keys = this.resolveKeysFromData(((ListSchemaNode) schemaOfData), data);
+ iiBuilder.nodeWithKey(schemaOfData.getQName(), keys);
+ }
+ else {
+ iiBuilder.node(schemaOfData.getQName());
+ }
+
+ InstanceIdentifier instance = iiBuilder.toInstance();
+ MountInstance mountPoint = null;
+ if (identifierWithSchemaNode != null) {
+ mountPoint=identifierWithSchemaNode.getMountPoint();
+ }
+
+ return new InstanceIdWithSchemaNode(instance, schemaOfData, mountPoint);
+ }
+
+ private HashMap<QName,Object> resolveKeysFromData(final ListSchemaNode listNode,
+ final CompositeNode dataNode) {
+ final HashMap<QName,Object> keyValues = new HashMap<QName, Object>();
+ List<QName> _keyDefinition = listNode.getKeyDefinition();
+ for (final QName key : _keyDefinition) {
+ SimpleNode<? extends Object> head = null;
+ String localName = key.getLocalName();
+ List<SimpleNode<? extends Object>> simpleNodesByName = dataNode.getSimpleNodesByName(localName);
+ if (simpleNodesByName != null) {
+ head = Iterables.getFirst(simpleNodesByName, null);
+ }
+
+ Object dataNodeKeyValueObject = null;
+ if (head != null) {
+ dataNodeKeyValueObject = head.getValue();
+ }
+
+ if (dataNodeKeyValueObject == null) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Data contains list \"" + dataNode.getNodeType().getLocalName() +
+ "\" which does not contain key: \"" + key.getLocalName() + "\"");
+ }
+
+ keyValues.put(key, dataNodeKeyValueObject);
+ }
+
+ return keyValues;
+ }
+
+ private boolean endsWithMountPoint(final String identifier) {
+ return identifier.endsWith(ControllerContext.MOUNT) ||
+ identifier.endsWith(ControllerContext.MOUNT + "/");
+ }
+
+ private boolean representsMountPointRootData(final CompositeNode data) {
+ URI namespace = this.namespace(data);
+ return (SchemaContext.NAME.getNamespace().equals( namespace ) /* ||
+ MOUNT_POINT_MODULE_NAME.equals( namespace.toString() )*/ ) &&
+ SchemaContext.NAME.getLocalName().equals( this.localName(data) );
+ }
+
+ private String addMountPointIdentifier(final String identifier) {
+ boolean endsWith = identifier.endsWith("/");
+ if (endsWith) {
+ return (identifier + ControllerContext.MOUNT);
+ }
+
+ return identifier + "/" + ControllerContext.MOUNT;
+ }
+
+ private CompositeNode normalizeNode(final CompositeNode node, final DataSchemaNode schema,
+ final MountInstance mountPoint) {
+ if (schema == null) {
+ QName nodeType = node == null ? null : node.getNodeType();
+ String localName = nodeType == null ? null : nodeType.getLocalName();
+ String _plus = ("Data schema node was not found for " + localName);
+ throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
+ "Data schema node was not found for " + localName );
+ }
+
+ if (!(schema instanceof DataNodeContainer)) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Root element has to be container or list yang datatype.");
+ }
+
+ if ((node instanceof CompositeNodeWrapper)) {
+ boolean isChangeAllowed = ((CompositeNodeWrapper) node).isChangeAllowed();
+ if (isChangeAllowed) {
+ try {
+ this.normalizeNode(((CompositeNodeWrapper) node), schema, null, mountPoint);
+ }
+ catch (NumberFormatException e) {
+ throw new ResponseException(Status.BAD_REQUEST, e.getMessage());
+ }
+ }
+
+ return ((CompositeNodeWrapper) node).unwrap();
+ }
+
+ return node;
+ }
+
+ private void normalizeNode(final NodeWrapper<? extends Object> nodeBuilder,
+ final DataSchemaNode schema, final QName previousAugment,
+ final MountInstance mountPoint) {
+ if (schema == null) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Data has bad format.\n\"" + nodeBuilder.getLocalName() +
+ "\" does not exist in yang schema.");
+ }
+
+ QName currentAugment = null;
+ if (nodeBuilder.getQname() != null) {
+ currentAugment = previousAugment;
+ }
+ else {
+ currentAugment = this.normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint);
+ if (nodeBuilder.getQname() == null) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Data has bad format.\nIf data is in XML format then namespace for \"" +
+ nodeBuilder.getLocalName() +
+ "\" should be \"" + schema.getQName().getNamespace() + "\".\n" +
+ "If data is in JSON format then module name for \"" + nodeBuilder.getLocalName() +
+ "\" should be corresponding to namespace \"" +
+ schema.getQName().getNamespace() + "\".");
+ }
+ }
+
+ if ((nodeBuilder instanceof CompositeNodeWrapper)) {
+ final List<NodeWrapper<?>> children = ((CompositeNodeWrapper) nodeBuilder).getValues();
+ for (final NodeWrapper<? extends Object> child : children) {
+ final List<DataSchemaNode> potentialSchemaNodes =
+ this.controllerContext.findInstanceDataChildrenByName(
+ ((DataNodeContainer) schema), child.getLocalName());
+
+ if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
+ StringBuilder builder = new StringBuilder();
+ for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
+ builder.append(" ").append(potentialSchemaNode.getQName().getNamespace().toString())
+ .append("\n");
+ }
+
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Node \"" + child.getLocalName() +
+ "\" is added as augment from more than one module. " +
+ "Therefore node must have namespace (XML format) or module name (JSON format)." +
+ "\nThe node is added as augment from modules with namespaces:\n" + builder);
+ }
+
+ boolean rightNodeSchemaFound = false;
+ for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
+ if (!rightNodeSchemaFound) {
+ final QName potentialCurrentAugment =
+ this.normalizeNodeName(child, potentialSchemaNode, currentAugment, mountPoint);
+ if (child.getQname() != null ) {
+ this.normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint);
+ rightNodeSchemaFound = true;
+ }
+ }
+ }
+
+ if (!rightNodeSchemaFound) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Schema node \"" + child.getLocalName() + "\" was not found in module.");
+ }
+ }
+
+ if ((schema instanceof ListSchemaNode)) {
+ final List<QName> listKeys = ((ListSchemaNode) schema).getKeyDefinition();
+ for (final QName listKey : listKeys) {
+ boolean foundKey = false;
+ for (final NodeWrapper<? extends Object> child : children) {
+ if (Objects.equal(child.unwrap().getNodeType().getLocalName(), listKey.getLocalName())) {
+ foundKey = true;
+ }
+ }
+
+ if (!foundKey) {
+ throw new ResponseException(Status.BAD_REQUEST,
+ "Missing key in URI \"" + listKey.getLocalName() +
+ "\" of list \"" + schema.getQName().getLocalName() + "\"");
+ }
+ }
+ }
+ }
+ else {
+ if ((nodeBuilder instanceof SimpleNodeWrapper)) {
+ final SimpleNodeWrapper simpleNode = ((SimpleNodeWrapper) nodeBuilder);
+ final Object value = simpleNode.getValue();
+ Object inputValue = value;
+ TypeDefinition<? extends Object> typeDefinition = this.typeDefinition(schema);
+ if ((typeDefinition instanceof IdentityrefTypeDefinition)) {
+ if ((value instanceof String)) {
+ inputValue = new IdentityValuesDTO( nodeBuilder.getNamespace().toString(),
+ (String) value, null, (String) value );
+ } // else value is already instance of IdentityValuesDTO
+ }
+
+ Codec<Object,Object> codec = RestCodec.from(typeDefinition, mountPoint);
+ Object outputValue = codec == null ? null : codec.deserialize(inputValue);
+
+ simpleNode.setValue(outputValue);
+ }
+ else {
+ if ((nodeBuilder instanceof EmptyNodeWrapper)) {
+ final EmptyNodeWrapper emptyNodeBuilder = ((EmptyNodeWrapper) nodeBuilder);
+ if ((schema instanceof LeafSchemaNode)) {
+ emptyNodeBuilder.setComposite(false);
+ }
+ else {
+ if ((schema instanceof ContainerSchemaNode)) {
+ // FIXME: Add presence check
+ emptyNodeBuilder.setComposite(true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private QName normalizeNodeName(final NodeWrapper<? extends Object> nodeBuilder,
+ final DataSchemaNode schema, final QName previousAugment,
+ final MountInstance mountPoint) {
+ QName validQName = schema.getQName();
+ QName currentAugment = previousAugment;
+ if (schema.isAugmenting()) {
+ currentAugment = schema.getQName();
+ }
+ else if (previousAugment != null &&
+ !Objects.equal( schema.getQName().getNamespace(), previousAugment.getNamespace())) {
+ validQName = QName.create(currentAugment, schema.getQName().getLocalName());
+ }
+
+ String moduleName = null;
+ if (mountPoint == null) {
+ moduleName = controllerContext.findModuleNameByNamespace(validQName.getNamespace());
+ }
+ else {
+ moduleName = controllerContext.findModuleNameByNamespace(mountPoint, validQName.getNamespace());
+ }
+
+ if (nodeBuilder.getNamespace() == null ||
+ Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace()) ||
+ Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*||
+ Note: this check is wrong - can never be true as it compares a URI with a String
+ not sure what the intention is so commented out...
+ Objects.equal(nodeBuilder.getNamespace(), MOUNT_POINT_MODULE_NAME)*/ ) {
+
+ nodeBuilder.setQname(validQName);
+ }
+
+ return currentAugment;
+ }
+
+ private URI namespace(final CompositeNode data) {
+ if (data instanceof CompositeNodeWrapper) {
+ return ((CompositeNodeWrapper)data).getNamespace();
+ }
+ else if (data != null) {
+ return data.getNodeType().getNamespace();
+ }
+ else {
+ throw new IllegalArgumentException("Unhandled parameter types: " +
+ Arrays.<Object>asList(data).toString());
+ }
+ }
+
+ private String localName(final CompositeNode data) {
+ if (data instanceof CompositeNodeWrapper) {
+ return ((CompositeNodeWrapper)data).getLocalName();
+ }
+ else if (data != null) {
+ return data.getNodeType().getLocalName();
+ }
+ else {
+ throw new IllegalArgumentException("Unhandled parameter types: " +
+ Arrays.<Object>asList(data).toString());
+ }
+ }
+
+ private String getName(final CompositeNode data) {
+ if (data instanceof CompositeNodeWrapper) {
+ return ((CompositeNodeWrapper)data).getLocalName();
+ }
+ else if (data != null) {
+ return data.getNodeType().getLocalName();
+ }
+ else {
+ throw new IllegalArgumentException("Unhandled parameter types: " +
+ Arrays.<Object>asList(data).toString());
+ }
+ }
+
+ private TypeDefinition<? extends Object> _typeDefinition(final LeafSchemaNode node) {
+ TypeDefinition<?> baseType = node.getType();
+ while (baseType.getBaseType() != null) {
+ baseType = baseType.getBaseType();
+ }
+
+ return baseType;
+ }
+
+ private TypeDefinition<? extends Object> typeDefinition(final LeafListSchemaNode node) {
+ TypeDefinition<?> baseType = node.getType();
+ while (baseType.getBaseType() != null) {
+ baseType = baseType.getBaseType();
+ }
+
+ return baseType;
+ }
+
+ private TypeDefinition<? extends Object> typeDefinition(final DataSchemaNode node) {
+ if (node instanceof LeafListSchemaNode) {
+ return typeDefinition((LeafListSchemaNode)node);
+ }
+ else if (node instanceof LeafSchemaNode) {
+ return _typeDefinition((LeafSchemaNode)node);
+ }
+ else {
+ throw new IllegalArgumentException("Unhandled parameter types: " +
+ Arrays.<Object>asList(node).toString());
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.sal.restconf.impl
-
-import com.google.common.base.Preconditions
-import com.google.common.base.Splitter
-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.HashMap
-import java.util.List
-import java.util.Set
-import javax.ws.rs.core.Response
-import javax.ws.rs.core.UriInfo
-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.streams.listeners.Notificator
-import org.opendaylight.controller.sal.streams.websockets.WebSocketServer
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.Module
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
-import org.opendaylight.yangtools.yang.model.util.EmptyType
-import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder
-import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder
-
-import static javax.ws.rs.core.Response.Status.*
-
-class RestconfImpl implements RestconfService {
-
- val static RestconfImpl INSTANCE = new RestconfImpl
- val static MOUNT_POINT_MODULE_NAME = "ietf-netconf"
- val static REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd")
- val static RESTCONF_MODULE_DRAFT02_REVISION = "2013-10-19"
- val static RESTCONF_MODULE_DRAFT02_NAME = "ietf-restconf"
- val static RESTCONF_MODULE_DRAFT02_NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-restconf"
- val static RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE = "restconf"
- val static RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE = "restconf"
- val static RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE = "modules"
- val static RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE = "module"
- val static RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE = "streams"
- val static RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE = "stream"
- val static RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE = "operations"
- val static SAL_REMOTE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote"
- val static SAL_REMOTE_RPC_SUBSRCIBE = "create-data-change-event-subscription"
-
- @Property
- BrokerFacade broker
-
- @Property
- extension ControllerContext controllerContext
-
- private new() {
- if (INSTANCE !== null) {
- throw new IllegalStateException("Already instantiated");
- }
- }
-
- static def getInstance() {
- return INSTANCE
- }
-
- override getModules() {
- val restconfModule = getRestconfModule()
- val List<Node<?>> modulesAsData = new ArrayList
- val moduleSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)
- for (module : allModules) {
- modulesAsData.add(module.toModuleCompositeNode(moduleSchemaNode))
- }
- val modulesSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE)
- val modulesNode = NodeFactory.createImmutableCompositeNode(modulesSchemaNode.QName, null, modulesAsData)
- return new StructuredData(modulesNode, modulesSchemaNode, null)
- }
-
- override getAvailableStreams(){
- var Set<String> availableStreams = Notificator.getStreamNames();
- val List<Node<?>> streamsAsData = new ArrayList
- val streamSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE)
- for (String streamName:availableStreams){
- streamsAsData.add(streamName.toStreamCompositeNode(streamSchemaNode))
- }
- val streamsSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE)
- val streamsNode = NodeFactory.createImmutableCompositeNode(streamsSchemaNode.QName, null, streamsAsData)
- return new StructuredData(streamsNode, streamsSchemaNode, null)
- }
- override getModules(String identifier) {
- var Set<Module> modules = null
- var MountInstance mountPoint = null
- if (identifier.contains(ControllerContext.MOUNT)) {
- mountPoint = identifier.toMountPointIdentifier.mountPoint
- modules = mountPoint.allModules
- } else {
- throw new ResponseException(BAD_REQUEST, "URI has bad format. If modules behind mount point should be showed, URI has to end with " + ControllerContext.MOUNT)
- }
- val List<Node<?>> modulesAsData = new ArrayList
- val moduleSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)
- for (module : modules) {
- modulesAsData.add(module.toModuleCompositeNode(moduleSchemaNode))
- }
- val modulesSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE)
- val modulesNode = NodeFactory.createImmutableCompositeNode(modulesSchemaNode.QName, null, modulesAsData)
- return new StructuredData(modulesNode, modulesSchemaNode, mountPoint)
- }
-
- override getModule(String identifier) {
- val moduleNameAndRevision = identifier.moduleNameAndRevision
- var Module module = null
- var MountInstance mountPoint = null
- if (identifier.contains(ControllerContext.MOUNT)) {
- mountPoint = identifier.toMountPointIdentifier.mountPoint
- module = mountPoint.findModuleByNameAndRevision(moduleNameAndRevision)
- } else {
- module = findModuleByNameAndRevision(moduleNameAndRevision)
- }
- if (module === null) {
- throw new ResponseException(BAD_REQUEST,
- "Module with name '" + moduleNameAndRevision.localName + "' and revision '" +
- moduleNameAndRevision.revision + "' was not found.")
- }
- val moduleSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)
- val moduleNode = module.toModuleCompositeNode(moduleSchemaNode)
- return new StructuredData(moduleNode, moduleSchemaNode, mountPoint)
- }
-
- override getOperations() {
- return operationsFromModulesToStructuredData(allModules,null)
- }
-
- override getOperations(String identifier) {
- var Set<Module> modules = null
- var MountInstance mountPoint = null
- if (identifier.contains(ControllerContext.MOUNT)) {
- mountPoint = identifier.toMountPointIdentifier.mountPoint
- modules = mountPoint.allModules
- } else {
- throw new ResponseException(BAD_REQUEST, "URI has bad format. If operations behind mount point should be showed, URI has to end with " + ControllerContext.MOUNT)
- }
- return operationsFromModulesToStructuredData(modules,mountPoint)
- }
-
- private def StructuredData operationsFromModulesToStructuredData(Set<Module> modules,MountInstance mountPoint) {
- val List<Node<?>> operationsAsData = new ArrayList
- val operationsSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE)
- val fakeOperationsSchemaNode = new ContainerSchemaNodeBuilder(RESTCONF_MODULE_DRAFT02_NAME, 0, operationsSchemaNode.QName, operationsSchemaNode.path)
- for (module : modules) {
- for (rpc : module.rpcs) {
- operationsAsData.add(NodeFactory.createImmutableSimpleNode(rpc.QName, null, null))
- val fakeRpcSchemaNode = new LeafSchemaNodeBuilder(module.name, 0, rpc.QName, null)
- fakeRpcSchemaNode.setAugmenting(true)
- fakeRpcSchemaNode.setType(EmptyType.instance)
- fakeOperationsSchemaNode.addChildNode(fakeRpcSchemaNode.build)
- }
- }
- val operationsNode = NodeFactory.createImmutableCompositeNode(operationsSchemaNode.QName, null, operationsAsData)
- return new StructuredData(operationsNode, fakeOperationsSchemaNode.build, mountPoint)
- }
-
- private def Module getRestconfModule() {
- val restconfModule = findModuleByNameAndRevision(
- QName.create(RESTCONF_MODULE_DRAFT02_NAMESPACE, RESTCONF_MODULE_DRAFT02_REVISION,
- RESTCONF_MODULE_DRAFT02_NAME))
- if (restconfModule === null) {
- throw new ResponseException(INTERNAL_SERVER_ERROR, "Restconf module was not found.")
- }
- return restconfModule
- }
-
- private def QName getModuleNameAndRevision(String identifier) {
- val indexOfMountPointFirstLetter = identifier.indexOf(ControllerContext.MOUNT)
- var moduleNameAndRevision = "";
- if (indexOfMountPointFirstLetter !== -1) { // module and revision is behind mount point string
- moduleNameAndRevision = identifier.substring(indexOfMountPointFirstLetter + ControllerContext.MOUNT.length)
- } else (
- moduleNameAndRevision = identifier
- )
- val pathArgs = Lists.newArrayList(Splitter.on("/").omitEmptyStrings.split(moduleNameAndRevision))
- if (pathArgs.length < 2) {
- throw new ResponseException(BAD_REQUEST,
- "URI has bad format. End of URI should be in format 'moduleName/yyyy-MM-dd'")
- }
- try {
- val moduleName = pathArgs.head
- val moduleRevision = REVISION_FORMAT.parse(pathArgs.get(1))
- return QName.create(null, moduleRevision, moduleName)
- } catch(ParseException e) {
- throw new ResponseException(BAD_REQUEST, "URI has bad format. It should be 'moduleName/yyyy-MM-dd'")
- }
- }
-
- private def CompositeNode toStreamCompositeNode(String streamName, DataSchemaNode streamSchemaNode) {
- val List<Node<?>> streamNodeValues = new ArrayList
- val nameSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("name").head
- streamNodeValues.add(NodeFactory.createImmutableSimpleNode(nameSchemaNode.QName, null, streamName))
-
- val descriptionSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("description").head
- streamNodeValues.add(NodeFactory.createImmutableSimpleNode(descriptionSchemaNode.QName, null, "DESCRIPTION_PLACEHOLDER"))
-
- val replaySupportSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("replay-support").head
- streamNodeValues.add(NodeFactory.createImmutableSimpleNode(replaySupportSchemaNode.QName, null, true))
-
- val replayLogCreationTimeSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("replay-log-creation-time").head
- streamNodeValues.add(NodeFactory.createImmutableSimpleNode(replayLogCreationTimeSchemaNode.QName, null, ""))
-
- val eventsSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("events").head
- streamNodeValues.add(NodeFactory.createImmutableSimpleNode(eventsSchemaNode.QName, null, ""))
-
- return NodeFactory.createImmutableCompositeNode(streamSchemaNode.QName, null, streamNodeValues)
- }
- private def CompositeNode toModuleCompositeNode(Module module, DataSchemaNode moduleSchemaNode) {
- val List<Node<?>> moduleNodeValues = new ArrayList
- val nameSchemaNode = (moduleSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("name").head
- moduleNodeValues.add(NodeFactory.createImmutableSimpleNode(nameSchemaNode.QName, null, module.name))
- val revisionSchemaNode = (moduleSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("revision").head
- moduleNodeValues.add(NodeFactory.createImmutableSimpleNode(revisionSchemaNode.QName, null, REVISION_FORMAT.format(module.revision)))
- val namespaceSchemaNode = (moduleSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("namespace").head
- moduleNodeValues.add(NodeFactory.createImmutableSimpleNode(namespaceSchemaNode.QName, null, module.namespace.toString))
- val featureSchemaNode = (moduleSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("feature").head
- for (feature : module.features) {
- moduleNodeValues.add(NodeFactory.createImmutableSimpleNode(featureSchemaNode.QName, null, feature.QName.localName))
- }
- return NodeFactory.createImmutableCompositeNode(moduleSchemaNode.QName, null, moduleNodeValues)
- }
-
- private def DataSchemaNode getSchemaNode(Module restconfModule, String schemaNodeName) {
- val restconfGrouping = restconfModule.groupings.filter[g|g.QName.localName == RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE].head
- val restconfContainer = restconfGrouping.findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE).head
- if (schemaNodeName == RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE) {
- return (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE).head
- } else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE) {
- return (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE).head
- } else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE) {
- val modules = (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE).head
- return (modules as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE).head
- }else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE) {
- return (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE).head
- } else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE) {
- val modules = (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE).head
- return (modules as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE).head
- }
- return null
- }
-
- override getRoot() {
- return null;
- }
-
- override invokeRpc(String identifier, CompositeNode payload) {
- val rpc = resolveIdentifierInInvokeRpc(identifier)
- if (rpc.QName.namespace.toString == SAL_REMOTE_NAMESPACE && rpc.QName.localName == SAL_REMOTE_RPC_SUBSRCIBE) {
- val value = normalizeNode(payload, rpc.input, null)
- val pathNode = value?.getFirstSimpleByName(QName.create(rpc.QName, "path"))
- val pathValue = pathNode?.value
- if (pathValue === null && !(pathValue instanceof InstanceIdentifier)) {
- throw new ResponseException(INTERNAL_SERVER_ERROR, "Instance identifier was not normalized correctly.");
- }
- val pathIdentifier = (pathValue as InstanceIdentifier)
- var String streamName = null
- if (!pathIdentifier.path.nullOrEmpty) {
- streamName = Notificator.createStreamNameFromUri(pathIdentifier.toFullRestconfIdentifier)
- }
- if (streamName.nullOrEmpty) {
- throw new ResponseException(BAD_REQUEST, "Path is empty or contains data node which is not Container or List build-in type.");
- }
- val streamNameNode = NodeFactory.createImmutableSimpleNode(QName.create(rpc.output.QName, "stream-name"), null, streamName)
- val List<Node<?>> output = new ArrayList
- output.add(streamNameNode)
- val responseData = NodeFactory.createMutableCompositeNode(rpc.output.QName, null, output, null, null)
-
- if (!Notificator.existListenerFor(pathIdentifier)) {
- Notificator.createListener(pathIdentifier, streamName)
- }
-
- return new StructuredData(responseData, rpc.output, null)
- }
- return callRpc(identifier.rpcDefinition, payload)
- }
-
- override invokeRpc(String identifier, String noPayload) {
- if (!noPayload.nullOrEmpty) {
- throw new ResponseException(UNSUPPORTED_MEDIA_TYPE, "Content-Type contains unsupported Media Type.");
- }
- val rpc = resolveIdentifierInInvokeRpc(identifier)
- return callRpc(rpc, null)
- }
-
- private def resolveIdentifierInInvokeRpc(String identifier) {
- if (identifier.indexOf("/") === -1) {
- val identifierDecoded = identifier.urlPathArgDecode
- val rpc = identifierDecoded.rpcDefinition
- if (rpc !== null) {
- return rpc
- }
- throw new ResponseException(NOT_FOUND, "RPC does not exist.");
- }
- val 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(NOT_FOUND, slashErrorMsg);
- }
-
- private def StructuredData callRpc(RpcDefinition rpc, CompositeNode payload) {
- if (rpc === null) {
- throw new ResponseException(NOT_FOUND, "RPC does not exist.");
- }
- var CompositeNode rpcRequest;
- if (payload === null) {
- rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, null, null, null)
- } else {
- val value = normalizeNode(payload, rpc.input, null)
- val List<Node<?>> input = new ArrayList
- input.add(value)
- rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
- }
- val rpcResult = broker.invokeRpc(rpc.QName, rpcRequest);
- if (!rpcResult.successful) {
- throw new ResponseException(INTERNAL_SERVER_ERROR, "Operation failed")
- }
- if (rpcResult.result === null) {
- return null
- }
- return new StructuredData(rpcResult.result, rpc.output, null)
- }
-
- override readConfigurationData(String identifier) {
- val iiWithData = identifier.toInstanceIdentifier
- var CompositeNode data = null;
- if (iiWithData.mountPoint !== null) {
- data = broker.readConfigurationDataBehindMountPoint(iiWithData.mountPoint, iiWithData.getInstanceIdentifier)
- } else {
- data = broker.readConfigurationData(iiWithData.getInstanceIdentifier);
- }
- return new StructuredData(data, iiWithData.schemaNode, iiWithData.mountPoint)
- }
-
- override readOperationalData(String identifier) {
- val iiWithData = identifier.toInstanceIdentifier
- var CompositeNode data = null;
- if (iiWithData.mountPoint !== null) {
- data = broker.readOperationalDataBehindMountPoint(iiWithData.mountPoint, iiWithData.getInstanceIdentifier)
- } else {
- data = broker.readOperationalData(iiWithData.getInstanceIdentifier);
- }
- return new StructuredData(data, iiWithData.schemaNode, iiWithData.mountPoint)
- }
-
- override updateConfigurationData(String identifier, CompositeNode payload) {
- val iiWithData = identifier.toInstanceIdentifier
- val value = normalizeNode(payload, iiWithData.schemaNode, iiWithData.mountPoint)
- var RpcResult<TransactionStatus> status = null
- if (iiWithData.mountPoint !== null) {
- status = broker.commitConfigurationDataPutBehindMountPoint(iiWithData.mountPoint,
- iiWithData.instanceIdentifier, value).get()
- } else {
- status = broker.commitConfigurationDataPut(iiWithData.instanceIdentifier, value).get();
- }
- switch status.result {
- case TransactionStatus.COMMITED: Response.status(OK).build
- default: Response.status(INTERNAL_SERVER_ERROR).build
- }
- }
-
- override createConfigurationData(String identifier, CompositeNode payload) {
- if (payload.namespace === null) {
- throw new ResponseException(BAD_REQUEST,
- "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
- }
- var InstanceIdWithSchemaNode iiWithData;
- var CompositeNode value;
- if (payload.representsMountPointRootData) { // payload represents mount point data and URI represents path to the mount point
- if (identifier.endsWithMountPoint) {
- throw new ResponseException(BAD_REQUEST,
- "URI has bad format. URI should be without \"" + ControllerContext.MOUNT + "\" for POST operation.");
- }
- val completIdentifier = identifier.addMountPointIdentifier
- iiWithData = completIdentifier.toInstanceIdentifier
- value = normalizeNode(payload, iiWithData.schemaNode, iiWithData.mountPoint)
- } else {
- val uncompleteInstIdWithData = identifier.toInstanceIdentifier
- val parentSchema = uncompleteInstIdWithData.schemaNode as DataNodeContainer
- val module = uncompleteInstIdWithData.mountPoint.findModule(payload)
- if (module === null) {
- throw new ResponseException(BAD_REQUEST, "Module was not found for \"" + payload.namespace + "\"")
- }
- val schemaNode = parentSchema.findInstanceDataChildByNameAndNamespace(payload.name, module.namespace)
- value = normalizeNode(payload, schemaNode, uncompleteInstIdWithData.mountPoint)
- iiWithData = uncompleteInstIdWithData.addLastIdentifierFromData(value, schemaNode)
- }
- var RpcResult<TransactionStatus> status = null
- if (iiWithData.mountPoint !== null) {
- status = broker.commitConfigurationDataPostBehindMountPoint(iiWithData.mountPoint,
- iiWithData.instanceIdentifier, value)?.get();
- } else {
- status = broker.commitConfigurationDataPost(iiWithData.instanceIdentifier, value)?.get();
- }
- if (status === null) {
- return Response.status(ACCEPTED).build
- }
- switch status.result {
- case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
- default: Response.status(INTERNAL_SERVER_ERROR).build
- }
- }
-
- override createConfigurationData(CompositeNode payload) {
- if (payload.namespace === null) {
- throw new ResponseException(BAD_REQUEST,
- "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
- }
- val module = findModule(null, payload)
- if (module === null) {
- throw new ResponseException(BAD_REQUEST,
- "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)");
- }
- val schemaNode = module.findInstanceDataChildByNameAndNamespace(payload.name, module.namespace)
- val value = normalizeNode(payload, schemaNode, null)
- val iiWithData = addLastIdentifierFromData(null, value, schemaNode)
- var RpcResult<TransactionStatus> status = null
- if (iiWithData.mountPoint !== null) {
- status = broker.commitConfigurationDataPostBehindMountPoint(iiWithData.mountPoint,
- iiWithData.instanceIdentifier, value)?.get();
- } else {
- status = broker.commitConfigurationDataPost(iiWithData.instanceIdentifier, value)?.get();
- }
- if (status === null) {
- return Response.status(ACCEPTED).build
- }
- switch status.result {
- case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
- default: Response.status(INTERNAL_SERVER_ERROR).build
- }
- }
-
- override deleteConfigurationData(String identifier) {
- val iiWithData = identifier.toInstanceIdentifier
- var RpcResult<TransactionStatus> status = null
- if (iiWithData.mountPoint !== null) {
- status = broker.commitConfigurationDataDeleteBehindMountPoint(iiWithData.mountPoint,
- iiWithData.getInstanceIdentifier).get;
- } else {
- status = broker.commitConfigurationDataDelete(iiWithData.getInstanceIdentifier).get;
- }
- switch status.result {
- case TransactionStatus.COMMITED: Response.status(OK).build
- default: Response.status(INTERNAL_SERVER_ERROR).build
- }
- }
-
- override subscribeToStream(String identifier, UriInfo uriInfo) {
- val streamName = Notificator.createStreamNameFromUri(identifier)
- if (streamName.nullOrEmpty) {
- throw new ResponseException(BAD_REQUEST, "Stream name is empty.")
- }
- val listener = Notificator.getListenerFor(streamName);
- if (listener === null) {
- throw new ResponseException(BAD_REQUEST, "Stream was not found.")
- }
- broker.registerToListenDataChanges(listener)
- val uriBuilder = uriInfo.getAbsolutePathBuilder()
- val uriToWebsocketServer = uriBuilder.port(WebSocketServer.PORT).replacePath(streamName).build()
- return Response.status(OK).location(uriToWebsocketServer).build
- }
-
- private def dispatch URI namespace(CompositeNode data) {
- return data.nodeType.namespace
- }
-
- private def dispatch URI namespace(CompositeNodeWrapper data) {
- return data.namespace
- }
-
- private def dispatch String localName(CompositeNode data) {
- return data.nodeType.localName
- }
-
- private def dispatch String localName(CompositeNodeWrapper data) {
- return data.localName
- }
-
- private def dispatch Module findModule(MountInstance mountPoint, CompositeNode data) {
- if (mountPoint !== null) {
- return mountPoint.findModuleByNamespace(data.nodeType.namespace)
- } else {
- return findModuleByNamespace(data.nodeType.namespace)
- }
- }
-
- private def dispatch Module findModule(MountInstance mountPoint, CompositeNodeWrapper data) {
- Preconditions.checkNotNull(data.namespace)
- var Module module = null;
- if (mountPoint !== null) {
- module = mountPoint.findModuleByNamespace(data.namespace) // namespace from XML
- if (module === null) {
- module = mountPoint.findModuleByName(data.namespace.toString) // namespace (module name) from JSON
- }
- } else {
- module = data.namespace.findModuleByNamespace // namespace from XML
- if (module === null) {
- module = data.namespace.toString.findModuleByName // namespace (module name) from JSON
- }
- }
- return module
- }
-
- private def dispatch getName(CompositeNode data) {
- return data.nodeType.localName
- }
-
- private def dispatch getName(CompositeNodeWrapper data) {
- return data.localName
- }
-
- private def InstanceIdWithSchemaNode addLastIdentifierFromData(InstanceIdWithSchemaNode identifierWithSchemaNode,
- CompositeNode data, DataSchemaNode schemaOfData) {
- val iiOriginal = identifierWithSchemaNode?.instanceIdentifier
- var InstanceIdentifierBuilder iiBuilder = null
- if (iiOriginal === null) {
- iiBuilder = InstanceIdentifier.builder
- } else {
- iiBuilder = InstanceIdentifier.builder(iiOriginal)
- }
-
- if (schemaOfData instanceof ListSchemaNode) {
- iiBuilder.nodeWithKey(schemaOfData.QName, (schemaOfData as ListSchemaNode).resolveKeysFromData(data))
- } else {
- iiBuilder.node(schemaOfData.QName)
- }
- return new InstanceIdWithSchemaNode(iiBuilder.toInstance, schemaOfData, identifierWithSchemaNode?.mountPoint)
- }
-
- private def resolveKeysFromData(ListSchemaNode listNode, CompositeNode dataNode) {
- val keyValues = new HashMap<QName, Object>();
- for (key : listNode.keyDefinition) {
- val dataNodeKeyValueObject = dataNode.getSimpleNodesByName(key.localName)?.head?.value
- if (dataNodeKeyValueObject === null) {
- throw new ResponseException(BAD_REQUEST,
- "Data contains list \"" + dataNode.nodeType.localName + "\" which does not contain key: \"" +
- key.localName + "\"")
- }
- keyValues.put(key, dataNodeKeyValueObject);
- }
- return keyValues
- }
-
- private def endsWithMountPoint(String identifier) {
- return (identifier.endsWith(ControllerContext.MOUNT) || identifier.endsWith(ControllerContext.MOUNT + "/"))
- }
-
- private def representsMountPointRootData(CompositeNode data) {
- return ((data.namespace == SchemaContext.NAME.namespace || data.namespace == MOUNT_POINT_MODULE_NAME) &&
- data.localName == SchemaContext.NAME.localName)
- }
-
- private def addMountPointIdentifier(String identifier) {
- if (identifier.endsWith("/")) {
- return identifier + ControllerContext.MOUNT
- }
- return identifier + "/" + ControllerContext.MOUNT
- }
-
- private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema, MountInstance mountPoint) {
- if (schema === null) {
- throw new ResponseException(INTERNAL_SERVER_ERROR,
- "Data schema node was not found for " + node?.nodeType?.localName)
- }
- if (!(schema instanceof DataNodeContainer)) {
- throw new ResponseException(BAD_REQUEST, "Root element has to be container or list yang datatype.");
- }
- if (node instanceof CompositeNodeWrapper) {
- if ((node as CompositeNodeWrapper).changeAllowed) {
- try {
- normalizeNode(node as CompositeNodeWrapper, schema, null, mountPoint)
- } catch (NumberFormatException e) {
- throw new ResponseException(BAD_REQUEST,e.message)
- }
- }
- return (node as CompositeNodeWrapper).unwrap()
- }
- return node
- }
-
- private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment,
- MountInstance mountPoint) {
- if (schema === null) {
- throw new ResponseException(BAD_REQUEST,
- "Data has bad format.\n\"" + nodeBuilder.localName + "\" does not exist in yang schema.");
- }
-
- var QName currentAugment;
- if (nodeBuilder.qname !== null) {
- currentAugment = previousAugment
- } else {
- currentAugment = normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint)
- if (nodeBuilder.qname === null) {
- throw new ResponseException(BAD_REQUEST,
- "Data has bad format.\nIf data is in XML format then namespace for \"" + nodeBuilder.localName +
- "\" should be \"" + schema.QName.namespace + "\".\n" +
- "If data is in JSON format then module name for \"" + nodeBuilder.localName +
- "\" should be corresponding to namespace \"" + schema.QName.namespace + "\".");
- }
- }
-
- if (nodeBuilder instanceof CompositeNodeWrapper) {
- val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
- for (child : children) {
- val potentialSchemaNodes = (schema as DataNodeContainer).findInstanceDataChildrenByName(child.localName)
- if (potentialSchemaNodes.size > 1 && child.namespace === null) {
- val StringBuilder namespacesOfPotentialModules = new StringBuilder;
- for (potentialSchemaNode : potentialSchemaNodes) {
- namespacesOfPotentialModules.append(" ").append(potentialSchemaNode.QName.namespace.toString).append("\n")
- }
- throw new ResponseException(BAD_REQUEST,
- "Node \"" + child.localName + "\" is added as augment from more than one module. "
- + "Therefore node must have namespace (XML format) or module name (JSON format)."
- + "\nThe node is added as augment from modules with namespaces:\n" + namespacesOfPotentialModules)
- }
- var rightNodeSchemaFound = false
- for (potentialSchemaNode : potentialSchemaNodes) {
- if (!rightNodeSchemaFound) {
- val potentialCurrentAugment = normalizeNodeName(child, potentialSchemaNode, currentAugment,
- mountPoint)
- if (child.qname !== null) {
- normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint)
- rightNodeSchemaFound = true
- }
- }
- }
- if (!rightNodeSchemaFound) {
- throw new ResponseException(BAD_REQUEST,
- "Schema node \"" + child.localName + "\" was not found in module.")
- }
- }
- if (schema instanceof ListSchemaNode) {
- val listKeys = (schema as ListSchemaNode).keyDefinition
- for (listKey : listKeys) {
- var foundKey = false
- for (child : children) {
- if (child.unwrap.nodeType.localName == listKey.localName) {
- foundKey = true;
- }
- }
- if (!foundKey) {
- throw new ResponseException(BAD_REQUEST,
- "Missing key in URI \"" + listKey.localName + "\" of list \"" + schema.QName.localName +
- "\"")
- }
- }
- }
- } else if (nodeBuilder instanceof SimpleNodeWrapper) {
- val simpleNode = (nodeBuilder as SimpleNodeWrapper)
- val value = simpleNode.value
- var inputValue = value;
-
- if (schema.typeDefinition instanceof IdentityrefTypeDefinition) {
- if (value instanceof String) {
- inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null,value as String);
- } // else value is already instance of IdentityValuesDTO
- }
-
- val outputValue = RestCodec.from(schema.typeDefinition, mountPoint)?.deserialize(inputValue);
- simpleNode.setValue(outputValue)
- } else if (nodeBuilder instanceof EmptyNodeWrapper) {
- val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper
- if (schema instanceof LeafSchemaNode) {
- emptyNodeBuilder.setComposite(false);
- } else if (schema instanceof ContainerSchemaNode) {
-
- // FIXME: Add presence check
- emptyNodeBuilder.setComposite(true);
- }
- }
- }
-
- private def dispatch TypeDefinition<?> typeDefinition(LeafSchemaNode node) {
- var baseType = node.type
- while (baseType.baseType !== null) {
- baseType = baseType.baseType;
- }
- baseType
- }
-
- private def dispatch TypeDefinition<?> typeDefinition(LeafListSchemaNode node) {
- var TypeDefinition<?> baseType = node.type
- while (baseType.baseType !== null) {
- baseType = baseType.baseType;
- }
- baseType
- }
-
- private def QName normalizeNodeName(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment,
- MountInstance mountPoint) {
- var validQName = schema.QName
- var currentAugment = previousAugment;
- if (schema.augmenting) {
- currentAugment = schema.QName
- } else if (previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
- validQName = QName.create(currentAugment, schema.QName.localName);
- }
- var String moduleName = null;
- if (mountPoint === null) {
- moduleName = controllerContext.findModuleNameByNamespace(validQName.namespace);
- } else {
- moduleName = controllerContext.findModuleNameByNamespace(mountPoint, validQName.namespace)
- }
- if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
- nodeBuilder.namespace.toString == moduleName || nodeBuilder.namespace == MOUNT_POINT_MODULE_NAME) {
- nodeBuilder.qname = validQName
- }
- return currentAugment
- }
-
-}
--- /dev/null
+/*
+ * Copyright (c) ${year} Brocade Communications Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.Future;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.mount.MountInstance;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.ResponseException;
+import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
+import org.opendaylight.controller.sal.streams.listeners.Notificator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+
+/**
+ * Unit tests for BrokerFacade.
+ *
+ * @author Thomas Pantelis
+ */
+public class BrokerFacadeTest {
+
+ @Mock
+ DataBrokerService dataBroker;
+
+ @Mock
+ DataModificationTransaction mockTransaction;
+
+ @Mock
+ ConsumerSession mockConsumerSession;
+
+ @Mock
+ MountInstance mockMountInstance;
+
+ BrokerFacade brokerFacade = BrokerFacade.getInstance();
+
+ CompositeNode dataNode = TestUtils.readInputToCnSn( "/parts/ietf-interfaces_interfaces.xml",
+ XmlToCompositeNodeProvider.INSTANCE );
+
+ QName qname = QName.create( "node" );
+
+ InstanceIdentifier instanceID = InstanceIdentifier.builder().node( qname ).toInstance();
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks( this );
+
+ brokerFacade.setDataService( dataBroker );
+ brokerFacade.setContext( mockConsumerSession );
+ }
+
+ @Test
+ public void testReadConfigurationData() {
+ when( dataBroker.readConfigurationData( instanceID ) ).thenReturn( dataNode );
+
+ CompositeNode actualNode = brokerFacade.readConfigurationData( instanceID );
+
+ assertSame( "readConfigurationData", dataNode, actualNode );
+ }
+
+ @Test
+ public void testReadConfigurationDataBehindMountPoint() {
+ when( mockMountInstance.readConfigurationData( instanceID ) ).thenReturn( dataNode );
+
+ CompositeNode actualNode = brokerFacade.readConfigurationDataBehindMountPoint(
+ mockMountInstance, instanceID );
+
+ assertSame( "readConfigurationDataBehindMountPoint", dataNode, actualNode );
+ }
+
+ @Test
+ public void testReadOperationalData() {
+ when( dataBroker.readOperationalData( instanceID ) ).thenReturn( dataNode );
+
+ CompositeNode actualNode = brokerFacade.readOperationalData( instanceID );
+
+ assertSame( "readOperationalData", dataNode, actualNode );
+ }
+
+ @Test
+ public void testReadOperationalDataBehindMountPoint() {
+ when( mockMountInstance.readOperationalData( instanceID ) ).thenReturn( dataNode );
+
+ CompositeNode actualNode = brokerFacade.readOperationalDataBehindMountPoint(
+ mockMountInstance, instanceID );
+
+ assertSame( "readOperationalDataBehindMountPoint", dataNode, actualNode );
+ }
+
+ @Test(expected=ResponseException.class)
+ public void testReadOperationalDataWithNoDataBroker() {
+ brokerFacade.setDataService( null );
+
+ brokerFacade.readOperationalData( instanceID );
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testInvokeRpc() {
+ RpcResult<CompositeNode> expResult = mock( RpcResult.class );
+ Future<RpcResult<CompositeNode>> future = Futures.immediateFuture( expResult );
+ when( mockConsumerSession.rpc( qname, dataNode ) ).thenReturn( future );
+
+ RpcResult<CompositeNode> actualResult = brokerFacade.invokeRpc( qname, dataNode );
+
+ assertSame( "invokeRpc", expResult, actualResult );
+ }
+
+ @Test(expected=ResponseException.class)
+ public void testInvokeRpcWithException() {
+ Exception mockEx = new Exception( "mock" );
+ Future<RpcResult<CompositeNode>> future = Futures.immediateFailedFuture( mockEx );
+ when( mockConsumerSession.rpc( qname, dataNode ) ).thenReturn( future );
+
+ brokerFacade.invokeRpc( qname, dataNode );
+ }
+
+ @Test(expected=ResponseException.class)
+ public void testInvokeRpcWithNoConsumerSession() {
+ brokerFacade.setContext( null );
+
+ brokerFacade.invokeRpc( qname, dataNode );
+ }
+
+ @Test
+ public void testCommitConfigurationDataPut() {
+ Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture( null );
+
+ when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
+ mockTransaction.putConfigurationData( instanceID, dataNode );
+ when( mockTransaction.commit() ).thenReturn( expFuture );
+
+ Future<RpcResult<TransactionStatus>> actualFuture =
+ brokerFacade.commitConfigurationDataPut( instanceID, dataNode );
+
+ assertSame( "invokeRpc", expFuture, actualFuture );
+
+ InOrder inOrder = inOrder( dataBroker, mockTransaction );
+ inOrder.verify( dataBroker ).beginTransaction();
+ inOrder.verify( mockTransaction ).putConfigurationData( instanceID, dataNode );
+ inOrder.verify( mockTransaction ).commit();
+ }
+
+ @Test
+ public void testCommitConfigurationDataPutBehindMountPoint() {
+ Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture( null );
+
+ when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
+ mockTransaction.putConfigurationData( instanceID, dataNode );
+ when( mockTransaction.commit() ).thenReturn( expFuture );
+
+ Future<RpcResult<TransactionStatus>> actualFuture =
+ brokerFacade.commitConfigurationDataPutBehindMountPoint(
+ mockMountInstance, instanceID, dataNode );
+
+ assertSame( "invokeRpc", expFuture, actualFuture );
+
+ InOrder inOrder = inOrder( mockMountInstance, mockTransaction );
+ inOrder.verify( mockMountInstance ).beginTransaction();
+ inOrder.verify( mockTransaction ).putConfigurationData( instanceID, dataNode );
+ inOrder.verify( mockTransaction ).commit();
+ }
+
+ @Test
+ public void testCommitConfigurationDataPost() {
+ Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture( null );
+
+ Map<InstanceIdentifier, CompositeNode> nodeMap =
+ new ImmutableMap.Builder<InstanceIdentifier,CompositeNode>()
+ .put( instanceID, dataNode ).build();
+
+ when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
+ mockTransaction.putConfigurationData( instanceID, dataNode );
+ when( mockTransaction.getCreatedConfigurationData() ).thenReturn( nodeMap );
+ when( mockTransaction.commit() ).thenReturn( expFuture );
+
+ Future<RpcResult<TransactionStatus>> actualFuture =
+ brokerFacade.commitConfigurationDataPost( instanceID, dataNode );
+
+ assertSame( "commitConfigurationDataPut", expFuture, actualFuture );
+
+ InOrder inOrder = inOrder( dataBroker, mockTransaction );
+ inOrder.verify( dataBroker ).beginTransaction();
+ inOrder.verify( mockTransaction ).putConfigurationData( instanceID, dataNode );
+ inOrder.verify( mockTransaction ).commit();
+ }
+
+ @Test
+ 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();
+ }
+
+ @Test
+ public void testCommitConfigurationDataPostBehindMountPoint() {
+ Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture( null );
+
+ Map<InstanceIdentifier, CompositeNode> nodeMap =
+ new ImmutableMap.Builder<InstanceIdentifier,CompositeNode>()
+ .put( instanceID, dataNode ).build();
+
+ when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
+ mockTransaction.putConfigurationData( instanceID, dataNode );
+ when( mockTransaction.getCreatedConfigurationData() ).thenReturn( nodeMap );
+ when( mockTransaction.commit() ).thenReturn( expFuture );
+
+ Future<RpcResult<TransactionStatus>> actualFuture =
+ brokerFacade.commitConfigurationDataPostBehindMountPoint( mockMountInstance,
+ instanceID, dataNode );
+
+ assertSame( "commitConfigurationDataPostBehindMountPoint", expFuture, actualFuture );
+
+ InOrder inOrder = inOrder( mockMountInstance, mockTransaction );
+ inOrder.verify( mockMountInstance ).beginTransaction();
+ inOrder.verify( mockTransaction ).putConfigurationData( instanceID, dataNode );
+ inOrder.verify( mockTransaction ).commit();
+ }
+
+ @Test
+ 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();
+ }
+
+ @Test
+ public void testCommitConfigurationDataDelete() {
+ Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture( null );
+
+ when( dataBroker.beginTransaction() ).thenReturn( mockTransaction );
+ mockTransaction.removeConfigurationData( instanceID );
+ when( mockTransaction.commit() ).thenReturn( expFuture );
+
+ Future<RpcResult<TransactionStatus>> actualFuture =
+ brokerFacade.commitConfigurationDataDelete( instanceID );
+
+ assertSame( "commitConfigurationDataDelete", expFuture, actualFuture );
+
+ InOrder inOrder = inOrder( dataBroker, mockTransaction );
+ inOrder.verify( dataBroker ).beginTransaction();
+ inOrder.verify( mockTransaction ).removeConfigurationData( instanceID );
+ inOrder.verify( mockTransaction ).commit();
+ }
+
+ @Test
+ public void testCommitConfigurationDataDeleteBehindMountPoint() {
+ Future<RpcResult<TransactionStatus>> expFuture = Futures.immediateFuture( null );
+
+ when( mockMountInstance.beginTransaction() ).thenReturn( mockTransaction );
+ mockTransaction.removeConfigurationData( instanceID );
+ when( mockTransaction.commit() ).thenReturn( expFuture );
+
+ Future<RpcResult<TransactionStatus>> actualFuture =
+ brokerFacade.commitConfigurationDataDeleteBehindMountPoint(
+ mockMountInstance, instanceID );
+
+ assertSame( "commitConfigurationDataDeleteBehindMountPoint", expFuture, actualFuture );
+
+ InOrder inOrder = inOrder( mockMountInstance, mockTransaction );
+ inOrder.verify( mockMountInstance ).beginTransaction();
+ inOrder.verify( mockTransaction ).removeConfigurationData( instanceID );
+ inOrder.verify( mockTransaction ).commit();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRegisterToListenDataChanges() {
+ ListenerAdapter listener = Notificator.createListener( instanceID, "stream" );
+
+ ListenerRegistration<DataChangeListener> mockRegistration = mock( ListenerRegistration.class );
+ when( dataBroker.registerDataChangeListener( instanceID, listener ) )
+ .thenReturn( mockRegistration );
+
+ brokerFacade.registerToListenDataChanges( listener );
+
+ verify( dataBroker ).registerDataChangeListener( instanceID, listener );
+
+ assertEquals( "isListening", true, listener.isListening() );
+
+ brokerFacade.registerToListenDataChanges( listener );
+ verifyNoMoreInteractions( dataBroker );
+ }
+}
import org.opendaylight.yangtools.restconf.client.api.UnsupportedProtocolException;
import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public SalRemoteClientImpl(final URL url) {
Preconditions.checkNotNull(url);
- this.mappingService = new RuntimeGeneratedMappingServiceImpl();
- this.mappingService.setPool(ClassPool.getDefault());
- this.mappingService.init();
+ this.mappingService = new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault());
final ModuleInfoBackedContext moduleInfo = ModuleInfoBackedContext.create();
moduleInfo.addModuleInfos(BindingReflections.loadModuleInfos());
Uri destPortUri = destPort.getValue().firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
Action outputToControllerAction = new ActionBuilder() //
+ .setOrder(0)
.setAction(new OutputActionCaseBuilder() //
.setOutputAction(new OutputActionBuilder() //
.setMaxLength(new Integer(0xffff)) //
// Wrap our Apply Action in an Instruction
Instruction applyActionsInstruction = new InstructionBuilder() //
+ .setOrder(0)
.setInstruction(new ApplyActionsCaseBuilder()//
.setApplyActions(applyActions) //
.build()) //
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Export-Package>org.opendaylight.controller.sample.toaster.provider.api,
- org.opendaylight.controller.config.yang.toaster-consumer,</Export-Package>
- <Import-Package>*</Import-Package>
- </instructions>
- </configuration>
</plugin>
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
--- /dev/null
+/**
+* Generated file
+
+* Generated from: yang module name: toaster-consumer-impl yang module local name: toaster-consumer-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Feb 05 11:31:30 CET 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.config.kitchen_service.impl;
+
+import org.opendaylight.controller.config.yang.config.kitchen_service.impl.AbstractKitchenServiceModule;
+import org.opendaylight.controller.sample.kitchen.api.EggsType;
+import org.opendaylight.controller.sample.kitchen.api.KitchenService;
+import org.opendaylight.controller.sample.kitchen.impl.KitchenServiceImpl;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+*
+*/
+public final class KitchenServiceModule extends AbstractKitchenServiceModule {
+ private static final Logger log = LoggerFactory.getLogger(KitchenServiceModule.class);
+
+ public KitchenServiceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public KitchenServiceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ KitchenServiceModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ protected void customValidation(){
+ // No need to validate dependencies, since all dependencies have mandatory true flag in yang
+ // config-subsystem will perform the validation
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ ToasterService toasterService = getRpcRegistryDependency().getRpcService(ToasterService.class);
+
+ final KitchenServiceImpl kitchenService = new KitchenServiceImpl(toasterService);
+
+ final Registration<NotificationListener> toasterListenerReg =
+ getNotificationServiceDependency().registerNotificationListener( kitchenService );
+
+ final KitchenServiceRuntimeRegistration runtimeReg =
+ getRootRuntimeBeanRegistratorWrapper().register( kitchenService );
+
+ final class AutoCloseableKitchenService implements KitchenService, AutoCloseable {
+
+ @Override
+ public void close() throws Exception {
+ toasterListenerReg.close();
+ runtimeReg.close();
+ log.info("Toaster consumer (instance {}) torn down.", this);
+ }
+
+ @Override
+ public boolean makeBreakfast( EggsType eggs, Class<? extends ToastType> toast, int toastDoneness ) {
+ return kitchenService.makeBreakfast( eggs, toast, toastDoneness );
+ }
+ }
+
+ AutoCloseable ret = new AutoCloseableKitchenService();
+ log.info("KitchenService (instance {}) initialized.", ret );
+ return ret;
+ }
+}
*
* Do not modify this file unless it is present under src/main directory
*/
-package org.opendaylight.controller.config.yang.config.toaster_consumer.impl;
+package org.opendaylight.controller.config.yang.config.kitchen_service.impl;
+
+import org.opendaylight.controller.config.yang.config.kitchen_service.impl.AbstractKitchenServiceModuleFactory;
/**
*
*/
-public class ToasterConsumerModuleFactory extends org.opendaylight.controller.config.yang.config.toaster_consumer.impl.AbstractToasterConsumerModuleFactory
+public class KitchenServiceModuleFactory extends AbstractKitchenServiceModuleFactory
{
+++ /dev/null
-/**
-* Generated file
-
-* Generated from: yang module name: toaster-consumer-impl yang module local name: toaster-consumer-impl
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Wed Feb 05 11:31:30 CET 2014
-*
-* Do not modify this file unless it is present under src/main directory
-*/
-package org.opendaylight.controller.config.yang.config.toaster_consumer.impl;
-
-import org.opendaylight.controller.sal.binding.api.NotificationListener;
-import org.opendaylight.controller.sample.toaster.provider.api.ToastConsumer;
-import org.opendaylight.controller.sample.toaster.provider.impl.ToastConsumerImpl;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastDone;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
-import org.opendaylight.yangtools.concepts.Registration;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
-*
-*/
-public final class ToasterConsumerModule extends org.opendaylight.controller.config.yang.config.toaster_consumer.impl.AbstractToasterConsumerModule
- {
- private static final Logger log = LoggerFactory.getLogger(ToasterConsumerModule.class);
-
- public ToasterConsumerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(identifier, dependencyResolver);
- }
-
- public ToasterConsumerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
- ToasterConsumerModule oldModule, java.lang.AutoCloseable oldInstance) {
-
- super(identifier, dependencyResolver, oldModule, oldInstance);
- }
-
- @Override
- protected void customValidation(){
- // No need to validate dependencies, since all dependencies have mandatory true flag in yang
- // config-subsystem will perform the validation
- }
-
- @Override
- public java.lang.AutoCloseable createInstance() {
- ToasterService toasterService = getRpcRegistryDependency().getRpcService(ToasterService.class);
-
- final ToastConsumerImpl consumer = new ToastConsumerImpl(toasterService);
- final Registration<NotificationListener<ToastDone>> notificationRegistration = getNotificationServiceDependency()
- .registerNotificationListener(ToastDone.class, consumer);
-
- final ToasterConsumerRuntimeRegistration runtimeRegistration = getRootRuntimeBeanRegistratorWrapper().register(consumer);
-
- final class AutoCloseableToastConsumer implements AutoCloseable, ToastConsumer {
-
- @Override
- public void close() throws Exception {
- runtimeRegistration.close();
- notificationRegistration.close();
- log.info("Toaster consumer (instance {}) torn down.", this);
- }
-
- @Override
- public boolean createToast(Class<? extends ToastType> type, int doneness) {
- return consumer.createToast(type, doneness);
- }
- }
-
- AutoCloseable ret = new AutoCloseableToastConsumer();
- log.info("Toaster consumer (instance {}) initialized.", ret);
- return ret;
- }
-}
--- /dev/null
+package org.opendaylight.controller.sample.kitchen.api;
+
+public enum EggsType {
+ SCRAMBLED,
+ OVER_EASY,
+ POACHED
+}
--- /dev/null
+package org.opendaylight.controller.sample.kitchen.api;
+
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
+
+public interface KitchenService {
+ boolean makeBreakfast( EggsType eggs, Class<? extends ToastType> toast, int toastDoneness );
+}
--- /dev/null
+package org.opendaylight.controller.sample.kitchen.impl;
+
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.config.yang.config.kitchen_service.impl.KitchenServiceRuntimeMXBean;
+import org.opendaylight.controller.sample.kitchen.api.EggsType;
+import org.opendaylight.controller.sample.kitchen.api.KitchenService;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterListener;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBread;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener {
+
+ private static final Logger log = LoggerFactory.getLogger( KitchenServiceImpl.class );
+
+ private final ToasterService toaster;
+
+ private volatile boolean toasterOutOfBread;
+
+ public KitchenServiceImpl(ToasterService toaster) {
+ this.toaster = toaster;
+ }
+
+ @Override
+ public boolean makeBreakfast( EggsType eggs, Class<? extends ToastType> toast, int toastDoneness ) {
+
+ if( toasterOutOfBread )
+ {
+ log.info( "We're out of toast but we can make eggs" );
+ return true;
+ }
+
+ // Access the ToasterService to make the toast.
+ // We don't actually make the eggs for this example - sorry.
+ MakeToastInputBuilder toastInput = new MakeToastInputBuilder();
+ toastInput.setToasterDoneness( (long) toastDoneness);
+ toastInput.setToasterToastType( toast );
+
+ try {
+ RpcResult<Void> result = toaster.makeToast( toastInput.build() ).get();
+
+ if( result.isSuccessful() ) {
+ log.info( "makeToast succeeded" );
+ } else {
+ log.warn( "makeToast failed: " + result.getErrors() );
+ }
+
+ return result.isSuccessful();
+ } catch( InterruptedException | ExecutionException e ) {
+ log.warn( "Error occurred during toast creation" );
+ }
+ return false;
+ }
+
+ @Override
+ public Boolean makeScrambledWithWheat() {
+ return makeBreakfast( EggsType.SCRAMBLED, WheatBread.class, 2 );
+ }
+
+ /**
+ * Implemented from the ToasterListener interface.
+ */
+ @Override
+ public void onToasterOutOfBread( ToasterOutOfBread notification ) {
+ log.info( "ToasterOutOfBread notification" );
+ toasterOutOfBread = true;
+ }
+
+ /**
+ * Implemented from the ToasterListener interface.
+ */
+ @Override
+ public void onToasterRestocked( ToasterRestocked notification ) {
+ log.info( "ToasterRestocked notification - amountOfBread: " + notification.getAmountOfBread() );
+ toasterOutOfBread = false;
+ }
+}
+++ /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.sample.toaster.provider.api;
-
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType;
-
-public interface ToastConsumer {
-
- boolean createToast(Class<? extends ToastType> type,int doneness);
-
-}
+++ /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.sample.toaster.provider.impl;
-
-import java.util.concurrent.ExecutionException;
-
-import org.opendaylight.controller.config.yang.config.toaster_consumer.impl.ToasterConsumerRuntimeMXBean;
-import org.opendaylight.controller.sal.binding.api.NotificationListener;
-import org.opendaylight.controller.sample.toaster.provider.api.ToastConsumer;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.*;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ToastConsumerImpl implements
- ToastConsumer,
- NotificationListener<ToastDone>,ToasterConsumerRuntimeMXBean {
-
- private static final Logger log = LoggerFactory.getLogger(ToastConsumerImpl.class);
-
- private ToasterService toaster;
-
- public ToastConsumerImpl(ToasterService toaster) {
- this.toaster = toaster;
- }
-
- @Override
- public boolean createToast(Class<? extends ToastType> type, int doneness) {
- MakeToastInputBuilder toastInput = new MakeToastInputBuilder();
- toastInput.setToasterDoneness((long) doneness);
- toastInput.setToasterToastType(type);
-
- try {
- RpcResult<Void> result = toaster.makeToast(toastInput.build()).get();
-
- if (result.isSuccessful()) {
- log.trace("Toast was successfully finished");
- } else {
- log.warn("Toast was not successfully finished");
- }
- return result.isSuccessful();
- } catch (InterruptedException | ExecutionException e) {
- log.warn("Error occurred during toast creation");
- }
- return false;
-
- }
-
- @Override
- public void onNotification(ToastDone notification) {
- log.trace("ToastDone Notification Received: {} ",notification.getToastStatus());
- }
-
- @Override
- public Boolean makeHashBrownToast(Integer doneness) {
- return createToast(HashBrown.class, doneness);
- }
-}
// vi: set smarttab et sw=4 tabstop=4:
-module toaster-consumer-impl {
+module kitchen-service-impl {
yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl";
- prefix "toaster-consumer-impl";
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl";
+ prefix "kitchen-service-impl";
import config { prefix config; revision-date 2013-04-05; }
import rpc-context { prefix rpcx; revision-date 2013-06-17; }
- import toaster-consumer { prefix toaster-consumer; revision-date 2014-01-31; }
import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
description
"This module contains the base YANG definitions for
- toaster-consumer impl implementation.";
+ kitchen-service impl implementation.";
revision "2014-01-31" {
description
"Initial revision.";
}
- // This is the definition of a service implementation
- identity toaster-consumer-impl {
+ // This is the definition of kitchen service interface identity.
+ identity kitchen-service {
+ base "config:service-type";
+ config:java-class "org.opendaylight.controller.sample.kitchen.api.KitchenService";
+ }
+
+ // This is the definition of kitchen service implementation module identity.
+ identity kitchen-service-impl {
base config:module-type;
- config:provided-service toaster-consumer:toaster-consumer;
- config:java-name-prefix ToasterConsumer;
+ config:provided-service kitchen-service;
+ config:java-name-prefix KitchenService;
}
augment "/config:modules/config:module/config:configuration" {
- case toaster-consumer-impl {
- when "/config:modules/config:module/config:type = 'toaster-consumer-impl'";
+ case kitchen-service-impl {
+ when "/config:modules/config:module/config:type = 'kitchen-service-impl'";
container rpc-registry {
uses config:service-ref {
}
}
}
-
}
}
-
+
augment "/config:modules/config:module/config:state" {
- case toaster-consumer-impl {
- when "/config:modules/config:module/config:type = 'toaster-consumer-impl'";
- rpcx:rpc-context-instance "make-hash-brown-toast-rpc";
+ case kitchen-service-impl {
+ when "/config:modules/config:module/config:type = 'kitchen-service-impl'";
+
+ rpcx:rpc-context-instance "make-scrambled-with-wheat-rpc";
}
}
- identity make-hash-brown-toast-rpc;
+ identity make-scrambled-with-wheat-rpc;
- rpc make-hash-brown-toast {
+ rpc make-scrambled-with-wheat {
+ description
+ "Shortcut JMX call to make breakfast with scrambled eggs and wheat toast for testing.";
+
input {
uses rpcx:rpc-context-ref {
refine context-instance {
- rpcx:rpc-context-instance make-hash-brown-toast-rpc;
+ rpcx:rpc-context-instance make-scrambled-with-wheat-rpc;
}
}
- leaf doneness {
- type uint16;
- }
}
+
output {
leaf result {
type boolean;
+++ /dev/null
-// vi: set smarttab et sw=4 tabstop=4:
-module toaster-consumer {
-
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer";
- prefix "toaster-consumer";
-
- import config { prefix config; revision-date 2013-04-05; }
-
- description
- "This module contains the base YANG definitions for
- toaster-consumer services.";
-
- revision "2014-01-31" {
- description
- "Initial revision.";
- }
-
- // This is the definition of a service
- identity toaster-consumer {
-
- base "config:service-type";
-
- config:java-class "org.opendaylight.controller.sample.toaster.provider.api.ToastConsumer";
- }
-}
\ No newline at end of file
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-it</artifactId>
- <version>1.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller.samples</groupId>
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.opendaylight.controller.sample.toaster.provider.api.ToastConsumer;
+import org.opendaylight.controller.sample.kitchen.api.EggsType;
+import org.opendaylight.controller.sample.kitchen.api.KitchenService;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.HashBrown;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WhiteBread;
import org.ops4j.pax.exam.Configuration;
import javax.inject.Inject;
import javax.management.MBeanServer;
import javax.management.ObjectName;
+
import java.lang.management.ManagementFactory;
import static org.junit.Assert.assertEquals;
@Inject
@Filter(timeout=60*1000)
- ToastConsumer toastConsumer;
+ KitchenService kitchenService;
@Configuration
public Option[] config() {
public void testToaster() throws Exception {
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
- ObjectName consumerOn = new ObjectName("org.opendaylight.controller:instanceName=toaster-consumer-impl,type=RuntimeBean,moduleFactoryName=toaster-consumer-impl");
ObjectName providerOn = new ObjectName("org.opendaylight.controller:instanceName=toaster-provider-impl,type=RuntimeBean,moduleFactoryName=toaster-provider-impl");
long toastsMade = (long) platformMBeanServer.getAttribute(providerOn, "ToastsMade");
boolean toasts = true;
// Make toasts using OSGi service
- toasts &= toastConsumer.createToast(HashBrown.class, 4);
- toasts &= toastConsumer.createToast(WhiteBread.class, 8);
-
- // Make toast using JMX/config-subsystem
- toasts &= (Boolean)platformMBeanServer.invoke(consumerOn, "makeHashBrownToast", new Object[]{4}, new String[]{Integer.class.getName()});
+ toasts &= kitchenService.makeBreakfast( EggsType.SCRAMBLED, HashBrown.class, 4);
+ toasts &= kitchenService.makeBreakfast( EggsType.POACHED, WhiteBread.class, 8 );
- Assert.assertTrue("Not all toasts done by " + toastConsumer, toasts);
+ Assert.assertTrue("Not all toasts done by " + kitchenService, toasts);
// Verify toasts made count on provider via JMX/config-subsystem
toastsMade = (long) platformMBeanServer.getAttribute(providerOn, "ToastsMade");
- assertEquals(3, toastsMade);
+ assertEquals(2, toastsMade);
}
}
<snapshots>
<snapshot>
<required-capabilities>
- <capability>urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27</capability>
+ <!-- <capability>urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27</capability>-->
<capability>
urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28
</capability>
urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28
</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&revision=2013-07-16</capability>
- <capability>urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09
- </capability>
+ <!-- <capability>urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09</capability>-->
<capability>
urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28
</capability>
<capability>http://netconfcentral.org/ns/toaster?module=toaster&revision=2009-11-20</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer?module=toaster-consumer&revision=2014-01-31</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl?module=toaster-consumer-impl&revision=2014-01-31</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider?module=toaster-provider&revision=2014-01-31</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&revision=2014-01-31</capability>
<capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&revision=2014-01-31</capability>
</required-capabilities>
<name>binding-rpc-broker</name>
</rpc-registry>
+ <data-broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <name>ref_binding-data-broker</name>
+ </data-broker>
+
<notification-service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
binding:binding-notification-service
</module>
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl">
- prefix:toaster-consumer-impl
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+ prefix:kitchen-service-impl
</type>
- <name>toaster-consumer-impl</name>
+ <name>kitchen-service-impl</name>
<rpc-registry>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
</modules>
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+ kitchen:kitchen-service
+ </type>
+ <instance>
+ <name>kitchen-service</name>
+ <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
+ </instance>
+ </service>
<service>
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
dom:schema-service
package org.opendaylight.controller.config.yang.config.toaster_provider.impl;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.controller.sample.toaster.provider.OpendaylightToaster;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterData;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// Register to md-sal
opendaylightToaster.setNotificationProvider(getNotificationServiceDependency());
- opendaylightToaster.setDataProvider(getDataBrokerDependency());
+
+ DataProviderService dataBrokerService = getDataBrokerDependency();
+ opendaylightToaster.setDataProvider(dataBrokerService);
+
+ final ListenerRegistration<DataChangeListener> dataChangeListenerRegistration =
+ dataBrokerService.registerDataChangeListener( OpendaylightToaster.TOASTER_IID, opendaylightToaster );
+
final BindingAwareBroker.RpcRegistration<ToasterService> rpcRegistration = getRpcRegistryDependency()
.addRpcImplementation(ToasterService.class, opendaylightToaster);
// Wrap toaster as AutoCloseable and close registrations to md-sal at
// close()
- final class AutoCloseableToaster implements AutoCloseable, ToasterData {
+ final class AutoCloseableToaster implements AutoCloseable {
@Override
public void close() throws Exception {
+ dataChangeListenerRegistration.close();
rpcRegistration.close();
runtimeReg.close();
opendaylightToaster.close();
log.info("Toaster provider (instance {}) torn down.", this);
}
-
- @Override
- public Toaster getToaster() {
- return opendaylightToaster.getToaster();
- }
}
AutoCloseable ret = new AutoCloseableToaster();
*/
package org.opendaylight.controller.sample.toaster.provider;
+import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicLong;
import org.opendaylight.controller.config.yang.config.toaster_provider.impl.ToasterProviderRuntimeMXBean;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.common.util.RpcErrors;
import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.DisplayString;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastDone.ToastStatus;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastDoneBuilder;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.Toaster.ToasterStatus;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.RestockToasterInput;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterBuilder;
-import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterData;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterOutOfBreadBuilder;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked;
+import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestockedBuilder;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import com.google.common.util.concurrent.Futures;
-public class OpendaylightToaster implements ToasterData, ToasterService, ToasterProviderRuntimeMXBean, AutoCloseable {
+public class OpendaylightToaster implements ToasterService, ToasterProviderRuntimeMXBean,
+ DataChangeListener, AutoCloseable {
- private static final Logger log = LoggerFactory.getLogger(OpendaylightToaster.class);
- private static final InstanceIdentifier<Toaster> toasterIID = InstanceIdentifier.builder(Toaster.class).build();
+ private static final Logger LOG = LoggerFactory.getLogger(OpendaylightToaster.class);
- private static final DisplayString toasterManufacturer = new DisplayString("Opendaylight");
- private static final DisplayString toasterModelNumber = new DisplayString("Model 1 - Binding Aware");
+ public static final InstanceIdentifier<Toaster> TOASTER_IID = InstanceIdentifier.builder(Toaster.class).build();
+
+ private static final DisplayString TOASTER_MANUFACTURER = new DisplayString("Opendaylight");
+ private static final DisplayString TOASTER_MODEL_NUMBER = new DisplayString("Model 1 - Binding Aware");
private NotificationProviderService notificationProvider;
private DataBrokerService dataProvider;
+
private final ExecutorService executor;
- private Future<RpcResult<Void>> currentTask;
+ // As you will see we are using multiple threads here. Therefore we need to be careful about concurrency.
+ // In this case we use the taskLock to provide synchronization for the current task.
+ private volatile Future<RpcResult<Void>> currentTask;
+ private final Object taskLock = new Object();
+
+ private final AtomicLong amountOfBreadInStock = new AtomicLong( 100 );
+
+ private final AtomicLong toastsMade = new AtomicLong(0);
+
+ // Thread safe holder for our darkness multiplier.
+ private final AtomicLong darknessFactor = new AtomicLong( 1000 );
public OpendaylightToaster() {
executor = Executors.newFixedThreadPool(1);
}
+ public void setNotificationProvider(NotificationProviderService salService) {
+ this.notificationProvider = salService;
+ }
+
+ public void setDataProvider(DataBrokerService salDataProvider) {
+ this.dataProvider = salDataProvider;
+ updateStatus();
+ }
+
+ /**
+ * Implemented from the AutoCloseable interface.
+ */
@Override
- public synchronized Toaster getToaster() {
- ToasterBuilder tb = new ToasterBuilder();
- tb //
- .setToasterManufacturer(toasterManufacturer) //
- .setToasterModelNumber(toasterModelNumber) //
- .setToasterStatus(currentTask == null ? ToasterStatus.Up : ToasterStatus.Down);
+ public void close() throws ExecutionException, InterruptedException {
+ // When we close this service we need to shutdown our executor!
+ executor.shutdown();
+ if (dataProvider != null) {
+ final DataModificationTransaction t = dataProvider.beginTransaction();
+ t.removeOperationalData(TOASTER_IID);
+ t.commit().get();
+ }
+ }
+
+ private Toaster buildToaster() {
+ // We don't need to synchronize on currentTask here b/c it's declared volatile and
+ // we're just doing a read.
+ boolean isUp = currentTask == null;
+
+ // note - we are simulating a device whose manufacture and model are
+ // fixed (embedded) into the hardware.
+ // This is why the manufacture and model number are hardcoded.
+ ToasterBuilder tb = new ToasterBuilder();
+ tb.setToasterManufacturer(TOASTER_MANUFACTURER).setToasterModelNumber(TOASTER_MODEL_NUMBER)
+ .setToasterStatus(isUp ? ToasterStatus.Up : ToasterStatus.Down);
return tb.build();
}
+ /**
+ * Implemented from the DataChangeListener interface.
+ */
@Override
- public synchronized Future<RpcResult<Void>> cancelToast() {
- if (currentTask != null) {
- cancelToastImpl();
+ public void onDataChanged( DataChangeEvent<InstanceIdentifier<?>, DataObject> change ) {
+ DataObject dataObject = change.getUpdatedConfigurationData().get( TOASTER_IID );
+ if( dataObject instanceof Toaster )
+ {
+ Toaster toaster = (Toaster) dataObject;
+ Long darkness = toaster.getDarknessFactor();
+ if( darkness != null )
+ {
+ darknessFactor.set( darkness );
+ }
}
- return null;
}
+ /**
+ * RestConf RPC call implemented from the ToasterService interface.
+ */
@Override
- public synchronized Future<RpcResult<Void>> makeToast(MakeToastInput input) {
- log.debug("makeToast - Received input for toast");
- logToastInput(input);
- if (currentTask != null) {
- return inProgressError();
+ public Future<RpcResult<Void>> cancelToast() {
+ synchronized (taskLock) {
+ if (currentTask != null) {
+ currentTask.cancel(true);
+ currentTask = null;
+ }
}
- currentTask = executor.submit(new MakeToastTask(input));
- updateStatus();
- return currentTask;
+ // Always return success from the cancel toast call.
+ return Futures.immediateFuture(Rpcs.<Void> getRpcResult(true, Collections.<RpcError> emptySet()));
}
- private Future<RpcResult<Void>> inProgressError() {
- RpcResult<Void> result = Rpcs.<Void> getRpcResult(false, null, Collections.<RpcError> emptySet());
- return Futures.immediateFuture(result);
- }
+ /**
+ * RestConf RPC call implemented from the ToasterService interface.
+ */
+ @Override
+ public Future<RpcResult<Void>> makeToast(MakeToastInput input) {
+ LOG.info("makeToast: " + input);
- private void cancelToastImpl() {
- currentTask.cancel(true);
- ToastDoneBuilder toastDone = new ToastDoneBuilder();
- toastDone.setToastStatus(ToastStatus.Cancelled);
- notificationProvider.publish(toastDone.build());
- }
+ synchronized (taskLock) {
+ if (currentTask != null) {
+ // return an error since we are already toasting some toast.
+ LOG.info( "Toaster is already making toast" );
- public void setNotificationProvider(NotificationProviderService salService) {
- this.notificationProvider = salService;
- }
+ RpcResult<Void> result = Rpcs.<Void> getRpcResult(false, null, Arrays.asList(
+ RpcErrors.getRpcError( null, null, null, null,
+ "Toaster is busy", null, null ) ) );
+ return Futures.immediateFuture(result);
+ }
+ else if( outOfBread() ) {
+ RpcResult<Void> result = Rpcs.<Void> getRpcResult(false, null, Arrays.asList(
+ RpcErrors.getRpcError( null, null, null, null,
+ "Toaster is out of bread", null, null ) ) );
+ return Futures.immediateFuture(result);
+ }
+ else {
+ // Notice that we are moving the actual call to another thread,
+ // allowing this thread to return immediately.
+ // The MD-SAL design encourages asynchronus programming. If the
+ // caller needs to block until the call is
+ // complete then they can leverage the blocking methods on the
+ // Future interface.
+ currentTask = executor.submit(new MakeToastTask(input));
+ }
+ }
- public void setDataProvider(DataBrokerService salDataProvider) {
- this.dataProvider = salDataProvider;
updateStatus();
+ return currentTask;
}
- private void logToastInput(MakeToastInput input) {
- String toastType = input.getToasterToastType().getName();
- String toastDoneness = input.getToasterDoneness().toString();
- log.trace("Toast: {} doneness: {}", toastType, toastDoneness);
+ /**
+ * RestConf RPC call implemented from the ToasterService interface.
+ * Restocks the bread for the toaster, resets the toastsMade counter to 0, and sends a
+ * ToasterRestocked notification.
+ */
+ @Override
+ public Future<RpcResult<java.lang.Void>> restockToaster(RestockToasterInput input) {
+ LOG.info( "restockToaster: " + input );
+
+ synchronized( taskLock ) {
+ amountOfBreadInStock.set( input.getAmountOfBreadToStock() );
+
+ if( amountOfBreadInStock.get() > 0 ) {
+ ToasterRestocked reStockedNotification =
+ new ToasterRestockedBuilder().setAmountOfBread( input.getAmountOfBreadToStock() ).build();
+ notificationProvider.publish( reStockedNotification );
+ }
+ }
+
+ return Futures.immediateFuture(Rpcs.<Void> getRpcResult(true, Collections.<RpcError> emptySet()));
}
- private final AtomicLong toastsMade = new AtomicLong(0);
+ /**
+ * JMX RPC call implemented from the ToasterProviderRuntimeMXBean interface.
+ */
+ @Override
+ public void clearToastsMade() {
+ LOG.info( "clearToastsMade" );
+ toastsMade.set( 0 );
+ }
+ /**
+ * Accesssor method implemented from the ToasterProviderRuntimeMXBean interface.
+ */
@Override
public Long getToastsMade() {
return toastsMade.get();
private void updateStatus() {
if (dataProvider != null) {
final DataModificationTransaction t = dataProvider.beginTransaction();
- t.removeOperationalData(toasterIID);
- t.putOperationalData(toasterIID, getToaster());
+ t.removeOperationalData(TOASTER_IID);
+ t.putOperationalData(TOASTER_IID, buildToaster());
try {
t.commit().get();
} catch (InterruptedException | ExecutionException e) {
- log.warn("Failed to update toaster status, operational otherwise", e);
+ LOG.warn("Failed to update toaster status, operational otherwise", e);
}
} else {
- log.trace("No data provider configured, not updating status");
+ LOG.trace("No data provider configured, not updating status");
}
}
- @Override
- public void close() throws ExecutionException, InterruptedException {
- if (dataProvider != null) {
- final DataModificationTransaction t = dataProvider.beginTransaction();
- t.removeOperationalData(toasterIID);
- t.commit().get();
- }
+ private boolean outOfBread()
+ {
+ return amountOfBreadInStock.get() == 0;
}
private class MakeToastTask implements Callable<RpcResult<Void>> {
}
@Override
- public RpcResult<Void> call() throws InterruptedException {
- Thread.sleep(1000 * toastRequest.getToasterDoneness());
+ public RpcResult<Void> call() {
+ try
+ {
+ // make toast just sleeps for n secondn per doneness level.
+ long darknessFactor = OpendaylightToaster.this.darknessFactor.get();
+ Thread.sleep(darknessFactor * toastRequest.getToasterDoneness());
- ToastDoneBuilder notifyBuilder = new ToastDoneBuilder();
- notifyBuilder.setToastStatus(ToastStatus.Done);
- notificationProvider.publish(notifyBuilder.build());
- log.debug("Toast Done");
- logToastInput(toastRequest);
+ }
+ catch( InterruptedException e ) {
+ LOG.info( "Interrupted while making the toast" );
+ }
- currentTask = null;
toastsMade.incrementAndGet();
+
+ amountOfBreadInStock.getAndDecrement();
+ if( outOfBread() ) {
+ LOG.info( "Toaster is out of bread!" );
+
+ notificationProvider.publish( new ToasterOutOfBreadBuilder().build() );
+ }
+
+ synchronized (taskLock) {
+ currentTask = null;
+ }
+
updateStatus();
+ LOG.debug("Toast done");
+
return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
}
}
prefix "toaster-provider-impl";
import config { prefix config; revision-date 2013-04-05; }
- import toaster-provider { prefix toaster-provider; revision-date 2014-01-31; }
+ import rpc-context { prefix rpcx; revision-date 2013-06-17; }
import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
description
"Initial revision.";
}
- // This is the definition of a service implementation
+ // This is the definition of the service implementation as a module identity.
identity toaster-provider-impl {
base config:module-type;
- config:provided-service toaster-provider:toaster-provider;
+
+ // Specifies the prefix for generated java classes.
config:java-name-prefix ToasterProvider;
}
+ // Augments the 'configuration' choice node under modules/module.
augment "/config:modules/config:module/config:configuration" {
case toaster-provider-impl {
when "/config:modules/config:module/config:type = 'toaster-provider-impl'";
augment "/config:modules/config:module/config:state" {
case toaster-provider-impl {
when "/config:modules/config:module/config:type = 'toaster-provider-impl'";
-
+
leaf toasts-made {
type uint32;
}
+
+ rpcx:rpc-context-instance "clear-toasts-made-rpc";
+ }
+ }
+
+ identity clear-toasts-made-rpc;
+ rpc clear-toasts-made {
+ description
+ "JMX call to clear the toasts-made counter.";
+
+ input {
+ uses rpcx:rpc-context-ref {
+ refine context-instance {
+ rpcx:rpc-context-instance clear-toasts-made-rpc;
+ }
+ }
}
}
}
+++ /dev/null
-// vi: set smarttab et sw=4 tabstop=4:
-module toaster-provider {
-
- yang-version 1;
- namespace "urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider";
- prefix "toaster-provider";
-
- import config { prefix config; revision-date 2013-04-05; }
-
- description
- "This module contains the base YANG definitions for
- toaster-provider services.";
-
- revision "2014-01-31" {
- description
- "Initial revision.";
- }
-
- // This is the definition of a service
- identity toaster-provider {
-
- base "config:service-type";
-
- config:java-class "org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterData";
- }
-}
\ No newline at end of file
"This variable indicates the current state of
the toaster.";
}
+
+ leaf darknessFactor {
+ type uint32;
+ config true;
+ default 1000;
+ description
+ "The darkness factor. Basically, the number of ms to multiple the doneness value by.";
+ }
} // container toaster
rpc make-toast {
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.";
- }
+ rpc restock-toaster {
+ description
+ "Restocks the toaster with the amount of bread specified.";
+
+ input {
+ leaf amountOfBreadToStock {
+ type uint32;
+ description
+ "Indicates the amount of bread to re-stock";
+ }
}
+ }
+
+ notification toasterOutOfBread {
+ description
+ "Indicates that the toaster has run of out bread.";
+ } // notification toasterOutOfStock
+
+ notification toasterRestocked {
+ description
+ "Indicates that the toaster has run of out bread.";
+ leaf amountOfBread {
+ type uint32;
description
- "Indicates the final toast status";
+ "Indicates the amount of bread that was re-stocked";
}
- } // notification toastDone
+ } // notification toasterOutOfStock
+
} // module toaster
abstract class AbstractStatsTracker<I, K> {
private static final Logger logger = LoggerFactory.getLogger(AbstractStatsTracker.class);
-
+
private static final int WAIT_FOR_REQUEST_CYCLE = 2;
-
+
private final FutureCallback<RpcResult<? extends TransactionAware>> callback =
new FutureCallback<RpcResult<? extends TransactionAware>>() {
@Override
}
protected final InstanceIdentifierBuilder<Node> getNodeIdentifierBuilder() {
- return InstanceIdentifier.builder(getNodeIdentifier());
+ return getNodeIdentifier().builder();
}
protected final NodeRef getNodeRef() {
if (Group.class.equals(key.getTargetType())) {
@SuppressWarnings("unchecked")
InstanceIdentifier<Group> group = (InstanceIdentifier<Group>)key;
- InstanceIdentifier<?> del = InstanceIdentifier.builder(group).augmentation(NodeGroupDescStats.class).toInstance();
+ InstanceIdentifier<?> del = group.augmentation(NodeGroupDescStats.class);
logger.debug("Key {} triggered remove of augmentation {}", key, del);
trans.removeOperationalData(del);
if (Group.class.equals(key.getTargetType())) {
@SuppressWarnings("unchecked")
InstanceIdentifier<Group> group = (InstanceIdentifier<Group>)key;
- InstanceIdentifier<?> del = InstanceIdentifier.builder(group).augmentation(NodeGroupStatistics.class).toInstance();
+ InstanceIdentifier<?> del = group.augmentation(NodeGroupStatistics.class);
logger.debug("Key {} triggered remove of augmentation {}", key, del);
trans.removeOperationalData(del);
InstanceIdentifier<Meter> meter = (InstanceIdentifier<Meter>)key;
InstanceIdentifier<?> nodeMeterStatisticsAugmentation =
- InstanceIdentifier.builder(meter).augmentation(NodeMeterConfigStats.class).toInstance();
+ meter.augmentation(NodeMeterConfigStats.class);
trans.removeOperationalData(nodeMeterStatisticsAugmentation);
}
}
InstanceIdentifier<Meter> meter = (InstanceIdentifier<Meter>)key;
InstanceIdentifier<?> nodeMeterStatisticsAugmentation =
- InstanceIdentifier.builder(meter).augmentation(NodeMeterStatistics.class).toInstance();
+ meter.augmentation(NodeMeterStatistics.class);
trans.removeOperationalData(nodeMeterStatisticsAugmentation);
}
}
if (Queue.class.equals(key.getTargetType())) {
@SuppressWarnings("unchecked")
final InstanceIdentifier<Queue> queue = (InstanceIdentifier<Queue>)key;
- final InstanceIdentifier<?> del = InstanceIdentifier.builder(queue)
- .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class).build();
+ final InstanceIdentifier<?> del = queue
+ .augmentation(FlowCapableNodeConnectorQueueStatisticsData.class);
logger.debug("Key {} triggered remove of augmentation {}", key, del);
trans.removeOperationalData(del);
}
for (Link link : topologyData.getLink()) {
if (id.equals(link.getSource().getSourceNode()) || id.equals(link.getDestination().getDestNode())) {
- InstanceIdentifier<Link> path = InstanceIdentifier.builder(topologyPath)
- .child(Link.class, link.getKey()).build();
+ InstanceIdentifier<Link> path = topologyPath.child(Link.class, link.getKey());
transaction.removeOperationalData(path);
}
}
}
for (Link link : topologyData.getLink()) {
if (id.equals(link.getSource().getSourceTp()) || id.equals(link.getDestination().getDestTp())) {
- InstanceIdentifier<Link> path = InstanceIdentifier.builder(topologyPath)
- .child(Link.class, link.getKey()).build();
+ InstanceIdentifier<Link> path = topologyPath.child(Link.class, link.getKey());
transaction.removeOperationalData(path);
}
}
.child(Topology.class, topology).child(Link.class, link.getKey()).build();
return linkInstanceId;
}
-
+
/**
* @param txId transaction identificator
* @param future transaction result
*/
private static void listenOnTransactionState(final Object txId, Future<RpcResult<TransactionStatus>> future) {
Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future),new FutureCallback<RpcResult<TransactionStatus>>() {
-
+
@Override
public void onFailure(Throwable t) {
LOG.error("Topology export failed for Tx:{}", txId, t);
-
+
}
-
+
@Override
public void onSuccess(RpcResult<TransactionStatus> result) {
if(!result.isSuccessful()) {
*/
package org.opendaylight.controller.netconf.confignetconfconnector.exception;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-
import java.util.Collections;
import java.util.Map;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
public class NetconfConfigHandlingException extends NetconfDocumentedException {
+ private static final long serialVersionUID = 1L;
public NetconfConfigHandlingException(final String message, final ErrorType errorType, final ErrorTag errorTag,
final ErrorSeverity errorSeverity) {
*/
package org.opendaylight.controller.netconf.confignetconfconnector.exception;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-
import java.util.Collections;
import java.util.Map;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
public class NoTransactionFoundException extends NetconfDocumentedException {
+ private static final long serialVersionUID = 1L;
public NoTransactionFoundException(final String message, final ErrorType errorType, final ErrorTag errorTag,
final ErrorSeverity errorSeverity) {
*/
package org.opendaylight.controller.netconf.confignetconfconnector.exception;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-
import java.util.Collections;
import java.util.Map;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
public class OperationNotPermittedException extends NetconfDocumentedException {
+ private static final long serialVersionUID = 1L;
public OperationNotPermittedException(final String message, final ErrorType errorType, final ErrorTag errorTag,
final ErrorSeverity errorSeverity) {
package org.opendaylight.controller.netconf.persist.impl;
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Collections2;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.concurrent.Immutable;
+
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
-import javax.annotation.concurrent.Immutable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.TimeUnit;
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Collections2;
@Immutable
public class ConfigPusher {
}
private static class NotEnoughCapabilitiesException extends Exception {
+ private static final long serialVersionUID = 1L;
+
private NotEnoughCapabilitiesException(String message, Throwable cause) {
super(message, cause);
}
</properties>
<dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>sal-binding-it</artifactId>
- <exclusions>
- <!-- FIXME see IdentityRefNetconfTest -->
- <!-- Pax-url-aether contains guava classes e.g. ImmutableSet that clashes with guava and causes tests to fail-->
- <exclusion>
- <groupId>org.ops4j.pax.url</groupId>
- <artifactId>pax-url-aether</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.logback_settings</artifactId>
<artifactId>yang-test</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.ops4j.pax.tinybundles</groupId>
- <artifactId>tinybundles</artifactId>
- <version>${tinybundles.version}</version>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<perCoreThreadCount>false</perCoreThreadCount>
- <classpathDependencyExcludes>
- <classpathDependencyExcludes>com.google.collections:google-collections</classpathDependencyExcludes>
- <classpathDependencyExcludes>org.ops4j.pax.url:pax-url-aether</classpathDependencyExcludes>
- </classpathDependencyExcludes>
</configuration>
<executions>
<execution>
import static java.util.Collections.emptyList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import javax.management.ObjectName;
import javax.xml.parsers.ParserConfigurationException;
-import junit.framework.Assert;
-
-import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean;
import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
-import org.opendaylight.controller.netconf.StubUserManager;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
-import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
-import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
-import ch.ethz.ssh2.Connection;
-import ch.ethz.ssh2.Session;
-
+import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.netty.channel.ChannelFuture;
static List<ModuleFactory> getModuleFactoriesS() {
return Lists.newArrayList(new TestImplModuleFactory(), new DepTestImplModuleFactory(),
- new NetconfTestImplModuleFactory());
+ new NetconfTestImplModuleFactory(), new IdentityTestModuleFactory());
}
@Test
return netconfClient;
}
- private void startSSHServer() throws Exception {
- logger.info("Creating SSH server");
- StubUserManager um = new StubUserManager(USERNAME, PASSWORD);
- String pem;
- try (InputStream is = getClass().getResourceAsStream("/RSA.pk")) {
- pem = IOUtils.toString(is);
+ @Test
+ public void testIdRef() throws Exception {
+ NetconfMessage editId = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_identities.xml");
+ NetconfMessage commit = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml");
+
+ try (TestingNetconfClient netconfClient = createSession(tcpAddress, "1")) {
+ assertIsOK(netconfClient.sendMessage(editId).getDocument());
+ assertIsOK(netconfClient.sendMessage(commit).getDocument());
+
+ NetconfMessage response = netconfClient.sendMessage(getConfig);
+
+ assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:afi>"));
+ assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:afi>"));
+ assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:safi>"));
+ assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:safi>"));
+
+ } catch (Exception e) {
+ fail(Throwables.getStackTraceAsString(e));
}
- AuthProvider ap = new AuthProvider(um, pem);
- Thread sshServerThread = new Thread(NetconfSSHServer.start(10830, tcpAddress, ap));
- sshServerThread.setDaemon(true);
- sshServerThread.start();
- logger.info("SSH server on");
}
- @Test
- public void sshTest() throws Exception {
- startSSHServer();
- logger.info("creating connection");
- Connection conn = new Connection(sshAddress.getHostName(), sshAddress.getPort());
- Assert.assertNotNull(conn);
- logger.info("connection created");
- conn.connect();
- boolean isAuthenticated = conn.authenticateWithPassword(USERNAME, PASSWORD);
- assertTrue(isAuthenticated);
- logger.info("user authenticated");
- final Session sess = conn.openSession();
- sess.startSubSystem("netconf");
- logger.info("user authenticated");
- sess.getStdin().write(XmlUtil.toString(this.getConfig.getDocument()).getBytes());
-
- new Thread() {
- @Override
- public void run() {
- while (true) {
- byte[] bytes = new byte[1024];
- int c = 0;
- try {
- c = sess.getStdout().read(bytes);
- } catch (IOException e) {
- throw new IllegalStateException("IO exception while reading data on ssh bridge.");
- }
- logger.info("got data:" + bytes);
- if (c == 0) {
- break;
- }
- }
- }
- }.join();
- }
+ @Override
+ protected CodecRegistry getCodecRegistry() {
+ final IdentityCodec<?> codec = mock(IdentityCodec.class);
+ doReturn(TestIdentity1.class).when(codec).deserialize(TestIdentity1.QNAME);
+ doReturn(TestIdentity2.class).when(codec).deserialize(TestIdentity2.QNAME);
+ final CodecRegistry ret = super.getCodecRegistry();
+ doReturn(codec).when(ret).getIdentityCodec();
+ return ret;
+ }
}
+++ /dev/null
-/*
-* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
-*
-* This program and the accompanying materials are made available under the
-* terms of the Eclipse Public License v1.0 which accompanies this distribution,
-* and is available at http://www.eclipse.org/legal/epl-v10.html
-*/
-package org.opendaylight.controller.netconf.it.pax;
-
-import static org.junit.Assert.fail;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.baseModelBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.bindingAwareSalBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.configMinumumBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.flowCapableModelBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.junitAndMockitoBundles;
-import static org.opendaylight.controller.test.sal.binding.it.TestHelper.mdSalCoreBundles;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.options;
-import static org.ops4j.pax.exam.CoreOptions.streamBundle;
-import static org.ops4j.pax.exam.CoreOptions.systemPackages;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-
-import io.netty.util.HashedWheelTimer;
-import io.netty.util.Timer;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.matchers.JUnitMatchers;
-import org.junit.runner.RunWith;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
-import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
-import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
-import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
-import org.opendaylight.controller.netconf.client.test.TestingNetconfClient;
-import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.protocol.framework.NeverReconnectStrategy;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.options.DefaultCompositeOption;
-import org.ops4j.pax.exam.util.Filter;
-import org.ops4j.pax.tinybundles.core.TinyBundles;
-import org.osgi.framework.Constants;
-import org.xml.sax.SAXException;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Throwables;
-
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.concurrent.GlobalEventExecutor;
-
-@Ignore
-@RunWith(PaxExam.class)
-public class IdentityRefNetconfTest {
-
- public static final int CLIENT_CONNECTION_TIMEOUT_MILLIS = 15000;
-
- // Wait for controller to start
-
- // FIXME move this (pax) test to different module
- // pax jars contain guava classes that clash with real guava dependencies in non-pax tests
- //
- //@Inject
- @Filter(timeout = 60 * 1000)
- BindingAwareBroker broker;
-
- @Configuration
- public Option[] config() {
- return options(
- systemProperty("osgi.console").value("2401"),
- systemProperty("osgi.bundles.defaultStartLevel").value("4"),
- systemProperty("pax.exam.osgi.unresolved.fail").value("true"),
- systemPackages("sun.nio.ch"),
-
- testingModules(),
- loggingModules(),
- mdSalCoreBundles(),
- bindingAwareSalBundles(), configMinumumBundles(), baseModelBundles(), flowCapableModelBundles(),
- junitAndMockitoBundles(),
-
- // Classes from test-jars bundled for pax-exam test
- streamBundle(TinyBundles.bundle()
- .add(TestingNetconfClient.class)
- .add(XmlFileLoader.class)
-
- .add("/netconfMessages/editConfig_identities.xml",
- XmlFileLoader.class.getResource("/netconfMessages/editConfig_identities.xml"))
- .add("/netconfMessages/commit.xml",
- XmlFileLoader.class.getResource("/netconfMessages/commit.xml"))
- .add("/netconfMessages/getConfig.xml",
- XmlFileLoader.class.getResource("/netconfMessages/getConfig.xml"))
-
- .set(Constants.BUNDLE_SYMBOLICNAME, "TestingClient_bundle")
- .set(Constants.EXPORT_PACKAGE, "org.opendaylight.controller.netconf.client.test, " +
- "org.opendaylight.controller.netconf.util.test")
- .build(TinyBundles.withBnd())));
- }
-
- private Option loggingModules() {
- return new DefaultCompositeOption(
- 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.openexi", "nagasena").versionAsInProject(),
- mavenBundle("org.openexi", "nagasena-rta").versionAsInProject());
-
-
- }
-
- private Option testingModules() {
- return new DefaultCompositeOption(
- mavenBundle("org.opendaylight.controller", "yang-test").versionAsInProject());
- }
-
- private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 18383);
-
- @Test
- public void testIdRef() throws Exception {
- Preconditions.checkNotNull(broker, "Controller not initialized");
-
-
- NetconfMessage edit = xmlFileToNetconfMessage("netconfMessages/editConfig_identities.xml");
- NetconfMessage commit = xmlFileToNetconfMessage("netconfMessages/commit.xml");
- NetconfMessage getConfig = xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
-
- NioEventLoopGroup nettyThreadgroup = new NioEventLoopGroup();
- Timer timer = new HashedWheelTimer();
- NetconfClientDispatcherImpl clientDispatcher = new NetconfClientDispatcherImpl(nettyThreadgroup, nettyThreadgroup, timer);
- try (TestingNetconfClient netconfClient = new TestingNetconfClient("client", clientDispatcher, getClientConfiguration(tcpAddress))) {
- sendMessage(edit, netconfClient);
- sendMessage(commit, netconfClient);
- sendMessage(getConfig, netconfClient, "id-test",
- "<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:afi>",
- "<prefix:afi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:afi>",
- "<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity2</prefix:safi>",
- "<prefix:safi xmlns:prefix=\"urn:opendaylight:params:xml:ns:yang:controller:config:test:types\">prefix:test-identity1</prefix:safi>");
-
- clientDispatcher.close();
- } catch (Exception e) {
- fail(Throwables.getStackTraceAsString(e));
- } finally {
- nettyThreadgroup.shutdownGracefully().get();
- timer.stop();
- }
- }
-
- private void sendMessage(NetconfMessage edit, TestingNetconfClient netconfClient, String... containingResponse)
- throws ExecutionException, InterruptedException, TimeoutException {
- NetconfMessage response = netconfClient.sendRequest(edit).get();
- if (containingResponse == null) {
- Assert.assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString("<ok/>"));
- } else {
- for (String resp : containingResponse) {
- Assert.assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString(resp));
- }
- }
- }
-
- public static NetconfMessage xmlFileToNetconfMessage(final String fileName) throws IOException, SAXException,
- ParserConfigurationException {
- return XmlFileLoader.xmlFileToNetconfMessage(fileName);
- }
-
- public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress) {
- final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
- b.withAddress(tcpAddress);
- b.withSessionListener(new SimpleNetconfClientSessionListener());
- b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE,
- CLIENT_CONNECTION_TIMEOUT_MILLIS));
- b.withConnectionTimeoutMillis(CLIENT_CONNECTION_TIMEOUT_MILLIS);
- return b.build();
- }
-}
+++ /dev/null
------BEGIN RSA PRIVATE KEY-----
-MIIEogIBAAKCAQEAuC9hbEacpewvylI0mwFwjy3Wou2hpr/ncN9BBiFDSaG5yW2k
-3Oy+SCAcFCL+ZKWb6cc6Ch4gUeCwyEHRojZguuhliKtak9YQf6qbvpPLe00842Lx
-iqNAGurMpzizCDsGFq8ChaAkBZQI3TvcHuPoSUWSMJ+K8xHpRyUdVr6g2yEjezKJ
-sTXBtWaeCCh6YUafFujuDJk7fvYcPW7Je5KRBBStIKvxcMW0zB+7eq04deTHwGbJ
-gGjKWilQ72hsDDP3Hbp5CJMAYg1r4GlCmFx3KyHRGztgWgNgaD7nNpKCkTLjtmA6
-b4x7TA+jrzZ6Af2z5TMrI4dv5w1SrxHaZ+ziLQIDAQABAoIBAHTndeGgq/rQf8De
-Do+4CTaHtK0zQSAyu/azbXUzlZ7drKuCEVs8VMY4wzmwwGEnkF+A2YDkgEUX5X0l
-8aYQ97KKoS9u+43MGCrAIhyDeGrpqlT1TzRcy+qJz53v6gq2U/X/3QztiQ+VV078
-mIluxNgE9XYxPaNsYfGLSCTv1+9c8y/hjGVX2kwFK+u4ut0ZZETggNa8UxfaHVDS
-fIJQX9Gm3J3GSUV30fDGMBIUW6ESLc2L8b7u8Mp9TRP39ZeQSuEUjBe8MYKv0Rel
-oEpjZvcnniMTpFbLpndBYn7/AoIiEBvtCN8faVTuRRcvvLcsRm09IctzKQYnMh6M
-6PLKV+ECgYEA8HFRYaKHUzxpzE/fyon82GQbzqFFY0/bbWrfWICMfNbIgshJUie6
-FmH5iUFMfeqaT7v557HFM0GB9FeIeSbvd88YmiBAcRopZ3DfMkDH+DT73yJ+/TKG
-2nrQtdhyuTIs4bwHqeS2BBJYs7PK9R2rratF3l34Tf7mjlvyOgygHdUCgYEAxBo2
-8hEBlAVNcNb1hTYUxe1w1B6675/mFlmw98Xmj9dRYfICXNhahs8tX3/lsBEd+vBu
-fI0oyHaff8m5bPgGzD1ZMybfeROujNrgxaKVk7Ef0FDRRCop4bm18OroFlFAt9l8
-wMp++ToACbdvQvL/mjWMPYlIxhB/YxHswICZZvkCgYAexxKYwdo6sGAGlC7cWT9x
-X5cjowcjyEQZRHXkeUgCbufpvcOM7aLnXJE5nY8yCwbHsBM0MlBA2GDPKylAANjk
-aDEJAZneIHAuWodngl1Wi0m2bU7+ECqs6s2uiU9eH2sZVh1RBQK7kLGkBx6ys6KX
-L3ZZGYRAT6GplWFzRsx0JQKBgCeVlxPD5QqpC1nEumi6YvUVGdpnnZpzL3HBhxxs
-wT612wKnZFyze4qM1X7ahVXGDsQxtkvD/sCAWW/lG13orw6ZL6FIroF1PJ3ILOkY
-CZN3hJF7TtKwpCWhZB2OfWzL2AGEkE8mUP0j/Q/5DCd6f6f0OSvOw3bfq6cm3iB5
-lP2ZAoGAXsRN5TZTX4AQ2xTlrDQ8A5XgcvyWQpJOmEXMTyHV7VaJVzmNWFVAvndK
-5UIq8ALDwB2t7vjmMUW6euvIwqtXiop7G79UOb3e3NhzeyWFGQyBLqCRznGaXQTT
-dlFy73xhukZMhFnj006bjKCYvOPnwuGl3+0fuWil5Rq3jOuY5c8=
------END RSA PRIVATE KEY-----
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<persisted-snapshots>
- <snapshots>
- <snapshot>
- <required-capabilities>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:test:types?module=test-types&revision=2013-11-27</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&revision=2013-07-16</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:test:impl?module=config-test-impl&revision=2013-04-03</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:test?module=config-test&revision=2013-06-13</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>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:impl-identity-test</prefix:type>
- <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">id-test</prefix:name>
- <identities-container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
- <prefix:afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity2</prefix:afi>
- </identities-container>
- <identities xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
- <prefix:safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity2</prefix:safi>
- <prefix:afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</prefix:afi>
- </identities>
- <identities xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
- <prefix:safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</prefix:safi>
- <prefix:afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity2</prefix:afi>
- </identities>
- <prefix:afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</prefix:afi>
- </module>
- <module>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</prefix:type>
- <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-broker-impl</prefix:name>
- <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-service</prefix:type>
- <name>ref_binding-notification-broker</name>
- </notification-service>
- <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-broker</prefix:type>
- <name>ref_binding-data-broker</name>
- </data-broker>
- </module>
- <module>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</prefix:type>
- <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">runtime-mapping-singleton</prefix:name>
- </module>
- <module>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</prefix:type>
- <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-notification-broker</prefix:name>
- </module>
- <module>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-broker</prefix:type>
- <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-data-broker</prefix:name>
- <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</prefix:type>
- <name>ref_dom-broker</name>
- </dom-broker>
- <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-dom-mapping-service</prefix:type>
- <name>ref_runtime-mapping-singleton</name>
- </mapping-service>
- </module>
- <module>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:logback:config">prefix:logback</prefix:type>
- <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:logback:config">singleton</prefix:name>
- <console-appenders xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
- <threshold-filter>DEBUG</threshold-filter>
- <name>console</name>
- <encoder-pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</encoder-pattern>
- </console-appenders>
- <loggers xmlns="urn:opendaylight:params:xml:ns:yang:controller:logback:config">
- <level>DEBUG</level>
- <logger-name>ROOT</logger-name>
- <appenders>console</appenders>
- </loggers>
- </module>
- <module>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</prefix:type>
- <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">yang-schema-service</prefix:name>
- </module>
- <module>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:hash-map-data-store</prefix:type>
- <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">hash-map-data-store</prefix:name>
- </module>
- <module>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</prefix:type>
- <prefix:name xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">dom-broker</prefix:name>
- <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-data-store</prefix:type>
- <name>ref_hash-map-data-store</name>
- </data-store>
- </module>
- </modules>
- <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:schema-service</prefix:type>
- <instance>
- <name>ref_yang-schema-service</name>
- <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-data-store</prefix:type>
- <instance>
- <name>ref_hash-map-data-store</name>
- <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">prefix:dom-broker-osgi-registry</prefix:type>
- <instance>
- <name>ref_dom-broker</name>
- <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</prefix:type>
- <instance>
- <name>ref_id-test</name>
- <provider>/modules/module[type='impl-identity-test'][name='id-test']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-dom-mapping-service</prefix:type>
- <instance>
- <name>ref_runtime-mapping-singleton</name>
- <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-consumer-broker</prefix:type>
- <instance>
- <name>ref_binding-data-broker</name>
- <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-rpc-registry</prefix:type>
- <instance>
- <name>ref_binding-broker-impl</name>
- <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-service</prefix:type>
- <instance>
- <name>ref_binding-notification-broker</name>
- <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</prefix:type>
- <instance>
- <name>ref_binding-broker-impl</name>
- <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-notification-subscription-service</prefix:type>
- <instance>
- <name>ref_binding-notification-broker</name>
- <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
- </instance>
- </service>
- <service>
- <prefix:type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-data-broker</prefix:type>
- <instance>
- <name>ref_binding-data-broker</name>
- <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
- </instance>
- </service>
- </services>
- </data>
- </configuration>
- </snapshot>
- </snapshots>
-</persisted-snapshots>
+++ /dev/null
-<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
- <commit></commit>
-</rpc>
+++ /dev/null
-<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
- <get-config>
- <source>
- <running/>
- </source>
- </get-config>
-</rpc>
*/
package org.opendaylight.controller.netconf.util.exception;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-
import java.util.Collections;
import java.util.Map;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
public class MissingNameSpaceException extends NetconfDocumentedException {
+ private static final long serialVersionUID = 1L;
public MissingNameSpaceException(final String message, final ErrorType errorType, final ErrorTag errorTag,
- final ErrorSeverity errorSeverity) {
+ final ErrorSeverity errorSeverity) {
this(message, errorType, errorTag, errorSeverity, Collections.<String, String> emptyMap());
}
public MissingNameSpaceException(final String message, final ErrorType errorType, final ErrorTag errorTag,
- final ErrorSeverity errorSeverity, final Map<String, String> errorInfo){
+ final ErrorSeverity errorSeverity, final Map<String, String> errorInfo){
super(message,errorType,errorTag,errorSeverity,errorInfo);
}
}
*/
package org.opendaylight.controller.netconf.util.exception;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-
import java.util.Collections;
import java.util.Map;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
public class UnexpectedElementException extends NetconfDocumentedException {
+ private static final long serialVersionUID = 1L;
public UnexpectedElementException(final String message, final ErrorType errorType, final ErrorTag errorTag,
- final ErrorSeverity errorSeverity) {
+ final ErrorSeverity errorSeverity) {
this(message, errorType, errorTag, errorSeverity, Collections.<String, String> emptyMap());
}
public UnexpectedElementException(final String message, final ErrorType errorType, final ErrorTag errorTag,
- final ErrorSeverity errorSeverity, final Map<String, String> errorInfo){
+ final ErrorSeverity errorSeverity, final Map<String, String> errorInfo) {
super(message,errorType,errorTag,errorSeverity,errorInfo);
}
}
*/
package org.opendaylight.controller.netconf.util.exception;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-
import java.util.Collections;
import java.util.Map;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+
public class UnexpectedNamespaceException extends NetconfDocumentedException {
+ private static final long serialVersionUID = 1L;
public UnexpectedNamespaceException(final String message, final ErrorType errorType, final ErrorTag errorTag,
final ErrorSeverity errorSeverity) {
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>2.3.6</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/connectionmanager"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/containermanager"/>
</services>
<modules>
<docs docsDir="rest" title="Container Manager REST API" includeExampleXml="true" includeExampleJson="true"/>
</modules>
-</enunciate>
\ No newline at end of file
+</enunciate>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/controllermanager"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.sal.core.Property;
+
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
-import org.opendaylight.controller.sal.core.Property;
/**
* The class describes set of properties attached to a controller
@XmlAccessorType(XmlAccessType.NONE)
public class ControllerProperties {
- @XmlElementRef
- @XmlElementWrapper
- @JsonIgnore
/**
* Set to store the controller properties
*/
+ @XmlElement(name="property")
+ @XmlElementWrapper
+ @JsonIgnore
private Set<Property> properties;
// JAXB required constructor
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/flowprogrammer"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/hosttracker"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services> </services>
<modules>
<!-- Disable doc generation -->
<docs disabled="true"/>
-
+ <swagger disabled="true"/>
<!-- Disable all the client generation tools -->
<basic-app disabled="true" />
<c disabled="true" />
<version>1.4.2-SNAPSHOT</version>
<relativePath>../../commons/opendaylight</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>northbound.client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<docs.output.dir>${project.build.directory}/rest-api-docs</docs.output.dir>
<java-client>${project.build.directory}/enunciate/build/java-client/full-client.jar</java-client>
<java-client-sources>${project.build.directory}/enunciate/build/java-client/full-client-sources.jar</java-client-sources>
- <json-client>${project.build.directory}/enunciate/build/java-client/full-json-client.jar</json-client>
- <json-client-sources>${project.build.directory}/enunciate/build/java-client/full-json-client-sources.jar</json-client-sources>
</properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>enunciate-core-annotations</artifactId>
+ </dependency>
+
+ <!-- add dependency on all northbound bundles -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>connectionmanager.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>controllermanager.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>flowprogrammer.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>forwarding.staticrouting.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>networkconfig.bridgedomain.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>networkconfig.neutron.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>statistics.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>subnets.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>switchmanager.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topology.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>usermanager.northbound</artifactId>
+ </dependency>
+ </dependencies>
+
<build>
<plugins>
- <plugin>
- <groupId>org.codehaus.enunciate</groupId>
- <artifactId>maven-enunciate-plugin</artifactId>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
- <version>1.5</version>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
<configuration>
<target>
- <taskdef resource="net/sf/antcontrib/antcontrib.properties"
- classpathref="maven.plugin.classpath" />
+ <taskdef classpathref="maven.plugin.classpath" resource="net/sf/antcontrib/antcontrib.properties"></taskdef>
<patternset id="rest.paths">
- <include name="**/target/site/wsdocs/**"/>
- <exclude name="**/java-client/**"/>
+ <include name="**/target/site/wsdocs/**"></include>
+ <exclude name="**/java-client/**"></exclude>
</patternset>
- <echo message="======== Assembling enunciate docs ========"/>
+ <echo message="======== Assembling enunciate docs ========"></echo>
<!-- cleanup existing generated files -->
- <delete dir="${docs.output.dir}"/>
- <delete file="${docs.output.dir}.zip"/>
- <mkdir dir="${docs.output.dir}"/>
+ <delete dir="${docs.output.dir}"></delete>
+ <delete file="${docs.output.dir}.zip"></delete>
+ <mkdir dir="${docs.output.dir}"></mkdir>
<!-- copy enunciate docs to stage -->
<copy todir="${docs.output.dir}">
<fileset dir="${basedir}/../../..">
- <patternset refid="rest.paths"/>
+ <patternset refid="rest.paths"></patternset>
</fileset>
- <mapper type="regexp"
- from="^(.*)/([^/]+)/target/site/wsdocs/(.*)$$"
- to="\2/\3"/>
+ <mapper from="^(.*)/([^/]+)/target/site/wsdocs/(.*)$$" to="\2/\3" type="regexp"></mapper>
</copy>
+ <!-- Remove Swagger doc link from enunciate generated index.html -->
+ <replaceregexp byline="false" match="<h2>Swagger</h2>${line.separator}\s*<p>${line.separator}.*${line.separator}\s*</p>" replace="">
+ <fileset dir="${docs.output.dir}">
+ <include name="**/index.html"></include>
+ </fileset>
+ </replaceregexp>
<!-- generate index.html -->
<!-- append header -->
- <echo file="${docs.output.dir}/index.html" append="true">
- <![CDATA[
+ <echo append="true" file="${docs.output.dir}/index.html"><![CDATA[
<html>
<head>
<title> OpenDaylight REST API Documentation </title>
<h2>OpenDaylight REST API Documentation</h2>
<p> OpenDaylight supports the following <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">Representational State Transfer (REST)</a> APIs: </p>
<h4>
- ]]>
- </echo>
- <dirset id="nbset" dir="${docs.output.dir}">
- <include name="*"/>
+ ]]></echo>
+ <dirset dir="${docs.output.dir}" id="nbset">
+ <include name="*"></include>
</dirset>
- <pathconvert pathsep="&#36;{line.separator}"
- property="nbs"
- refid="nbset"/>
- <echo file="${docs.output.dir}/index.html"
- append="true"
- message="${nbs}"/>
- <replaceregexp file="${docs.output.dir}/index.html"
- match="^\${docs.output.dir}/(.*)$"
- replace="&lt;li&gt;&lt;a href=\1/index.html&gt; \1 &lt;/a&gt;&lt;/li&gt;"
- byline="true"/>
+ <pathconvert pathsep="&#36;{line.separator}" property="nbs" refid="nbset"></pathconvert>
+ <echo append="true" file="${docs.output.dir}/index.html" message="${nbs}"></echo>
+ <replaceregexp byline="true" file="${docs.output.dir}/index.html" match="^\${docs.output.dir}/(.*)$" replace="&lt;li&gt;&lt;a href=\1/index.html&gt; \1 &lt;/a&gt;&lt;/li&gt;"></replaceregexp>
<!-- append footer -->
- <echo file="${docs.output.dir}/index.html" append="true">
- <![CDATA[
+ <echo append="true" file="${docs.output.dir}/index.html"><![CDATA[
</h4>
<i>---</i>
</body>
</html>
- ]]>
- </echo>
+ ]]></echo>
<!-- archive all the docs excluding whatever is not needed -->
- <echo message="======== Archiving enunciate docs ========"/>
+ <echo message="======== Archiving enunciate docs ========"></echo>
<zip destfile="${docs.output.dir}.zip">
- <zipfileset dir="${docs.output.dir}"/>
+ <zipfileset dir="${docs.output.dir}"></zipfileset>
</zip>
- <echo message="======== Build successful ========"/>
- <echo message="REST docs archive: ${docs.output.dir}.zip"/>
+ <echo message="======== Build successful ========"></echo>
+ <echo message="REST docs archive: ${docs.output.dir}.zip"></echo>
</target>
</configuration>
<dependencies>
<version>20020829</version>
</dependency>
</dependencies>
+ <executions>
+ <execution>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <phase>package</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>maven-enunciate-plugin</artifactId>
</plugin>
<plugin>
<executions>
<execution>
<id>attach-artifacts</id>
- <phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
+ <phase>package</phase>
<configuration>
<artifacts>
<artifact>
<type>jar</type>
<classifier>full-java-client-sources</classifier>
</artifact>
- <artifact>
- <file>${json-client}</file>
- <type>jar</type>
- <classifier>full-json-client</classifier>
- </artifact>
- <artifact>
- <file>${json-client-sources}</file>
- <type>jar</type>
- <classifier>full-json-client-sources</classifier>
- </artifact>
</artifacts>
</configuration>
</execution>
</plugin>
</plugins>
</build>
- <dependencies>
- <dependency>
- <groupId>org.codehaus.enunciate</groupId>
- <artifactId>enunciate-core-annotations</artifactId>
- </dependency>
-
- <!-- add dependency on all northbound bundles -->
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>connectionmanager.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>controllermanager.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>flowprogrammer.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>hosttracker.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>networkconfig.bridgedomain.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>networkconfig.neutron.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>forwarding.staticrouting.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>statistics.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>subnets.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>switchmanager.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>topology.northbound</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>usermanager.northbound</artifactId>
- </dependency>
- </dependencies>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ </scm>
</project>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/networkconfig/bridgedomain"/>
<modules>
<docs docsDir="rest" title="Bridge Domain Configuration REST API" includeExampleXml="true" includeExampleJson="true"/>
- </modules>
+ </modules>
</enunciate>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
-<?xml version="1.0"?>\r
-<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">\r
-\r
- <services>\r
- <rest defaultRestSubcontext="/controller/nb/v2/neutron"/>\r
- </services>\r
-\r
- <modules>\r
- <docs docsDir="rest" title="OpenStack Neutron REST API" includeExampleXml="false" includeExampleJson="true"/>\r
- </modules>\r
-</enunciate>\r
+<?xml version="1.0"?>
+<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
+
+ <services>
+ <rest defaultRestSubcontext="/controller/nb/v2/neutron"/>
+ </services>
+
+ <modules>
+ <docs docsDir="rest" title="OpenStack Neutron REST API" includeExampleXml="false" includeExampleJson="true"/>
+ </modules>
+</enunciate>
<artifactId>networkconfig.neutron.northbound</artifactId>
<version>0.4.2-SNAPSHOT</version>
<packaging>bundle</packaging>
- <properties>
- <enunciate.version>1.26.2</enunciate.version>
- </properties>
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>2.3.6</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.codehaus.enunciate</groupId>
<artifactId>maven-enunciate-plugin</artifactId>
- <configuration>
- <configFile>enunciate.xml</configFile>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>docs</goal>
- </goals>
- </execution>
- </executions>
</plugin>
</plugins>
</build>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/staticroute"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/statistics"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/subnetservice"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/switchmanager"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.core.Property;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
/**
* The class describes set of properties attached to a node connector
*/
public class NodeConnectorProperties {
@XmlElement
private NodeConnector nodeconnector;
- @XmlElementRef
+
+ @XmlElement(name="property")
@XmlElementWrapper
@JsonIgnore
private Set<Property> properties;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.Property;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
/**
* The class describes set of properties attached to a node
*/
public class NodeProperties {
@XmlElement
private Node node;
- @XmlElementRef
+
+ @XmlElement(name="property")
@XmlElementWrapper
@JsonIgnore
private Set<Property> properties;
return NorthboundUtils.getResponse(status);
}
+ /**
+ * Get a property of a node
+ *
+ * @param containerName
+ * Name of the Container (Eg. 'SliceRed')
+ * @param nodeType
+ * Type of the node being programmed (Eg. 'OF')
+ * @param nodeId
+ * Node Identifier as specified by
+ * {@link org.opendaylight.controller.sal.core.Node} (Eg.
+ * '00:00:00:00:00:03:01:02')
+ * @param propertyName
+ * Name of the Property. Properties that can be deleted are
+ * description, forwarding(only in default container) and tier.
+ * @return Property value of the property
+ *
+ * <pre>
+ *
+ * Example:
+ *
+ * Request URL:
+ * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:01/property/description
+ *
+ * Response body in XML
+ * <description>
+ *   <value>switch1</value>
+ * </description>
+ *
+ * Response body in JSON
+ * {
+ *   "value": "switch1"
+ * }
+ * </pre>
+ */
+
+ @Path("/{containerName}/node/{nodeType}/{nodeId}/property/{propertyName}")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(String.class)
+ @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+ @ResponseCode(code = 404, condition = "The containerName is not found"),
+ @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
+ public Property getNodeProperty(@PathParam("containerName") String containerName,
+ @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
+ @PathParam("propertyName") String propertyName) {
+
+ if (!isValidContainer(containerName)) {
+ throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+ }
+ if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ + containerName);
+ }
+ ISwitchManager switchManager = getIfSwitchManagerService(containerName);
+ if (switchManager == null) {
+ throw new ServiceUnavailableException("Switch Manager " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ handleNodeAvailability(containerName, nodeType, nodeId);
+ Node node = Node.fromString(nodeType, nodeId);
+ if (node == null) {
+ throw new ResourceNotFoundException(nodeId + " : " + RestMessages.NONODE.toString());
+ }
+ SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
+ if (switchConfig == null) {
+ throw new ResourceNotFoundException(nodeId + " : " + "Config Not Found" );
+ } else {
+ Map<String, Property> nodeProperties = new HashMap<String, Property>(switchConfig.getNodeProperties());
+ if (!nodeProperties.containsKey(propertyName.toLowerCase())) {
+ String msg = "Property " + propertyName + " does not exist or not "
+ + "configured for switch " + nodeId;
+ throw new ResourceNotFoundException(msg);
+ } else {
+ return nodeProperties.get(propertyName.toLowerCase());
+ }
+ }
+ }
+
/**
*
* Retrieve a list of all the nodeconnectors and their properties in a given
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/topology"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
import org.opendaylight.controller.sal.core.Edge;
import org.opendaylight.controller.sal.core.Property;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class EdgeProperties {
@XmlElement
private Edge edge;
- @XmlElementRef
+
+ @XmlElement(name="property")
@XmlElementWrapper
@JsonIgnore
private Set<Property> properties;
<?xml version="1.0"?>
<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.28.xsd">
<services>
<rest defaultRestSubcontext="/controller/nb/v2/usermanager"/>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
}
}
} catch (IllegalStateException e) {
- log.debug("IllegalStateException Received by PendingPacketsAgerTimerHandler from: {}",
+ log.warn("IllegalStateException Received by PendingPacketsAgerTimerHandler from: {}",
e.getMessage());
}
}
* hope that the destination is known by hostTracker.
*/
private void sendPendingPacket(InetAddress dIP) {
- pendingPacketDestinations.get(dIP);
PendingPacketData pendingPacketData = pendingPacketDestinations.get(dIP);
if (pendingPacketData != null) {
handlePuntedIPPacket(pendingPacketData.pkt, pendingPacketData.incomingNodeConnector, false);
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
org.springframework.security.core.userdetails,
javax.xml.bind.annotation</Import-Package>
<Export-Package>org.opendaylight.controller.usermanager,</Export-Package>
- <Bundle-Activator></Bundle-Activator>
</instructions>
<manifestLocation>${project.basedir}/META-INF</manifestLocation>
</configuration>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
webconsole.product.url = http://www.opendaylight.org/
webconsole.product.image = /res/imgs/odl/logo.png
webconsole.favicon = /res/imgs/odl/favicon.ico
-
+#To disable web console authentication clear default username
+webconsole.username =
# webconsole.vendor.name = Linux Foundation
# webconsole.vendor.url = http://www.linuxfoundation.org/
# webconsole.vendor.image = /res/imgs/vendor.png
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>