Skip to content

Commit

Permalink
Issue #10066 - Allow customization of SAXParserFactory and `SAXPars…
Browse files Browse the repository at this point in the history
…er` in `XmlParser` (#10299)

Backports of
* Issue #10066 - Allow customization of `SAXParserFactory` and `SAXParser` in `XmlParser` (#10067)
* Updating various old/moved URL references found across project (`jetty-10.0.x`) (#10098)

Consisting of
* Allow customization of SAXParserFactory / SAXParser in XmlParser
* Introduce method `.getSAXParser()`
* Prepending doctype in testcases
* More comprehensive changes to redirectEntity config
* Updating various old/moved URL references found across project (`jetty-10.0.x`) (#10098)
* Now that the migration of `https://eclipse.org/jetty/` to `https://eclipse.dev/jetty/` has occurred, it is time to review the URI use in our project
* Added more URIs to XmlConfiguration
* Better SAXParseException handling to report resource that is causing the problem
* Add missing DOCTYPE declarations
* Enforcing unique XML ids

---------

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
Co-authored-by: Greg Wilkins <gregw@webtide.com>
  • Loading branch information
joakime and gregw authored Aug 14, 2023
1 parent 490626e commit d4d8832
Show file tree
Hide file tree
Showing 15 changed files with 192 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ public void stop() throws Exception
public void testTmpDirectory() throws Exception
{
Path warPath = MavenTestingUtils.getTestResourcePath("webapps/foo-webapp-1.war");
String deploymentXml = "<Configure class=\"org.eclipse.jetty.webapp.WebAppContext\">\n" +
String deploymentXml =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"https://eclipse.dev/jetty/configure.dtd\">\n" +
"<Configure class=\"org.eclipse.jetty.webapp.WebAppContext\">\n" +
"<Set name=\"war\">" + warPath + "</Set>\n" +
"<Set name=\"tempDirectory\">" + tmpDir + "</Set>\n" +
"<Set name=\"persistTempDirectory\">false</Set>\n" +
Expand Down Expand Up @@ -141,7 +144,10 @@ public void testTmpDirectory() throws Exception
public void testPersistentTmpDirectory() throws Exception
{
Path warPath = MavenTestingUtils.getTestResourcePath("webapps/foo-webapp-1.war");
String deploymentXml = "<Configure class=\"org.eclipse.jetty.webapp.WebAppContext\">\n" +
String deploymentXml =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"https://eclipse.dev/jetty/configure.dtd\">\n" +
"<Configure class=\"org.eclipse.jetty.webapp.WebAppContext\">\n" +
"<Set name=\"war\">" + warPath + "</Set>\n" +
"<Set name=\"tempDirectory\">" + tmpDir + "</Set>\n" +
"<Set name=\"persistTempDirectory\">true</Set>\n" +
Expand Down
2 changes: 2 additions & 0 deletions jetty-deploy/src/test/resources/context-binding-test-1.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://eclipse.dev/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">

<Call name="addServerClass">
Expand Down
3 changes: 2 additions & 1 deletion jetty-deploy/src/test/resources/jetty.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://eclipse.org/jetty/configure_9_3.dtd">

<!-- =============================================================== -->
<!-- Documentation of this file format can be found at: -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,10 @@ The deployer discovers and hot deploys context IoC descriptors like the followin

[source, xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC
"-//Mort Bay Consulting//DTD Configure//EN"
"http://www.eclipse.org/jetty/configure_9_3.dtd">
"-//Jetty//Configure//EN"
"https://eclipse.org/jetty/configure_9_3.dtd">
<!--
Configure a custom context for serving javadoc as static resources
Expand Down Expand Up @@ -202,10 +202,10 @@ To set the contextPath from within the WAR file, you can include a `WEB-INF/jett

[source, xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC
"-//Mort Bay Consulting//DTD Configure//EN"
"http://www.eclipse.org/jetty/configure_9_3.dtd">
"-//Jetty//Configure//EN"
"https://eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/contextpath</Set>
Expand All @@ -217,10 +217,10 @@ Instead of allowing the WAR file to be discovered by the deployer, an IoC XML fi

[source, xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC
"-//Mort Bay Consulting//DTD Configure//EN"
"http://www.eclipse.org/jetty/configure_9_3.dtd">
"-//Jetty//Configure//EN"
"https://eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/test.war</Set>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://eclipse.dev/jetty/configure_9_3.dtd">

<Configure id="Server" class="org.eclipse.jetty.server.Server">
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://eclipse.dev/jetty/configure_9_3.dtd">

<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Call name="setInitParameter">
<Arg>org.eclipse.jetty.servlet.Default.useFileMappedBuffer</Arg>
Expand Down
1 change: 1 addition & 0 deletions jetty-start/src/test/resources/bogus.xml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://eclipse.dev/jetty/configure_9_3.dtd">
<Configure />
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.eclipse.jetty.xml;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
Expand Down Expand Up @@ -67,6 +68,7 @@
import org.eclipse.jetty.util.resource.Resource;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
* <p>Configures objects from XML.</p>
Expand Down Expand Up @@ -203,7 +205,7 @@ public static String normalizeURI(String uri)
private final String _dtd;
private ConfigurationProcessor _processor;

ConfigurationParser getParser()
public XmlParser getXmlParser()
{
Pool<ConfigurationParser>.Entry entry = __parsers.acquire(ConfigurationParser::new);
if (entry == null)
Expand All @@ -220,12 +222,22 @@ ConfigurationParser getParser()
*/
public XmlConfiguration(Resource resource) throws SAXException, IOException
{
try (ConfigurationParser parser = getParser(); InputStream inputStream = resource.getInputStream())
XmlParser parser = getXmlParser();
try (InputStream inputStream = resource.getInputStream())
{
_location = resource;
setConfig(parser.parse(inputStream));
_dtd = parser.getDTD();
}
catch (SAXParseException e)
{
throw new SAXParseException("Unable to parse: " + resource, null, e);
}
finally
{
if (parser instanceof Closeable)
((Closeable)parser).close();
}
}

/**
Expand Down Expand Up @@ -257,13 +269,19 @@ public XmlConfiguration(String configuration) throws SAXException, IOException
configuration = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://www.eclipse.org/jetty/configure_9_3.dtd\">" +
configuration;
try (ConfigurationParser parser = getParser(); StringReader reader = new StringReader(configuration))
XmlParser parser = getXmlParser();
try (StringReader reader = new StringReader(configuration))
{
InputSource source = new InputSource(reader);
_location = null;
setConfig(parser.parse(source));
_dtd = parser.getDTD();
}
finally
{
if (parser instanceof Closeable)
((Closeable)parser).close();
}
}

/**
Expand All @@ -278,12 +296,18 @@ public XmlConfiguration(String configuration) throws SAXException, IOException
public XmlConfiguration(InputStream configuration) throws SAXException, IOException
{
InputSource source = new InputSource(configuration);
try (ConfigurationParser parser = getParser())
XmlParser parser = getXmlParser();
try
{
_location = null;
setConfig(parser.parse(source));
_dtd = parser.getDTD();
}
finally
{
if (parser instanceof Closeable)
((Closeable)parser).close();
}
}

@Override
Expand Down Expand Up @@ -1918,7 +1942,7 @@ else if (arg.toLowerCase(Locale.ENGLISH).endsWith(".properties"))
}
}

private static class ConfigurationParser extends XmlParser implements AutoCloseable
private static class ConfigurationParser extends XmlParser implements Closeable
{
private final Pool<ConfigurationParser>.Entry _entry;

Expand All @@ -1942,8 +1966,23 @@ private ConfigurationParser(Pool<ConfigurationParser>.Entry entry)
redirectEntity("http://jetty.mortbay.org/configure.dtd", config93);
redirectEntity("http://jetty.eclipse.org/configure.dtd", config93);
redirectEntity("https://jetty.eclipse.org/configure.dtd", config93);
redirectEntity("http://www.eclipse.org/jetty/configure.dtd", config93);
redirectEntity("https://www.eclipse.org/jetty/configure.dtd", config93);
redirectEntity("http://jetty.mortbay.org/configure.dtd", config93);

// Register all variations of DOCTYPE entity references for Config 9.3
String[] schemes = {"http", "https"};
String[] hosts = {"www.eclipse.org", "eclipse.org", "www.eclipse.dev", "eclipse.dev"};
String[] paths = {"/jetty/configure.dtd", "/jetty/configure_9_3.dtd"};

for (String scheme : schemes)
{
for (String host : hosts)
{
for (String path : paths)
{
redirectEntity(String.format("%s://%s%s", scheme, host, path), config93);
}
}
}
redirectEntity("-//Mort Bay Consulting//DTD Configure//EN", config93);
redirectEntity("-//Jetty//Configure//EN", config93);
}
Expand Down
35 changes: 20 additions & 15 deletions jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ public class XmlParser
*/
public XmlParser()
{
SAXParserFactory factory = SAXParserFactory.newInstance();
boolean validatingDft = factory.getClass().toString().startsWith("org.apache.xerces.");
String validatingProp = System.getProperty("org.eclipse.jetty.xml.XmlParser.Validating", validatingDft ? "true" : "false");
SAXParserFactory factory = newSAXParserFactory();
boolean validatingDefault = factory.getClass().toString().contains("org.apache.xerces.");
String validatingProp = System.getProperty("org.eclipse.jetty.xml.XmlParser.Validating", validatingDefault ? "true" : "false");
boolean validating = Boolean.valueOf(validatingProp).booleanValue();
setValidating(validating);
}
Expand All @@ -81,11 +81,16 @@ public XmlParser(boolean validating)
setValidating(validating);
}

protected SAXParserFactory newSAXParserFactory()
{
return SAXParserFactory.newInstance();
}

public void setValidating(boolean validating)
{
try
{
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParserFactory factory = newSAXParserFactory();
factory.setValidating(validating);
_parser = factory.newSAXParser();

Expand Down Expand Up @@ -127,6 +132,11 @@ public boolean isValidating()
return _parser.isValidating();
}

public SAXParser getSAXParser()
{
return _parser;
}

public synchronized void redirectEntity(String name, URL entity)
{
if (entity != null)
Expand Down Expand Up @@ -261,18 +271,10 @@ protected InputSource resolveEntity(String pid, String sid)
if (pid != null)
entity = _redirectMap.get(pid);
if (entity == null)
entity = _redirectMap.get(sid);
if (entity == null)
{
String dtd = sid;
if (dtd.lastIndexOf('/') >= 0)
dtd = dtd.substring(dtd.lastIndexOf('/') + 1);

if (LOG.isDebugEnabled())
LOG.debug("Can't exact match entity in redirect map, trying " + dtd);
entity = _redirectMap.get(dtd);
}
entity = (URL)_redirectMap.get(sid);

// Only serve entity if found.
// We don't want to serve from unknown hosts or random paths.
if (entity != null)
{
try
Expand All @@ -289,6 +291,9 @@ protected InputSource resolveEntity(String pid, String sid)
LOG.ignore(e);
}
}

if (LOG.isDebugEnabled())
LOG.debug("Entity not found for PID:{} / SID:{}", pid, sid);
return null;
}

Expand Down
Loading

0 comments on commit d4d8832

Please sign in to comment.