From 37b37e348a362f31e01077753cee1c6bdaa645dc Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Wed, 22 Oct 2014 17:49:19 +0200 Subject: [PATCH] BUG-2184 Fix subtree filtering for identity-ref leaves Change-Id: I7d367c793a461ae26f56ddf611f7e45a723f28fc Signed-off-by: Maros Marsalek --- .../netconf/impl/SubtreeFilter.java | 31 +++++++++++--- .../netconf/impl/SubtreeFilterTest.java | 2 +- .../test/resources/subtree/9/post-filter.xml | 14 +++++++ .../test/resources/subtree/9/pre-filter.xml | 40 +++++++++++++++++++ .../src/test/resources/subtree/9/request.xml | 19 +++++++++ .../netconf/util/xml/XmlElement.java | 27 +++++++++---- 6 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/post-filter.xml create mode 100644 opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/pre-filter.xml create mode 100644 opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/request.xml diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/SubtreeFilter.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/SubtreeFilter.java index 6e81584133..42a8bae448 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/SubtreeFilter.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/SubtreeFilter.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.impl; import com.google.common.base.Optional; import java.io.IOException; +import java.util.Map; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation.OperationNameAndNamespace; @@ -73,7 +74,7 @@ public class SubtreeFilter { return result; } - private static void addSubtree(XmlElement filter, XmlElement src, XmlElement dst) { + private static void addSubtree(XmlElement filter, XmlElement src, XmlElement dst) throws NetconfDocumentedException { for (XmlElement srcChild : src.getChildElements()) { for (XmlElement filterChild : filter.getChildElements()) { addSubtree2(filterChild, srcChild, dst); @@ -81,7 +82,7 @@ public class SubtreeFilter { } } - private static MatchingResult addSubtree2(XmlElement filter, XmlElement src, XmlElement dstParent) { + private static MatchingResult addSubtree2(XmlElement filter, XmlElement src, XmlElement dstParent) throws NetconfDocumentedException { Document document = dstParent.getDomElement().getOwnerDocument(); MatchingResult matches = matches(src, filter); if (matches != MatchingResult.NO_MATCH && matches != MatchingResult.CONTENT_MISMATCH) { @@ -123,7 +124,7 @@ public class SubtreeFilter { * Shallow compare src node to filter: tag name and namespace must match. * If filter node has no children and has text content, it also must match. */ - private static MatchingResult matches(XmlElement src, XmlElement filter) { + private static MatchingResult matches(XmlElement src, XmlElement filter) throws NetconfDocumentedException { boolean tagMatch = src.getName().equals(filter.getName()) && src.getNamespaceOptionally().equals(filter.getNamespaceOptionally()); MatchingResult result = null; @@ -131,7 +132,7 @@ public class SubtreeFilter { // match text content Optional maybeText = filter.getOnlyTextContentOptionally(); if (maybeText.isPresent()) { - if (maybeText.equals(src.getOnlyTextContentOptionally())) { + if (maybeText.equals(src.getOnlyTextContentOptionally()) || prefixedContentMatches(filter, src)) { result = MatchingResult.CONTENT_MATCH; } else { result = MatchingResult.CONTENT_MISMATCH; @@ -159,10 +160,30 @@ public class SubtreeFilter { if (result == null) { result = MatchingResult.NO_MATCH; } - logger.debug("Matching {} to {} resulted in {}", src, filter, tagMatch); + logger.debug("Matching {} to {} resulted in {}", src, filter, result); return result; } + private static boolean prefixedContentMatches(final XmlElement filter, final XmlElement src) throws NetconfDocumentedException { + final Map.Entry prefixToNamespaceOfFilter = filter.findNamespaceOfTextContent(); + final Map.Entry prefixToNamespaceOfSrc = src.findNamespaceOfTextContent(); + + final String prefix = prefixToNamespaceOfFilter.getKey(); + // If this is not a prefixed content, we do not need to continue since content do not match + if(prefix.equals(XmlElement.DEFAULT_NAMESPACE_PREFIX)) { + return false; + } + // Namespace mismatch + if(!prefixToNamespaceOfFilter.getValue().equals(prefixToNamespaceOfSrc.getValue())) { + return false; + } + + final String unprefixedFilterContent = filter.getTextContent().substring(prefix.length()); + final String unprefixedSrcCOntnet = src.getTextContent().substring(prefix.length()); + // Finally compare unprefixed content + return unprefixedFilterContent.equals(unprefixedSrcCOntnet); + } + enum MatchingResult { NO_MATCH, TAG_MATCH, CONTENT_MATCH, CONTENT_MISMATCH } diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/SubtreeFilterTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/SubtreeFilterTest.java index b11834386e..5d9470750e 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/SubtreeFilterTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/SubtreeFilterTest.java @@ -36,7 +36,7 @@ public class SubtreeFilterTest { @Parameters public static Collection data() { List result = new ArrayList<>(); - for (int i = 0; i <= 8; i++) { + for (int i = 0; i <= 9; i++) { result.add(new Object[]{i}); } return result; diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/post-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/post-filter.xml new file mode 100644 index 0000000000..afe9655326 --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/post-filter.xml @@ -0,0 +1,14 @@ + + + + + + fred + x:admin + Fred Flintstone + + + + + \ No newline at end of file diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/pre-filter.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/pre-filter.xml new file mode 100644 index 0000000000..eca3241f05 --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/pre-filter.xml @@ -0,0 +1,40 @@ + + + + + + root + superuser + Charlie Root + + 1 + 1 + + + + fred + x:admin + Fred Flintstone + + 2 + 2 + + + + barney + admin + Barney Rubble + + 2 + 3 + + + + + + admin + + + + + \ No newline at end of file diff --git a/opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/request.xml b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/request.xml new file mode 100644 index 0000000000..47da0feec1 --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/test/resources/subtree/9/request.xml @@ -0,0 +1,19 @@ + + + + + + + + + + fred + a:admin + + + + + + + \ No newline at end of file diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java index 78efe7e972..3c63204881 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java @@ -37,6 +37,8 @@ import org.xml.sax.SAXException; public final class XmlElement { + public static final String DEFAULT_NAMESPACE_PREFIX = ""; + private final Element element; private static final Logger logger = LoggerFactory.getLogger(XmlElement.class); @@ -72,16 +74,16 @@ public final class XmlElement { return xmlElement; } - private static Map extractNamespaces(Element typeElement) throws NetconfDocumentedException { + private Map extractNamespaces() throws NetconfDocumentedException { Map namespaces = new HashMap<>(); - NamedNodeMap attributes = typeElement.getAttributes(); + NamedNodeMap attributes = element.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node attribute = attributes.item(i); String attribKey = attribute.getNodeName(); if (attribKey.startsWith(XmlUtil.XMLNS_ATTRIBUTE_KEY)) { String prefix; if (attribKey.equals(XmlUtil.XMLNS_ATTRIBUTE_KEY)) { - prefix = ""; + prefix = DEFAULT_NAMESPACE_PREFIX; } else { if (!attribKey.startsWith(XmlUtil.XMLNS_ATTRIBUTE_KEY + ":")){ throw new NetconfDocumentedException("Attribute doesn't start with :", @@ -94,6 +96,15 @@ public final class XmlElement { namespaces.put(prefix, attribute.getNodeValue()); } } + + // namespace does not have to be defined on this element but inherited + if(!namespaces.containsKey(DEFAULT_NAMESPACE_PREFIX)) { + Optional namespaceOptionally = getNamespaceOptionally(); + if(namespaceOptionally.isPresent()) { + namespaces.put(DEFAULT_NAMESPACE_PREFIX, namespaceOptionally.get()); + } + } + return namespaces; } @@ -132,7 +143,7 @@ public final class XmlElement { } public String getName() { - if (element.getLocalName()!=null && !element.getLocalName().equals("")){ + if (element.getLocalName()!=null && !element.getLocalName().equals(DEFAULT_NAMESPACE_PREFIX)){ return element.getLocalName(); } return element.getTagName(); @@ -327,7 +338,7 @@ public final class XmlElement { public String getTextContent() throws NetconfDocumentedException { NodeList childNodes = element.getChildNodes(); if (childNodes.getLength() == 0) { - return ""; + return DEFAULT_NAMESPACE_PREFIX; } for(int i = 0; i < childNodes.getLength(); i++) { Node textChild = childNodes.item(i); @@ -356,7 +367,7 @@ public final class XmlElement { public String getNamespaceAttribute() throws MissingNameSpaceException { String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY); - if (attribute == null || attribute.equals("")){ + if (attribute == null || attribute.equals(DEFAULT_NAMESPACE_PREFIX)){ throw new MissingNameSpaceException(String.format("Element %s must specify namespace", toString()), NetconfDocumentedException.ErrorType.application, @@ -415,14 +426,14 @@ public final class XmlElement { * is found value will be null. */ public Map.Entry findNamespaceOfTextContent() throws NetconfDocumentedException { - Map namespaces = extractNamespaces(element); + Map namespaces = extractNamespaces(); String textContent = getTextContent(); int indexOfColon = textContent.indexOf(':'); String prefix; if (indexOfColon > -1) { prefix = textContent.substring(0, indexOfColon); } else { - prefix = ""; + prefix = DEFAULT_NAMESPACE_PREFIX; } if (!namespaces.containsKey(prefix)) { throw new IllegalArgumentException("Cannot find namespace for " + XmlUtil.toString(element) + ". Prefix from content is " -- 2.36.6