Skip to content

Commit c88e507

Browse files
GWC make use of XMLUtils to make better use of GeoTools Hints (#1534)
* Add PMD rules to check and recommend use of XMLUtils * Using GT utility classes for XML parsing/producing * GeoRSSReader: making use of XMLUtils utility class from GT * Adding a PMD rule to avoid direct calls to XMLInputFactory.newInstance() * Also go through XMLUtils for sensible defaults on DocumentBuilderFactory * XMLConfiguration - block external schema resolution * Make use of XMLUtils.newSchemaFactory() and fix up validation based on GeoWebCache 2.0.0 --------- Co-authored-by: Pierre Mauduit <pierre.mauduit@camptocamp.com>
1 parent 5d1c9e5 commit c88e507

15 files changed

Lines changed: 613 additions & 45 deletions

File tree

geowebcache/core/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
<groupId>org.geotools</groupId>
2424
<artifactId>gt-coverage</artifactId>
2525
</dependency>
26+
<dependency>
27+
<groupId>org.geotools</groupId>
28+
<artifactId>gt-xml</artifactId>
29+
</dependency>
2630
<dependency>
2731
<groupId>org.apache.commons</groupId>
2832
<artifactId>commons-collections4</artifactId>

geowebcache/core/src/main/java/org/geowebcache/config/XMLConfiguration.java

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
import java.io.FileNotFoundException;
2222
import java.io.IOException;
2323
import java.io.InputStream;
24+
import java.io.OutputStream;
2425
import java.io.OutputStreamWriter;
26+
import java.io.PrintWriter;
2527
import java.io.UnsupportedEncodingException;
2628
import java.net.MalformedURLException;
2729
import java.net.URL;
@@ -41,19 +43,21 @@
4143
import java.util.logging.Logger;
4244
import java.util.stream.Collectors;
4345
import javax.annotation.Nullable;
46+
import javax.xml.XMLConstants;
4447
import javax.xml.parsers.DocumentBuilder;
4548
import javax.xml.parsers.DocumentBuilderFactory;
4649
import javax.xml.transform.Transformer;
4750
import javax.xml.transform.TransformerException;
48-
import javax.xml.transform.TransformerFactory;
4951
import javax.xml.transform.TransformerFactoryConfigurationError;
5052
import javax.xml.transform.dom.DOMResult;
5153
import javax.xml.transform.dom.DOMSource;
54+
import javax.xml.transform.stream.StreamResult;
5255
import javax.xml.transform.stream.StreamSource;
5356
import javax.xml.validation.Schema;
5457
import javax.xml.validation.SchemaFactory;
5558
import javax.xml.validation.Validator;
5659
import org.geotools.util.logging.Logging;
60+
import org.geotools.xml.XMLUtils;
5761
import org.geowebcache.GeoWebCacheEnvironment;
5862
import org.geowebcache.GeoWebCacheException;
5963
import org.geowebcache.GeoWebCacheExtensions;
@@ -117,6 +121,10 @@ public class XMLConfiguration
117121

118122
public static final String DEFAULT_CONFIGURATION_FILE_NAME = "geowebcache.xml";
119123

124+
public static final String SCHEMA_NAMESPACE_PREFIX = "http://geowebcache.org/schema/";
125+
126+
public static final String DEFAULT_SCHEMA_RESOURCE = "geowebcache.xsd";
127+
120128
private static Logger log = Logging.getLogger(XMLConfiguration.class.getName());
121129

122130
/** Web app context, used to look up {@link XMLConfigurationProvider}s. */
@@ -614,9 +622,9 @@ private synchronized void addOrReplaceGridSet(final XMLGridSet gridSet) throws I
614622
static Node loadDocument(InputStream xmlFile) throws ConfigurationException, IOException {
615623
Node topNode = null;
616624
try {
617-
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
625+
DocumentBuilderFactory docBuilderFactory = XMLUtils.newDocumentBuilderFactory();
618626
docBuilderFactory.setNamespaceAware(true);
619-
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
627+
DocumentBuilder docBuilder = XMLUtils.newDocumentBuilder(docBuilderFactory);
620628
topNode = checkAndTransform(docBuilder.parse(xmlFile));
621629
} catch (Exception e) {
622630
throw (IOException) new IOException(e.getMessage()).initCause(e);
@@ -629,14 +637,12 @@ private static Node checkAndTransform(Document doc) throws ConfigurationExceptio
629637
Node rootNode = doc.getDocumentElement();
630638

631639
// debugPrint(rootNode);
632-
633640
if (!rootNode.getNodeName().equals("gwcConfiguration")) {
634641
log.config("The configuration file is of the pre 1.0 type, trying to convert.");
635642
rootNode = applyTransform(rootNode, "geowebcache_pre10.xsl").getFirstChild();
636643
}
637644

638645
// debugPrint(rootNode);
639-
640646
if (rootNode.getNamespaceURI().equals("http://geowebcache.org/schema/1.0.0")) {
641647
log.config("Updating configuration from 1.0.0 to 1.0.1");
642648
rootNode = applyTransform(rootNode, "geowebcache_100.xsl").getFirstChild();
@@ -716,6 +722,11 @@ private static Node checkAndTransform(Document doc) throws ConfigurationExceptio
716722
rootNode = applyTransform(rootNode, "geowebcache_151.xsl").getFirstChild();
717723
}
718724

725+
if (!rootNode.getNamespaceURI().equals("http://geowebcache.org/schema/2.0.0")) {
726+
log.config("Updating configuration to 2.0.0");
727+
rootNode = applyTransform(rootNode, "geowebcache_200.xsl").getFirstChild();
728+
}
729+
719730
// Check again after transform
720731
if (!rootNode.getNodeName().equals("gwcConfiguration")) {
721732
log.log(Level.SEVERE, "Unable to parse file, expected gwcConfiguration at root after transform.");
@@ -726,8 +737,8 @@ private static Node checkAndTransform(Document doc) throws ConfigurationExceptio
726737
validate(rootNode);
727738
log.config("TileLayerConfiguration file validated fine.");
728739
} catch (SAXException e) {
729-
log.warning("GWC configuration validation error: " + e.getMessage());
730-
log.warning(
740+
log.fine("GWC configuration validation error: " + e.getMessage());
741+
log.fine(
731742
"Will try to use configuration anyway. Please check the order of declared elements against the schema.");
732743
} catch (IOException e) {
733744
throw new RuntimeException(e.getMessage(), e);
@@ -739,11 +750,14 @@ private static Node checkAndTransform(Document doc) throws ConfigurationExceptio
739750

740751
static void validate(Node rootNode) throws SAXException, IOException {
741752
// Perform validation
742-
// TODO dont know why this one suddenly failed to look up, revert to
743-
// XMLConstants.W3C_XML_SCHEMA_NS_URI
744-
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
753+
SchemaFactory factory = XMLUtils.newSchemaFactory(XMLConstants.W3C_XML_SCHEMA_NS_URI);
754+
// We do not need access to external schemas
755+
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
756+
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
745757
try (InputStream is = XMLConfiguration.class.getResourceAsStream("geowebcache.xsd")) {
746-
758+
if (is == null) {
759+
throw new IOException("Could not load schema resource 'geowebcache.xsd'");
760+
}
747761
Schema schema = factory.newSchema(new StreamSource(is));
748762
Validator validator = schema.newValidator();
749763

@@ -758,7 +772,7 @@ static String getCurrentSchemaVersion() {
758772

759773
Document dom;
760774
try (InputStream is = XMLConfiguration.class.getResourceAsStream("geowebcache.xsd")) {
761-
dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
775+
dom = XMLUtils.newDocumentBuilder().parse(is);
762776
} catch (Exception e) {
763777
throw new RuntimeException(e);
764778
}
@@ -777,7 +791,7 @@ private static Node applyTransform(Node oldRootNode, String xslFilename) {
777791
try (InputStream is = XMLConfiguration.class.getResourceAsStream(xslFilename)) {
778792

779793
try {
780-
transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(is));
794+
transformer = XMLUtils.newTransformer(new StreamSource(is));
781795
transformer.transform(new DOMSource(oldRootNode), result);
782796
} catch (TransformerFactoryConfigurationError | TransformerException e) {
783797
log.log(Level.FINE, e.getMessage(), e);
@@ -1462,4 +1476,17 @@ public void deinitialize() throws Exception {
14621476
this.layers = null;
14631477
this.gwcConfig = null;
14641478
}
1479+
1480+
/** Print a DOM tree to an output stream or if there is an exception while doing so, print the stack trace. */
1481+
public static void printDom(Node dom, OutputStream os) {
1482+
Transformer trans;
1483+
PrintWriter w = new PrintWriter(os);
1484+
try {
1485+
trans = XMLUtils.newTransformer(); // XMLUtils.newTransformer()
1486+
trans.transform(new DOMSource(dom), new StreamResult(new OutputStreamWriter(os)));
1487+
} catch (TransformerException e) {
1488+
w.println("An error ocurred while transforming the given DOM:");
1489+
e.printStackTrace(w);
1490+
}
1491+
}
14651492
}

geowebcache/core/src/main/resources/org/geowebcache/config/geowebcache.xsd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0"?>
22
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xml="http://www.w3.org/XML/1998/namespace"
3-
targetNamespace="http://geowebcache.org/schema/1.28.0" xmlns:gwc="http://geowebcache.org/schema/1.28.0"
4-
elementFormDefault="qualified" version="1.28.0">
3+
targetNamespace="http://geowebcache.org/schema/2.0.0" xmlns:gwc="http://geowebcache.org/schema/2.0.0"
4+
elementFormDefault="qualified" version="2.0.0">
55

66
<xs:element name="gwcConfiguration">
77
<xs:annotation>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<xsl:stylesheet xmlns:gwc="http://geowebcache.org/schema/1.6.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
3+
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
4+
5+
<xsl:template match="node()|*">
6+
<xsl:copy>
7+
<xsl:apply-templates/>
8+
</xsl:copy>
9+
</xsl:template>
10+
11+
<xsl:template match="/|comment()|processing-instruction()">
12+
<xsl:copy>
13+
<xsl:apply-templates/>
14+
</xsl:copy>
15+
</xsl:template>
16+
17+
<xsl:template match="*">
18+
<xsl:element name="{local-name()}">
19+
<xsl:apply-templates select="@*|node()"/>
20+
</xsl:element>
21+
</xsl:template>
22+
23+
<xsl:template match="@*">
24+
<xsl:attribute name="{local-name()}">
25+
<xsl:value-of select="."/>
26+
</xsl:attribute>
27+
</xsl:template>
28+
29+
<xsl:template match="gwc:keyword">
30+
<string><xsl:apply-templates/></string>
31+
</xsl:template>
32+
33+
<xsl:template match="gwc:gwcConfiguration">
34+
<gwcConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
35+
xmlns="http://geowebcache.org/schema/2.0.0"
36+
xsi:schemaLocation="http://geowebcache.org/schema/2.0.0 http://geowebcache.org/schema/2.0.0/geowebcache.xsd">
37+
<xsl:apply-templates/>
38+
</gwcConfiguration>
39+
</xsl:template>
40+
41+
</xsl:stylesheet>

geowebcache/core/src/test/java/org/geowebcache/config/ServerConfigurationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
public class ServerConfigurationTest {
3838

39-
private static final String VERSION_PATTERN = "1(\\.\\d+)+(\\-\\w+)*";
39+
private static final String VERSION_PATTERN = "2(\\.\\d+)+(\\-\\w+)*";
4040

4141
ServerConfiguration config;
4242

geowebcache/core/src/test/java/org/geowebcache/config/XMLConfigurationBackwardsCompatibilityTest.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import javax.xml.transform.TransformerFactory;
3030
import javax.xml.transform.dom.DOMSource;
3131
import javax.xml.transform.stream.StreamResult;
32+
import org.geotools.xml.XMLUtils;
3233
import org.geowebcache.GeoWebCacheException;
3334
import org.geowebcache.config.meta.ServiceInformation;
3435
import org.geowebcache.filter.request.RequestFilter;
@@ -45,7 +46,9 @@ public class XMLConfigurationBackwardsCompatibilityTest {
4546

4647
public static final String GWC_125_CONFIG_FILE = "geowebcache_125.xml";
4748

48-
public static final String LATEST_FILENAME = "geowebcache_130.xml";
49+
public static final String GWC_130_CONFIG_FILE = "geowebcache_130.xml";
50+
51+
public static final String LATEST_FILENAME = "geowebcache_200.xml";
4952

5053
@Test
5154
public void testLoadPre10() throws Exception {
@@ -227,14 +230,14 @@ private XMLConfiguration loadConfig(String fileName) throws Exception {
227230

228231
/** Utility method to print out a dom. */
229232
protected void print(Document dom) throws Exception {
230-
TransformerFactory txFactory = TransformerFactory.newInstance();
233+
TransformerFactory txFactory = XMLUtils.newTransformerFactory();
231234
try {
232235
txFactory.setAttribute("{http://xml.apache.org/xalan}indent-number", Integer.valueOf(2));
233236
} catch (Exception e) {
234237
// some
235238
}
236239

237-
Transformer tx = txFactory.newTransformer();
240+
Transformer tx = XMLUtils.newTransformer(txFactory);
238241
tx.setOutputProperty(OutputKeys.METHOD, "xml");
239242
tx.setOutputProperty(OutputKeys.INDENT, "yes");
240243

0 commit comments

Comments
 (0)