2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.netconf.util;
10 import java.io.ByteArrayInputStream;
11 import java.io.ByteArrayOutputStream;
12 import java.io.StringWriter;
14 import javax.xml.parsers.DocumentBuilder;
15 import javax.xml.parsers.DocumentBuilderFactory;
16 import javax.xml.parsers.ParserConfigurationException;
17 import javax.xml.transform.OutputKeys;
18 import javax.xml.transform.Transformer;
19 import javax.xml.transform.TransformerException;
20 import javax.xml.transform.TransformerFactory;
21 import javax.xml.transform.TransformerFactoryConfigurationError;
22 import javax.xml.transform.dom.DOMResult;
23 import javax.xml.transform.dom.DOMSource;
24 import javax.xml.transform.sax.SAXResult;
25 import javax.xml.transform.sax.SAXTransformerFactory;
26 import javax.xml.transform.sax.TransformerHandler;
27 import javax.xml.transform.stream.StreamResult;
29 import org.junit.Ignore;
30 import org.junit.Test;
31 import org.openexi.proc.common.AlignmentType;
32 import org.openexi.proc.common.GrammarOptions;
33 import org.openexi.proc.grammars.GrammarCache;
34 import org.openexi.sax.EXIReader;
35 import org.openexi.sax.Transmogrifier;
36 import org.w3c.dom.Document;
37 import org.w3c.dom.Element;
38 import org.xml.sax.InputSource;
41 * This test case tests nagasena library used for exi encode/decode.
43 * This library does not work correctly, since it is impossible to encode and then decode DOM xml.
44 * Encoding DOM using sax Transformer produces invalid xml, that cannot be decoded (Problem seems to be the namespace handling).
48 public class EXILibTest {
50 public static final AlignmentType ALIGNMENT_TYPE = AlignmentType.preCompress;
53 public void testExiLibWithSaxTransformer() throws Exception {
54 final byte[] encode = encodeEXI(getDom2());
55 final byte[] encodeWithTransformer = encodeEXITransformer(getDom2());
57 // System.err.println(Arrays.toString(encode));
58 // System.err.println(Arrays.toString(encodeWithTransformer));
60 // This works fine (encoded from string)
62 // Error, encoded from Dom with Transformer cannot be decoded, Exception is thrown
65 // org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
68 // java.lang.NullPointerException
70 // depends on GrammarOptions.addNS(go); option set
71 decodeEXI(encodeWithTransformer);
74 private static final SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
76 public static byte[] encodeEXITransformer(final Element xml) throws Exception {
77 final Transmogrifier transmogrifier = new Transmogrifier();
79 transmogrifier.setAlignmentType(ALIGNMENT_TYPE);
81 final ByteArrayOutputStream out = new ByteArrayOutputStream();
83 transmogrifier.setGrammarCache(getGrammarCache());
85 transmogrifier.setOutputStream(out);
87 final Transformer transformer = saxTransformerFactory.newTransformer();
88 transformer.transform(new DOMSource(xml), new SAXResult(transmogrifier.getSAXTransmogrifier()));
90 return out.toByteArray();
93 public static byte[] encodeEXI(final Element xml) throws Exception {
94 final Transmogrifier transmogrifier = new Transmogrifier();
96 transmogrifier.setAlignmentType(ALIGNMENT_TYPE);
98 final ByteArrayOutputStream out = new ByteArrayOutputStream();
100 transmogrifier.setGrammarCache(getGrammarCache());
102 transmogrifier.setOutputStream(out);
104 transmogrifier.encode(new InputSource(new ByteArrayInputStream(toString(xml, false).getBytes())));
108 return out.toByteArray();
111 private static GrammarCache getGrammarCache() {
112 short go = GrammarOptions.DEFAULT_OPTIONS;
114 // This option on or off, nagasena still fails
115 // go = GrammarOptions.addNS(go);
117 return new GrammarCache(null, go);
120 public static Document decodeEXI(final byte[] input) throws Exception {
122 final GrammarCache grammarCache;
123 final DOMResult domResult = new DOMResult();
125 try(ByteArrayInputStream in = new ByteArrayInputStream(input)) {
127 final EXIReader reader = new EXIReader();
129 reader.setAlignmentType(ALIGNMENT_TYPE);
130 grammarCache = getGrammarCache();
132 reader.setGrammarCache(grammarCache);
134 final SAXTransformerFactory transformerFactory
135 = (SAXTransformerFactory) TransformerFactory.newInstance();
136 final TransformerHandler handler = transformerFactory.newTransformerHandler();
137 handler.setResult(domResult);
139 reader.setContentHandler(handler);
141 reader.parse(new InputSource(in));
144 return (Document) domResult.getNode();
147 public static Element getDom() {
150 final Document d = newDocument();
152 dom = d.createElement("rpc");
153 dom.setAttribute("xmlns", "a.b.c");
154 dom.setAttribute("message-id", "id");
155 dom.appendChild(d.createElement("inner"));
160 public static Element getDom2() {
163 final Document d = newDocument();
165 dom = d.createElementNS("a.b.c", "rpc");
166 dom.setAttribute("message-id", "id");
167 dom.appendChild(d.createElement("inner"));
172 private static final DocumentBuilderFactory BUILDERFACTORY;
175 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
176 factory.setNamespaceAware(true);
177 factory.setCoalescing(true);
178 factory.setIgnoringElementContentWhitespace(true);
179 factory.setIgnoringComments(true);
180 BUILDERFACTORY = factory;
183 private static Document newDocument() {
185 final DocumentBuilder builder = BUILDERFACTORY.newDocumentBuilder();
186 return builder.newDocument();
187 } catch (final ParserConfigurationException e) {
188 throw new RuntimeException("Failed to create document", e);
192 private static String toString(final Element xml, final boolean addXmlDeclaration) {
194 final Transformer transformer = TransformerFactory.newInstance().newTransformer();
195 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
196 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, addXmlDeclaration ? "no" : "yes");
198 final StreamResult result = new StreamResult(new StringWriter());
199 final DOMSource source = new DOMSource(xml);
200 transformer.transform(source, result);
202 return result.getWriter().toString();
203 } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
204 throw new RuntimeException("Unable to serialize xml element " + xml, e);