Skip to content

Commit 134d985

Browse files
authored
Merge pull request #35 from RUB-NDS/xmlPrettyPrintingFix
Xml pretty printing fix
2 parents 38f943f + 3938b61 commit 134d985

File tree

8 files changed

+105
-16
lines changed

8 files changed

+105
-16
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
language: java
2-
2+
dist: trusty
33
sudo: false
44

55
jdk:

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>de.rub.nds</groupId>
55
<artifactId>ModifiableVariable</artifactId>
6-
<version>2.5</version>
6+
<version>2.6</version>
77
<packaging>jar</packaging>
88

99
<name>ModifiableVariable</name>

src/main/java/de/rub/nds/modifiablevariable/ModifiableVariable.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,25 @@
1010

1111
import java.io.Serializable;
1212
import javax.xml.bind.annotation.XmlAnyElement;
13+
import javax.xml.bind.annotation.XmlAttribute;
1314
import javax.xml.bind.annotation.XmlRootElement;
1415
import javax.xml.bind.annotation.XmlTransient;
1516

1617
/**
1718
* The base abstract class for modifiable variables, including the getValue
1819
* function.
19-
*
20+
*
2021
* The class needs to be defined transient to allow propOrder definition in
2122
* subclasses, see:
2223
* http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html
23-
*
24+
*
2425
*/
2526
@XmlRootElement
2627
@XmlTransient
2728
public abstract class ModifiableVariable<E> implements Serializable {
2829

30+
protected Boolean autoformat = null;
31+
2932
private VariableModification<E> modification = null;
3033

3134
private boolean createRandomModification;
@@ -36,6 +39,15 @@ public ModifiableVariable() {
3639

3740
}
3841

42+
@XmlAttribute(required = false)
43+
public Boolean getAutoformat() {
44+
return autoformat;
45+
}
46+
47+
public void setAutoformat(Boolean autoformat) {
48+
this.autoformat = autoformat;
49+
}
50+
3951
public void setModification(VariableModification<E> modification) {
4052
this.modification = modification;
4153
}

src/main/java/de/rub/nds/modifiablevariable/bytearray/ModifiableByteArray.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
@XmlType(propOrder = { "originalValue", "modification", "assertEquals" })
2727
public class ModifiableByteArray extends ModifiableVariable<byte[]> implements Serializable {
2828

29+
public ModifiableByteArray() {
30+
autoformat = true;
31+
}
32+
2933
private byte[] originalValue;
3034

3135
@Override
@@ -88,10 +92,12 @@ public String toString() {
8892

8993
@Override
9094
public boolean equals(Object o) {
91-
if (this == o)
95+
if (this == o) {
9296
return true;
93-
if (!(o instanceof ModifiableByteArray))
97+
}
98+
if (!(o instanceof ModifiableByteArray)) {
9499
return false;
100+
}
95101

96102
ModifiableByteArray that = (ModifiableByteArray) o;
97103

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* ModifiableVariable - A Variable Concept for Runtime Modifications
3+
*
4+
* Copyright 2014-2017 Ruhr University Bochum / Hackmanit GmbH
5+
*
6+
* Licensed under Apache License 2.0
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*/
9+
package de.rub.nds.modifiablevariable.util;
10+
11+
import javax.xml.bind.annotation.adapters.XmlAdapter;
12+
13+
/**
14+
*
15+
*/
16+
public class UnformattedByteArrayAdapter extends XmlAdapter<String, byte[]> {
17+
18+
@Override
19+
public byte[] unmarshal(String value) {
20+
21+
value = value.replaceAll("\\s", "");
22+
return ArrayConverter.hexStringToByteArray(value);
23+
}
24+
25+
@Override
26+
public String marshal(byte[] value) {
27+
return ArrayConverter.bytesToHexString(value, false, false);
28+
}
29+
}

src/main/java/de/rub/nds/modifiablevariable/util/XMLPrettyPrinter.java

+26-8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
import javax.xml.xpath.XPathFactory;
2828
import javax.xml.xpath.XPathFactoryConfigurationException;
2929
import org.w3c.dom.Document;
30+
import org.w3c.dom.Element;
31+
import org.w3c.dom.NamedNodeMap;
32+
import org.w3c.dom.Node;
3033
import org.w3c.dom.NodeList;
3134
import org.xml.sax.InputSource;
3235
import org.xml.sax.SAXException;
@@ -40,6 +43,20 @@ public class XMLPrettyPrinter {
4043

4144
public static int IDENT_AMOUNT = 4;
4245

46+
/**
47+
* This function formats all tags (and their children) which are marked with
48+
* the autoformat="true" attribute and removes this attribute.
49+
*
50+
* @param input
51+
* @return
52+
* @throws TransformerConfigurationException
53+
* @throws ParserConfigurationException
54+
* @throws SAXException
55+
* @throws IOException
56+
* @throws TransformerException
57+
* @throws XPathExpressionException
58+
* @throws XPathFactoryConfigurationException
59+
*/
4360
public static String prettyPrintXML(String input) throws TransformerConfigurationException,
4461
ParserConfigurationException, SAXException, IOException, TransformerException, XPathExpressionException,
4562
XPathFactoryConfigurationException {
@@ -50,24 +67,25 @@ public static String prettyPrintXML(String input) throws TransformerConfiguratio
5067
StreamResult result = new StreamResult(new StringWriter());
5168
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
5269
.parse(new InputSource(new StringReader(input)));
53-
XPathExpression xpath = XPathFactory.newInstance().newXPath().compile("//*[count(./*) = 0]");
5470
XPathExpression xpathDepth = XPathFactory.newInstance().newXPath().compile("count(ancestor-or-self::*)");
55-
56-
NodeList textNodes = (NodeList) xpath.evaluate(doc, XPathConstants.NODESET);
57-
71+
XPathExpression toBeFormatted = XPathFactory.newInstance().newXPath().compile("//*[@autoformat = \'true\']/*");
72+
NodeList textNodes = (NodeList) toBeFormatted.evaluate(doc, XPathConstants.NODESET);
5873
for (int i = 0; i < textNodes.getLength(); i++) {
59-
String content = textNodes.item(i).getTextContent();
74+
Node node = textNodes.item(i);
75+
String content = node.getTextContent();
6076
double doubleDepth = (Double) xpathDepth.evaluate(textNodes.item(i), XPathConstants.NUMBER);
6177
int depth = (int) doubleDepth;
6278
String emptyString = createEmptyString(depth);
6379
String newContent = content.replaceAll("\n", ("\n" + emptyString));
64-
if (newContent.length() > content.length()) {
80+
if (newContent.length() > content.length()
81+
&& newContent.substring(newContent.length() - IDENT_AMOUNT, newContent.length()).trim().equals("")) {
6582
newContent = newContent.substring(0, newContent.length() - IDENT_AMOUNT);
6683
}
67-
textNodes.item(i).setTextContent(newContent);
84+
node.setTextContent(newContent);
85+
Element element = (Element) node.getParentNode();
86+
element.removeAttribute("autoformat");
6887

6988
}
70-
7189
DOMSource source = new DOMSource(doc);
7290
transformer.transform(source, result);
7391
return result.getWriter().toString();

src/test/java/de/rub/nds/modifiablevariable/util/ArrayConverterTest.java

+25
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111
import de.rub.nds.modifiablevariable.ModifiableVariableFactory;
1212
import de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray;
1313
import java.math.BigInteger;
14+
import java.util.Random;
15+
import org.hamcrest.core.IsEqual;
1416
import static org.junit.Assert.assertArrayEquals;
1517
import static org.junit.Assert.assertEquals;
18+
import static org.junit.Assert.assertThat;
1619
import org.junit.Test;
1720

1821
public class ArrayConverterTest {
@@ -247,4 +250,26 @@ public void testReverseByteOrder() {
247250
assertArrayEquals("Testing byte order reversion", new byte[] { 0x04, 0x03, 0x02, 0x01, 0x00 },
248251
ArrayConverter.reverseByteOrder(array));
249252
}
253+
254+
@Test
255+
public void testBigIntegerReconversion() {
256+
Random r = new Random(0);
257+
for (int i = 0; i < 10000; i++) {
258+
BigInteger b = new BigInteger(1024 + r.nextInt(1000), r);
259+
byte[] bigIntegerToByteArray = ArrayConverter.bigIntegerToByteArray(b);
260+
BigInteger c = new BigInteger(1, bigIntegerToByteArray);
261+
assertEquals(b, c);
262+
}
263+
}
264+
265+
@Test
266+
public void testIntegerReconversion() {
267+
Random r = new Random(0);
268+
for (int i = 0; i < 10000; i++) {
269+
Integer b = r.nextInt();
270+
byte[] intBytes = ArrayConverter.intToBytes(b, 4);
271+
Integer c = ArrayConverter.bytesToInt(intBytes);
272+
assertEquals(b, c);
273+
}
274+
}
250275
}

src/test/java/de/rub/nds/modifiablevariable/util/XMLPrettyPrinterTest.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,13 @@ public class XMLPrettyPrinterTest {
2121
*/
2222
@Test
2323
public void testPrettyPrintXML() throws Exception {
24-
String input = "<modifiableByteArray>\n" + " <originalValue>\n"
24+
String input = "<modifiableByteArray autoformat=\"true\">\n" + " <originalValue>\n"
2525
+ "FF 01 02 03 FF 01 02 03 FF 01 02 03 FF 01 02 03\n" + "FF 01 02 03\n" + "</originalValue>\n"
2626
+ "</modifiableByteArray>";
2727
String expected = "<modifiableByteArray>\n" + " <originalValue>\n"
2828
+ " FF 01 02 03 FF 01 02 03 FF 01 02 03 FF 01 02 03\n" + " FF 01 02 03\n"
2929
+ " </originalValue>\n" + "</modifiableByteArray>";
3030
String result = XMLPrettyPrinter.prettyPrintXML(input);
31-
3231
assertEquals(expected.trim(), result.trim());
3332
}
3433
}

0 commit comments

Comments
 (0)