Skip to content

Commit

Permalink
Fix XML configuration's indentation with Java 9+
Browse files Browse the repository at this point in the history
Change ZapXmlConfiguration to force the creation of new nodes after
loading the configuration, to ensure just the configuration nodes are
persisted when saved (i.e. without any text nodes that would be indented
again).
Add tests to assert the expected behaviour.

Part of zaproxy#2602.
Fix zaproxy#4194 - Size of the configuration file keeps increasing each time
ZAP is started with Java 9+
  • Loading branch information
thc202 committed Jul 2, 2018
1 parent d1d711c commit 5db552e
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/org/zaproxy/zap/utils/ZapXmlConfiguration.java
Expand Up @@ -21,11 +21,14 @@

import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
Expand Down Expand Up @@ -131,6 +134,13 @@ public void error(SAXParseException ex) throws SAXException {
return result;
}

@Override
protected Transformer createTransformer() throws TransformerException {
Transformer transformer = super.createTransformer();
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
return transformer;
}

/**
* Creates a new instance of {@code ZapXmlConfiguration}. The configuration
* is loaded from the specified {@code url}.
Expand Down Expand Up @@ -176,4 +186,27 @@ public void setListDelimiter(char listDelimiter) {
public void setDelimiterParsingDisabled(boolean delimiterParsingDisabled) {
// Always disabled.
}

@Override
public void load(InputStream in) throws ConfigurationException {
super.load(in);
postLoad();
}

@Override
public void load(Reader in) throws ConfigurationException {
super.load(in);
postLoad();
}

private void postLoad() {
// Ensure it's used a "clean" document for proper indentation of the configurations.
// In newer Java versions (9+) the text nodes are indented as well, which would lead
// to additional text nodes each time the configuration is loaded/saved.
clearReferences(getRootNode());
String rootName = getRootElementName();
getDocument().removeChild(getDocument().getDocumentElement());
getDocument().appendChild(getDocument().createElement(rootName));
}

}
80 changes: 80 additions & 0 deletions test/org/zaproxy/zap/utils/ZapXmlConfigurationUnitTest.java
@@ -0,0 +1,80 @@
/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2018 The ZAP Development Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.zaproxy.zap.utils;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

import org.junit.Test;

/**
* Unit test for {@link ZapXmlConfiguration}.
*/
public class ZapXmlConfigurationUnitTest {

private static final String INDENTED_XML =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<a>\n" +
" <b>1</b>\n" +
" <c/>\n" +
" <d>\n" +
" <e/>\n" +
" <f>2</f>\n" +
" </d>\n" +
"</a>\n";

@Test
public void shouldSaveNewConfigurationIndented() throws Exception {
// Given
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZapXmlConfiguration conf = new ZapXmlConfiguration();
conf.setRootElementName("a");
conf.setProperty("b", "1");
conf.setProperty("c", "");
conf.setProperty("d.e", "");
conf.setProperty("d.f", "2");
// When
conf.save(outputStream);
// Then
assertThat(contents(outputStream), is(equalTo(INDENTED_XML)));
}

@Test
public void shouldSaveLoadedConfigurationIndented() throws Exception {
// Given
ByteArrayInputStream inputStream = new ByteArrayInputStream(INDENTED_XML.getBytes(StandardCharsets.UTF_8));
ZapXmlConfiguration conf = new ZapXmlConfiguration(inputStream);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// When
conf.save(outputStream);
// Then
assertThat(contents(outputStream), is(equalTo(INDENTED_XML)));
}

private static String contents(ByteArrayOutputStream outputStream) throws UnsupportedEncodingException {
return outputStream.toString(StandardCharsets.UTF_8.name()).replaceAll(System.lineSeparator(), "\n");
}
}

0 comments on commit 5db552e

Please sign in to comment.