From: Igor Foltin Date: Sun, 30 Jul 2017 08:41:42 +0000 (+0200) Subject: Bug 8879: Migrate controller to the new XML parser X-Git-Tag: release/nitrogen~22 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=93b203c3e2223018000af3472e8eca5363152910 Bug 8879: Migrate controller to the new XML parser Migrate blueprint to the new XML parser from YANG tools. Change-Id: Ib82da2f4b2b49dde7df78f425c700b9d3f473a26 Signed-off-by: Igor Foltin --- diff --git a/opendaylight/blueprint/pom.xml b/opendaylight/blueprint/pom.xml index dc11fac924..ec90f78bc0 100644 --- a/opendaylight/blueprint/pom.xml +++ b/opendaylight/blueprint/pom.xml @@ -38,6 +38,13 @@ pom import + + org.opendaylight.yangtools + yangtools-artifacts + 1.2.0-SNAPSHOT + pom + import + @@ -71,6 +78,10 @@ org.opendaylight.mdsal mdsal-binding-dom-codec + + org.opendaylight.yangtools + yang-data-codec-xml + org.osgi org.osgi.core diff --git a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/BindingContext.java b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/BindingContext.java index e4ae3fc0ef..fb950b8a58 100644 --- a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/BindingContext.java +++ b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/BindingContext.java @@ -9,23 +9,34 @@ package org.opendaylight.controller.blueprint.ext; import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.util.Collections; +import java.net.URISyntaxException; import java.util.List; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLStreamException; +import javax.xml.transform.dom.DOMSource; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.Identifiable; import org.opendaylight.yangtools.yang.binding.Identifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.util.BindingReflections; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; -import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.osgi.service.blueprint.container.ComponentDefinitionException; import org.w3c.dom.Element; +import org.xml.sax.SAXException; /** * Base class to abstract binding type-specific behavior. @@ -72,8 +83,23 @@ public abstract class BindingContext { bindingQName = BindingReflections.findQName(appConfigBindingClass); } - public abstract NormalizedNode parseDataElement(Element element, DataSchemaNode dataSchema, - DomToNormalizedNodeParserFactory parserFactory); + public NormalizedNode parseDataElement(final Element element, final DataSchemaNode dataSchema, + final SchemaContext schemaContext) throws XMLStreamException, IOException, ParserConfigurationException, + SAXException, URISyntaxException { + final NormalizedNodeResult resultHolder = new NormalizedNodeResult(); + final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder); + final XmlParserStream xmlParser = XmlParserStream.create(writer, schemaContext, dataSchema); + xmlParser.traverse(new DOMSource(element)); + + final NormalizedNode result = resultHolder.getResult(); + if (result instanceof MapNode) { + final MapNode mapNode = (MapNode) result; + final MapEntryNode mapEntryNode = mapNode.getValue().iterator().next(); + return mapEntryNode; + } + + return result; + } public abstract NormalizedNode newDefaultNode(DataSchemaNode dataSchema); @@ -91,13 +117,6 @@ public abstract class BindingContext { public NormalizedNode newDefaultNode(final DataSchemaNode dataSchema) { return ImmutableNodes.containerNode(bindingQName); } - - @Override - public NormalizedNode parseDataElement(final Element element, final DataSchemaNode dataSchema, - final DomToNormalizedNodeParserFactory parserFactory) { - return parserFactory.getContainerNodeParser().parse(Collections.singletonList(element), - (ContainerSchemaNode)dataSchema); - } } /** @@ -133,12 +152,5 @@ public abstract class BindingContext { QName listKeyQName = keys.get(0); return ImmutableNodes.mapEntryBuilder(bindingQName, listKeyQName, appConfigListKeyValue).build(); } - - @Override - public NormalizedNode parseDataElement(final Element element, final DataSchemaNode dataSchema, - final DomToNormalizedNodeParserFactory parserFactory) { - return parserFactory.getMapEntryNodeParser().parse(Collections.singletonList(element), - (ListSchemaNode)dataSchema); - } } } diff --git a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/DataStoreAppConfigDefaultXMLReader.java b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/DataStoreAppConfigDefaultXMLReader.java index 2d24c21463..709e0b4bab 100644 --- a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/DataStoreAppConfigDefaultXMLReader.java +++ b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/DataStoreAppConfigDefaultXMLReader.java @@ -12,7 +12,10 @@ import com.google.common.base.Strings; import com.google.common.io.Resources; import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; import java.net.URL; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLStreamException; import org.opendaylight.controller.sal.core.api.model.SchemaService; import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer; import org.opendaylight.yangtools.util.xml.UntrustedXML; @@ -20,8 +23,6 @@ import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils; -import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; @@ -51,7 +52,8 @@ public class DataStoreAppConfigDefaultXMLReader { @FunctionalInterface public interface FallbackConfigProvider { - NormalizedNode get(SchemaContext schemaContext, DataSchemaNode dataSchema); + NormalizedNode get(SchemaContext schemaContext, DataSchemaNode dataSchema) throws IOException, + XMLStreamException, ParserConfigurationException, SAXException, URISyntaxException; } @FunctionalInterface @@ -90,7 +92,8 @@ public class DataStoreAppConfigDefaultXMLReader { return Resources.getResource(testClass, defaultAppConfigFileName); } - public T createDefaultInstance() throws ConfigXMLReaderException { + public T createDefaultInstance() throws ConfigXMLReaderException, ParserConfigurationException, XMLStreamException, + IOException, SAXException, URISyntaxException { return createDefaultInstance((schemaContext, dataSchema) -> { throw new IllegalArgumentException("Failed to read XML " + "(not creating model from defaults as runtime would, for better clarity in tests)"); @@ -98,7 +101,8 @@ public class DataStoreAppConfigDefaultXMLReader { } @SuppressWarnings("unchecked") - public T createDefaultInstance(final FallbackConfigProvider fallback) throws ConfigXMLReaderException { + public T createDefaultInstance(final FallbackConfigProvider fallback) throws ConfigXMLReaderException, + URISyntaxException, ParserConfigurationException, XMLStreamException, SAXException, IOException { YangInstanceIdentifier yangPath = bindingSerializer.toYangInstanceIdentifier(bindingContext.appConfigPath); LOG.debug("{}: Creating app config instance from path {}, Qname: {}", logName, yangPath, @@ -157,9 +161,6 @@ public class DataStoreAppConfigDefaultXMLReader { appConfigFileName = moduleName + "_" + bindingContext.bindingQName.getLocalName() + ".xml"; } - final DomToNormalizedNodeParserFactory parserFactory = DomToNormalizedNodeParserFactory.getInstance( - XmlUtils.DEFAULT_XML_CODEC_PROVIDER, schemaContext); - Optional optionalURL; try { optionalURL = inputStreamProvider.getURL(appConfigFileName); @@ -175,12 +176,13 @@ public class DataStoreAppConfigDefaultXMLReader { try (InputStream is = url.openStream()) { Document root = UntrustedXML.newDocumentBuilder().parse(is); NormalizedNode dataNode = bindingContext.parseDataElement(root.getDocumentElement(), dataSchema, - parserFactory); + schemaContext); LOG.debug("{}: Parsed data node: {}", logName, dataNode); return dataNode; - } catch (SAXException | IOException e) { + } catch (final IOException | SAXException | XMLStreamException | ParserConfigurationException + | URISyntaxException e) { String msg = String.format("%s: Could not read/parse app config %s", logName, url); LOG.error(msg, e); throw new ConfigXMLReaderException(msg, e); diff --git a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/DataStoreAppConfigMetadata.java b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/DataStoreAppConfigMetadata.java index f1024d7e4b..c2e7e3723c 100644 --- a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/DataStoreAppConfigMetadata.java +++ b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/ext/DataStoreAppConfigMetadata.java @@ -12,11 +12,15 @@ import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; import java.util.Collection; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLStreamException; import org.apache.aries.blueprint.services.ExtendedBlueprintContainer; import org.opendaylight.controller.blueprint.ext.DataStoreAppConfigDefaultXMLReader.ConfigURLProvider; import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener; @@ -33,14 +37,13 @@ import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSeriali import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlUtils; -import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.osgi.service.blueprint.container.ComponentDefinitionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; +import org.xml.sax.SAXException; /** * Factory metadata corresponding to the "clustered-app-config" element that obtains an application's @@ -269,7 +272,8 @@ public class DataStoreAppConfigMetadata extends AbstractDependentComponentFactor } }); - } catch (final ConfigXMLReaderException e) { + } catch (final ConfigXMLReaderException | IOException | SAXException | XMLStreamException + | ParserConfigurationException | URISyntaxException e) { if (e.getCause() == null) { setFailureMessage(e.getMessage()); } else { @@ -281,21 +285,18 @@ public class DataStoreAppConfigMetadata extends AbstractDependentComponentFactor @Nullable private NormalizedNode parsePossibleDefaultAppConfigElement(final SchemaContext schemaContext, - final DataSchemaNode dataSchema) { + final DataSchemaNode dataSchema) throws URISyntaxException, IOException, ParserConfigurationException, + SAXException, XMLStreamException { if (defaultAppConfigElement == null) { return null; } LOG.debug("{}: parsePossibleDefaultAppConfigElement for {}", logName(), bindingContext.bindingQName); - DomToNormalizedNodeParserFactory parserFactory = DomToNormalizedNodeParserFactory.getInstance( - XmlUtils.DEFAULT_XML_CODEC_PROVIDER, schemaContext); - - LOG.debug("{}: Got app config schema: {}", logName(), dataSchema); NormalizedNode dataNode = bindingContext.parseDataElement(defaultAppConfigElement, dataSchema, - parserFactory); + schemaContext); LOG.debug("{}: Parsed data node: {}", logName(), dataNode);