From b624989978c4b456fcd29a2b87eb52cbb3b6f152 Mon Sep 17 00:00:00 2001 From: Vaclav Demcak Date: Fri, 6 Mar 2015 14:35:45 +0100 Subject: [PATCH 1/1] Add SchemaContext to NormalizedNode parser in RESTCONF Correct parsing of identities, instance-identifiers and others, requires access to full SchemaContext, not only subset of it. Migrated to parser factory, which provides that access in order to correctly deserialize context-sensitive types. Change-Id: Ic92b9ce745080076a10d654acaba39e5c59f2b42 Signed-off-by: Vaclav Demcak --- .../impl/XmlNormalizedNodeBodyReader.java | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlNormalizedNodeBodyReader.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlNormalizedNodeBodyReader.java index ad7122058c..905cb50c3a 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlNormalizedNodeBodyReader.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlNormalizedNodeBodyReader.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import java.util.Collection; import java.util.Collections; import java.util.List; import javax.ws.rs.Consumes; @@ -34,6 +35,7 @@ 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.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import org.slf4j.Logger; @@ -47,18 +49,17 @@ import org.w3c.dom.Element; public class XmlNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsProvider implements MessageBodyReader { private final static Logger LOG = LoggerFactory.getLogger(XmlNormalizedNodeBodyReader.class); - private final static DomToNormalizedNodeParserFactory DOM_PARSER_FACTORY = DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER); private static final DocumentBuilderFactory BUILDERFACTORY; static { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); factory.setFeature("http://xml.org/sax/features/external-general-entities", false); factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); factory.setXIncludeAware(false); factory.setExpandEntityReferences(false); - } catch (ParserConfigurationException e) { + } catch (final ParserConfigurationException e) { throw new ExceptionInInitializerError(e); } factory.setNamespaceAware(true); @@ -80,19 +81,19 @@ public class XmlNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsPro final MultivaluedMap httpHeaders, final InputStream entityStream) throws IOException, WebApplicationException { try { - Optional path = getIdentifierWithSchema(); + final Optional path = getIdentifierWithSchema(); final DocumentBuilder dBuilder; try { dBuilder = BUILDERFACTORY.newDocumentBuilder(); - } catch (ParserConfigurationException e) { + } catch (final ParserConfigurationException e) { throw new RuntimeException("Failed to parse XML document", e); } - Document doc = dBuilder.parse(entityStream); + final Document doc = dBuilder.parse(entityStream); - NormalizedNode result = parse(path.get(),doc); + final NormalizedNode result = parse(path.get(),doc); return new NormalizedNodeContext(path.get(),result); - } catch (Exception e) { + } catch (final Exception e) { LOG.debug("Error parsing json input", e); throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL, @@ -100,14 +101,34 @@ public class XmlNormalizedNodeBodyReader extends AbstractIdentifierAwareJaxRsPro } } - private static NormalizedNode parse(InstanceIdentifierContext pathContext,Document doc) { - List elements = Collections.singletonList(doc.getDocumentElement()); + private static NormalizedNode parse(final InstanceIdentifierContext pathContext,final Document doc) { + + final List elements = Collections.singletonList(doc.getDocumentElement()); DataSchemaNode schemaNode = pathContext.getSchemaNode(); + + final String docRootElm = doc.getDocumentElement().getLocalName(); + final String schemaNodeName = pathContext.getSchemaNode().getQName().getLocalName(); + + // TODO : do we want to really follow netconf-restconf specification ? + if (!schemaNodeName.equalsIgnoreCase(docRootElm)) { + final Collection children = ((DataNodeContainer) schemaNode).getChildNodes(); + for (final DataSchemaNode child : children) { + if (child.getQName().getLocalName().equalsIgnoreCase(docRootElm)) { + schemaNode = child; + break; + } + } + } + + // FIXME the factory instance should be cached if the schema context is the same + final DomToNormalizedNodeParserFactory parserFactory = + DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, pathContext.getSchemaContext()); + if(schemaNode instanceof ContainerSchemaNode) { - return DOM_PARSER_FACTORY.getContainerNodeParser().parse(Collections.singletonList(doc.getDocumentElement()), (ContainerSchemaNode) schemaNode); + return parserFactory.getContainerNodeParser().parse(Collections.singletonList(doc.getDocumentElement()), (ContainerSchemaNode) schemaNode); } else if(schemaNode instanceof ListSchemaNode) { - ListSchemaNode casted = (ListSchemaNode) schemaNode; - return DOM_PARSER_FACTORY.getMapEntryNodeParser().parse(elements, casted); + final ListSchemaNode casted = (ListSchemaNode) schemaNode; + return parserFactory.getMapEntryNodeParser().parse(elements, casted); } return null; } -- 2.36.6