();
+ this(false);
}
- public CommandLineBuilder(String bin)
+ public CommandLineBuilder(boolean multiline)
{
- this();
- args.add(bin);
+ separator = multiline ? (" \\" + System.lineSeparator() + " ") : " ";
}
/**
- * Add a simple argument to the command line.
- *
- * Will quote arguments that have a space in them.
+ * This method applies single quotes suitable for a POSIX compliant shell if
+ * necessary.
+ *
+ * @param input The string to quote if needed
+ * @return The quoted string or the original string if quotes are not necessary
+ */
+ public static String shellQuoteIfNeeded(String input)
+ {
+ // Single quotes are used because double quotes
+ // are evaluated differently by some shells.
+
+ if (input == null)
+ return null;
+ if (input.length() == 0)
+ return "''";
+
+ int i = 0;
+ boolean needsQuoting = false;
+ while (!needsQuoting && i < input.length())
+ {
+ char c = input.charAt(i++);
+
+ // needs quoting unless a limited set of known good characters
+ needsQuoting = !(
+ (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') ||
+ c == '/' ||
+ c == ':' ||
+ c == '.' ||
+ c == ',' ||
+ c == '+' ||
+ c == '-' ||
+ c == '_'
+ );
+ }
+
+ if (!needsQuoting)
+ return input;
+
+ StringBuilder builder = new StringBuilder(input.length() * 2);
+ builder.append("'");
+ builder.append(input, 0, --i);
+
+ while (i < input.length())
+ {
+ char c = input.charAt(i++);
+ if (c == '\'')
+ {
+ // There is no escape for a literal single quote, so we must leave the quotes
+ // and then escape the single quote. We test for the start/end of the string, so
+ // we can be less ugly in those cases.
+ if (i == 1)
+ builder.insert(0, "\\").append("'");
+ else if (i == input.length())
+ builder.append("'\\");
+ else
+ builder.append("'\\''");
+ }
+ else
+ builder.append(c);
+ }
+ builder.append("'");
+
+ return builder.toString();
+ }
+
+ /**
+ * Add a simple argument to the command line, quoted if necessary.
*
* @param arg the simple argument to add
*/
@@ -76,49 +130,75 @@ public class CommandLineBuilder
{
if (arg != null)
{
+ if (commandLine.length() > 0)
+ commandLine.append(separator);
args.add(arg);
+ commandLine.append(shellQuoteIfNeeded(arg));
}
}
/**
- * Similar to {@link #addArg(String)} but concats both name + value with an "=" sign, quoting were needed, and excluding the "=" portion if the value is
- * undefined or empty.
- *
- *
- * addEqualsArg("-Dname", "value") = "-Dname=value"
- * addEqualsArg("-Djetty.home", "/opt/company inc/jetty (7)/") = "-Djetty.home=/opt/company\ inc/jetty\ (7)/"
- * addEqualsArg("-Djenkins.workspace", "/opt/workspaces/jetty jdk7/") = "-Djenkins.workspace=/opt/workspaces/jetty\ jdk7/"
- * addEqualsArg("-Dstress", null) = "-Dstress"
- * addEqualsArg("-Dstress", "") = "-Dstress"
- *
- *
+ * Add a "name=value" style argument to the command line with
+ * name and value quoted if necessary.
* @param name the name
* @param value the value
*/
- public void addEqualsArg(String name, String value)
+ public void addArg(String name, String value)
{
+ Objects.requireNonNull(name);
+
+ if (commandLine.length() > 0)
+ commandLine.append(separator);
+
if ((value != null) && (value.length() > 0))
{
args.add(name + "=" + value);
+ commandLine.append(shellQuoteIfNeeded(name)).append('=').append(shellQuoteIfNeeded(value));
}
else
{
args.add(name);
+ commandLine.append(shellQuoteIfNeeded(name));
}
}
/**
- * Add a simple argument to the command line.
- *
- * Will NOT quote/escape arguments that have a space in them.
- *
- * @param arg the simple argument to add
+ * Adds a "-OPTION" style option to the command line with no quoting, for example `--help`.
+ * @param option the option
*/
- public void addRawArg(String arg)
+ public void addOption(String option)
{
- if (arg != null)
+ addOption(option, null, null);
+ }
+
+ /**
+ * Adds a "-OPTIONname=value" style option to the command line with
+ * name and value quoted if necessary, for example "-Dprop=value".
+ * @param option the option
+ * @param name the name
+ * @param value the value
+ */
+ public void addOption(String option, String name, String value)
+ {
+ Objects.requireNonNull(option);
+
+ if (commandLine.length() > 0)
+ commandLine.append(separator);
+
+ if (name == null || name.length() == 0)
{
- args.add(arg);
+ commandLine.append(option);
+ args.add(option);
+ }
+ else if ((value != null) && (value.length() > 0))
+ {
+ args.add(option + name + "=" + value);
+ commandLine.append(option).append(shellQuoteIfNeeded(name)).append('=').append(shellQuoteIfNeeded(value));
+ }
+ else
+ {
+ args.add(option + name);
+ commandLine.append(option).append(shellQuoteIfNeeded(name));
}
}
@@ -129,20 +209,12 @@ public class CommandLineBuilder
@Override
public String toString()
- {
- return toString(" ");
- }
-
- public String toString(String delim)
{
StringBuilder buf = new StringBuilder();
-
for (String arg : args)
{
if (buf.length() > 0)
- {
- buf.append(delim);
- }
+ buf.append(' ');
buf.append(arg); // we assume escaping has occurred during addArg
}
@@ -154,23 +226,9 @@ public class CommandLineBuilder
*
* @return the toString but each arg that has spaces is surrounded by {@code '} (single-quote tick)
*/
- public String toQuotedString()
+ public String toCommandLine()
{
- StringBuilder buf = new StringBuilder();
-
- for (String arg : args)
- {
- if (buf.length() > 0)
- buf.append(' ');
- boolean needsQuotes = (arg.contains(" "));
- if (needsQuotes)
- buf.append("'");
- buf.append(arg);
- if (needsQuotes)
- buf.append("'");
- }
-
- return buf.toString();
+ return commandLine.toString();
}
public void debug()
diff --git a/jetty-core/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-core/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
index afe0e875af9..4ccc2325ac3 100644
--- a/jetty-core/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
+++ b/jetty-core/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
@@ -436,7 +436,7 @@ public class Main
{
CommandLineBuilder cmd = args.getMainArgs(args.getDryRunParts());
cmd.debug();
- System.out.println(cmd.toQuotedString());
+ System.out.println(cmd.toCommandLine());
}
if (args.isStopCommand())
diff --git a/jetty-core/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java b/jetty-core/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
index 4b6585bfec4..6dcadddb57a 100644
--- a/jetty-core/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
+++ b/jetty-core/jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java
@@ -13,6 +13,7 @@
package org.eclipse.jetty.start;
+import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
@@ -182,6 +183,7 @@ public class StartArgs
private boolean listConfig = false;
private boolean version = false;
private boolean dryRun = false;
+ private boolean multiLine = false;
private final Set dryRunParts = new HashSet<>();
private boolean jpms = false;
private boolean createStartD = false;
@@ -493,17 +495,6 @@ public class StartArgs
return files;
}
- /**
- * Gets the List of JVM arguments detected.
- *
- * @deprecated use {@link #getJvmArgSources()} instead, as it will return source references with each arg.
- */
- @Deprecated
- public List getJvmArgs()
- {
- return new ArrayList<>(jvmArgSources.keySet());
- }
-
/**
* Return ordered Map of JVM arguments to Source (locations)
*
@@ -519,7 +510,7 @@ public class StartArgs
if (parts.isEmpty())
parts = ALL_PARTS;
- CommandLineBuilder cmd = new CommandLineBuilder();
+ CommandLineBuilder cmd = new CommandLineBuilder(multiLine);
// Special Stop/Shutdown properties
ensureSystemPropertySet("STOP.PORT");
@@ -527,13 +518,13 @@ public class StartArgs
ensureSystemPropertySet("STOP.WAIT");
if (parts.contains("java"))
- cmd.addRawArg(CommandLineBuilder.findJavaBin());
+ cmd.addArg(CommandLineBuilder.findJavaBin());
if (parts.contains("opts"))
{
- cmd.addRawArg("-Djava.io.tmpdir=" + System.getProperty("java.io.tmpdir"));
- cmd.addRawArg("-Djetty.home=" + baseHome.getHome());
- cmd.addRawArg("-Djetty.base=" + baseHome.getBase());
+ cmd.addOption("-D", "java.io.tmpdir", System.getProperty("java.io.tmpdir"));
+ cmd.addOption("-D", "jetty.home", baseHome.getHome());
+ cmd.addOption("-D", "jetty.base", baseHome.getBase());
Props properties = jettyEnvironment.getProperties();
for (String x : getJvmArgSources().keySet())
@@ -545,11 +536,11 @@ public class StartArgs
String value = assign.length == 1 ? "" : assign[1];
Prop p = processSystemProperty(key, value, null);
- cmd.addRawArg("-D" + p.key + "=" + properties.expand(p.value));
+ cmd.addOption("-D", p.key, properties.expand(p.value));
}
else
{
- cmd.addRawArg(properties.expand(x));
+ cmd.addArg(properties.expand(x));
}
}
@@ -557,7 +548,7 @@ public class StartArgs
for (String propKey : systemPropertySource.keySet())
{
String value = System.getProperty(propKey);
- cmd.addEqualsArg("-D" + propKey, value);
+ cmd.addOption("-D", propKey, value);
}
}
@@ -594,38 +585,38 @@ public class StartArgs
if (!files.isEmpty())
{
- cmd.addRawArg("--module-path");
+ cmd.addOption("--module-path");
String modules = files.stream()
.map(Path::toAbsolutePath)
.map(Path::toString)
.collect(Collectors.joining(FS.pathSeparator()));
- cmd.addRawArg(modules);
+ cmd.addArg(modules);
}
List dirs = dirsAndFiles.get(true);
if (dirs != null && !dirs.isEmpty())
{
- cmd.addRawArg("--class-path");
+ cmd.addOption("--class-path");
String directories = dirs.stream()
.map(Path::toAbsolutePath)
.map(Path::toString)
.collect(Collectors.joining(FS.pathSeparator()));
- cmd.addRawArg(directories);
+ cmd.addArg(directories);
}
generateJpmsArgs(cmd);
}
else
{
- cmd.addRawArg("--class-path");
- cmd.addRawArg(jettyEnvironment.getClasspath().toString());
+ cmd.addOption("--class-path");
+ cmd.addArg(jettyEnvironment.getClasspath().toString());
}
}
if (parts.contains("main"))
{
if (isJPMS())
- cmd.addRawArg("--module");
- cmd.addRawArg(getMainClassname());
+ cmd.addOption("--module");
+ cmd.addArg(getMainClassname());
}
// do properties and xmls
@@ -637,7 +628,8 @@ public class StartArgs
// pass properties as args
for (Prop p : properties)
{
- cmd.addRawArg(CommandLineBuilder.quote(p.key) + "=" + CommandLineBuilder.quote(properties.expand(p.value)));
+ if (!p.key.startsWith("java.version."))
+ cmd.addArg(p.key, properties.expand(p.value));
}
}
else if (properties.size() > 0)
@@ -658,17 +650,17 @@ public class StartArgs
{
properties.store(out, "start.jar properties");
}
- cmd.addRawArg(propPath.toAbsolutePath().toString());
+ cmd.addArg(propPath.toAbsolutePath().toString());
}
for (Path xml : jettyEnvironment.getXmlFiles())
{
- cmd.addRawArg(xml.toAbsolutePath().toString());
+ cmd.addArg(xml.toAbsolutePath().toString());
}
for (Path propertyFile : jettyEnvironment.getPropertyFiles())
{
- cmd.addRawArg(propertyFile.toAbsolutePath().toString());
+ cmd.addArg(propertyFile.toAbsolutePath().toString());
}
}
@@ -773,28 +765,28 @@ public class StartArgs
{
if (!_jmodAdds.isEmpty())
{
- cmd.addRawArg("--add-modules");
- cmd.addRawArg(String.join(",", _jmodAdds));
+ cmd.addOption("--add-modules");
+ cmd.addArg(String.join(",", _jmodAdds));
}
for (Map.Entry> entry : _jmodPatch.entrySet())
{
- cmd.addRawArg("--patch-module");
- cmd.addRawArg(entry.getKey() + "=" + String.join(FS.pathSeparator(), entry.getValue()));
+ cmd.addOption("--patch-module");
+ cmd.addArg(entry.getKey(), String.join(File.pathSeparator, entry.getValue()));
}
for (Map.Entry> entry : _jmodOpens.entrySet())
{
- cmd.addRawArg("--add-opens");
- cmd.addRawArg(entry.getKey() + "=" + String.join(",", entry.getValue()));
+ cmd.addOption("--add-opens");
+ cmd.addArg(entry.getKey(), String.join(",", entry.getValue()));
}
for (Map.Entry> entry : _jmodExports.entrySet())
{
- cmd.addRawArg("--add-exports");
- cmd.addRawArg(entry.getKey() + "=" + String.join(",", entry.getValue()));
+ cmd.addOption("--add-exports");
+ cmd.addArg(entry.getKey(), String.join(",", entry.getValue()));
}
for (Map.Entry> entry : _jmodReads.entrySet())
{
- cmd.addRawArg("--add-reads");
- cmd.addRawArg(entry.getKey() + "=" + String.join(",", entry.getValue()));
+ cmd.addOption("--add-reads");
+ cmd.addArg(entry.getKey(), String.join(",", entry.getValue()));
}
}
@@ -1154,6 +1146,12 @@ public class StartArgs
int colon = arg.indexOf('=');
for (String part : arg.substring(colon + 1).split(","))
{
+ if ("multiline".equalsIgnoreCase(part))
+ {
+ multiLine = true;
+ continue;
+ }
+
if (!ALL_PARTS.contains(part))
throw new UsageException(UsageException.ERR_BAD_ARG, "Unrecognized --dry-run=\"%s\" in %s", part, source);
diff --git a/jetty-core/jetty-start/src/main/resources/org/eclipse/jetty/start/usage.txt b/jetty-core/jetty-start/src/main/resources/org/eclipse/jetty/start/usage.txt
index 64f8461abbf..e316011a83d 100644
--- a/jetty-core/jetty-start/src/main/resources/org/eclipse/jetty/start/usage.txt
+++ b/jetty-core/jetty-start/src/main/resources/org/eclipse/jetty/start/usage.txt
@@ -60,12 +60,13 @@ Report Commands:
--dry-run
Prints the command line that start.jar generates,
- then exits.
+ in a format usable by a POSIX compliant shell, then exits.
This may be used to generate command lines into scripts:
$ java -jar start.jar --dry-run > jetty.sh
--dry-run=(,)*
- Prints specific parts of the command line. The parts are:
+ Prints specific parts of the command line in a format usable by
+ a POSIX compliant shell. The parts are:
o "java" - the JVM to run
o "opts" - the JVM options (e.g. -D, -X and -XX flags)
o "path" - the JVM class-path and/or the JPMS module-path
diff --git a/jetty-core/jetty-start/src/test/java/org/eclipse/jetty/start/CommandLineBuilderTest.java b/jetty-core/jetty-start/src/test/java/org/eclipse/jetty/start/CommandLineBuilderTest.java
index 06753229e7e..6f938f7ae00 100644
--- a/jetty-core/jetty-start/src/test/java/org/eclipse/jetty/start/CommandLineBuilderTest.java
+++ b/jetty-core/jetty-start/src/test/java/org/eclipse/jetty/start/CommandLineBuilderTest.java
@@ -13,7 +13,12 @@
package org.eclipse.jetty.start;
+import java.util.stream.Stream;
+
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -23,43 +28,90 @@ public class CommandLineBuilderTest
@Test
public void testSimpleCommandline()
{
- CommandLineBuilder cmd = new CommandLineBuilder("java");
- cmd.addEqualsArg("-Djava.io.tmpdir", "/home/java/temp dir/");
+ CommandLineBuilder cmd = new CommandLineBuilder();
+ cmd.addArg("java");
+ cmd.addArg("-Djava.io.tmpdir", "/home/java/temp dir/");
cmd.addArg("--version");
- assertThat(cmd.toQuotedString(), is("java '-Djava.io.tmpdir=/home/java/temp dir/' --version"));
+ assertThat(cmd.toCommandLine(), is("java -Djava.io.tmpdir='/home/java/temp dir/' --version"));
}
@Test
public void testSimpleHomeNoSpace()
{
- CommandLineBuilder cmd = new CommandLineBuilder("java");
- cmd.addEqualsArg("-Djetty.home", "/opt/jetty");
- assertThat(cmd.toQuotedString(), is("java -Djetty.home=/opt/jetty"));
+ CommandLineBuilder cmd = new CommandLineBuilder();
+ cmd.addArg("java");
+ cmd.addArg("-Djetty.home", "/opt/jetty");
+ assertThat(cmd.toCommandLine(), is("java -Djetty.home=/opt/jetty"));
}
@Test
public void testSimpleHomeWithSpace()
{
- CommandLineBuilder cmd = new CommandLineBuilder("java");
- cmd.addEqualsArg("-Djetty.home", "/opt/jetty 10/home");
- assertThat(cmd.toQuotedString(), is("java '-Djetty.home=/opt/jetty 10/home'"));
+ CommandLineBuilder cmd = new CommandLineBuilder();
+ cmd.addArg("java");
+ cmd.addArg("-Djetty.home", "/opt/jetty 10/home");
+ assertThat(cmd.toCommandLine(), is("java -Djetty.home='/opt/jetty 10/home'"));
}
@Test
public void testEscapedFormattingString()
{
- CommandLineBuilder cmd = new CommandLineBuilder("java");
- cmd.addEqualsArg("-Djetty.home", "/opt/jetty");
- cmd.addEqualsArg("jetty.requestlog.formatter", "%{client}a - %u %{dd/MMM/yyyy:HH:mm:ss ZZZ|GMT}t \"%r\" %s %O \"%{Referer}i\" \"%{User-Agent}i\"");
- assertThat(cmd.toQuotedString(), is("java -Djetty.home=/opt/jetty 'jetty.requestlog.formatter=%{client}a - %u %{dd/MMM/yyyy:HH:mm:ss ZZZ|GMT}t \"%r\" %s %O \"%{Referer}i\" \"%{User-Agent}i\"'"));
+ CommandLineBuilder cmd = new CommandLineBuilder();
+ cmd.addArg("java");
+ cmd.addArg("-Djetty.home", "/opt/jetty");
+ cmd.addArg("jetty.requestlog.formatter", "%{client}a - %u %{dd/MMM/yyyy:HH:mm:ss ZZZ|GMT}t \"%r\" %s %O \"%{Referer}i\" \"%{User-Agent}i\"");
+ assertThat(cmd.toCommandLine(), is("java -Djetty.home=/opt/jetty jetty.requestlog.formatter='%{client}a - %u %{dd/MMM/yyyy:HH:mm:ss ZZZ|GMT}t \"%r\" %s %O \"%{Referer}i\" \"%{User-Agent}i\"'"));
}
@Test
public void testEscapeUnicode()
{
- CommandLineBuilder cmd = new CommandLineBuilder("java");
- cmd.addEqualsArg("-Djetty.home", "/opt/jetty");
- cmd.addEqualsArg("monetary.symbol", "€");
- assertThat(cmd.toQuotedString(), is("java -Djetty.home=/opt/jetty monetary.symbol=€"));
+ CommandLineBuilder cmd = new CommandLineBuilder();
+ cmd.addArg("java");
+ cmd.addArg("-Djetty.home", "/opt/jetty");
+ cmd.addArg("monetary.symbol", "€");
+ assertThat(cmd.toCommandLine(), is("java -Djetty.home=/opt/jetty monetary.symbol='€'"));
+ }
+
+ public static Stream shellQuoting()
+ {
+ return Stream.of(
+ Arguments.of(null, null),
+ Arguments.of("", "''"),
+ Arguments.of("Hello", "Hello"),
+ Arguments.of("Hell0", "Hell0"),
+ Arguments.of("Hello$World", "'Hello$World'"),
+ Arguments.of("Hello\\World", "'Hello\\World'"),
+ Arguments.of("Hello`World", "'Hello`World'"),
+ Arguments.of("'Hello World'", "\\''Hello World'\\'"),
+ Arguments.of("\"Hello World\"", "'\"Hello World\"'"),
+ Arguments.of("H-llo_world", "H-llo_world"),
+ Arguments.of("H:llo/world", "H:llo/world"),
+ Arguments.of("Hello World", "'Hello World'"),
+ Arguments.of("foo\\bar", "'foo\\bar'"),
+ Arguments.of("foo'bar", "'foo'\\''bar'"),
+ Arguments.of("some 'internal' quoting", "'some '\\''internal'\\'' quoting'"),
+ Arguments.of("monetary.symbol=€", "'monetary.symbol=€'")
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("shellQuoting")
+ public void testShellQuoting(String string, String expected)
+ {
+ assertThat(CommandLineBuilder.shellQuoteIfNeeded(string), is(expected));
+ }
+
+ @Test
+ public void testMultiLine()
+ {
+ CommandLineBuilder cmd = new CommandLineBuilder(true);
+ cmd.addArg("java");
+ cmd.addArg("-Djetty.home", "/opt/jetty");
+ cmd.addArg("monetary.symbol", "€");
+ assertThat(cmd.toCommandLine(),
+ is("java \\" + System.lineSeparator() +
+ " -Djetty.home=/opt/jetty \\" + System.lineSeparator() +
+ " monetary.symbol='€'"));
}
}
diff --git a/jetty-core/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java b/jetty-core/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java
index 036668f152f..98051e391eb 100644
--- a/jetty-core/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java
+++ b/jetty-core/jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java
@@ -177,7 +177,7 @@ public class MainTest
assertThat("jetty.base", baseHome.getBase(), is(homePath.toString()));
CommandLineBuilder commandLineBuilder = args.getMainArgs(StartArgs.ALL_PARTS);
- String commandLine = commandLineBuilder.toString("\n");
+ String commandLine = commandLineBuilder.toString();
String expectedExpansion = String.format("-Xloggc:%s/logs/gc-%s.log",
baseHome.getBase(), System.getProperty("java.version")
);
diff --git a/jetty-core/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlParser.java b/jetty-core/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlParser.java
index bf374c9d50f..6165ac4b708 100644
--- a/jetty-core/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlParser.java
+++ b/jetty-core/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlParser.java
@@ -104,11 +104,16 @@ public class XmlParser
return _lock.lock();
}
+ 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();
@@ -150,6 +155,11 @@ public class XmlParser
return _parser.isValidating();
}
+ public SAXParser getSAXParser()
+ {
+ return _parser;
+ }
+
/**
* Load the specified URI as a catalog for entity mapping purposes.
*
diff --git a/jetty-core/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlParserTest.java b/jetty-core/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlParserTest.java
index d0863a19392..3a84117d0d9 100644
--- a/jetty-core/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlParserTest.java
+++ b/jetty-core/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlParserTest.java
@@ -15,12 +15,18 @@ package org.eclipse.jetty.xml;
import java.net.URL;
import java.nio.file.Path;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.jupiter.api.Test;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
public class XmlParserTest
{
@@ -73,4 +79,32 @@ public class XmlParserTest
assertTrue(testDocStr.startsWith(""));
}
+
+ /**
+ * Customize SAXParserFactory behavior.
+ */
+ @Test
+ public void testNewSAXParserFactory() throws SAXException
+ {
+ XmlParser xmlParser = new XmlParser()
+ {
+ @Override
+ protected SAXParserFactory newSAXParserFactory()
+ {
+ SAXParserFactory saxParserFactory = super.newSAXParserFactory();
+ // Configure at factory level
+ saxParserFactory.setXIncludeAware(false);
+ return saxParserFactory;
+ }
+ };
+
+ SAXParser saxParser = xmlParser.getSAXParser();
+ assertNotNull(saxParser);
+
+ XMLReader xmlReader = saxParser.getXMLReader();
+ // Only run testcase if Xerces is being used.
+ assumeTrue(xmlReader.getClass().getName().contains("org.apache.xerces."));
+ // look to see it was set at XMLReader level
+ assertFalse(xmlReader.getFeature("http://apache.org/xml/features/xinclude"));
+ }
}
diff --git a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-http2-webapp/pom.xml b/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-http2-webapp/pom.xml
index 1fec9811ca6..c30c30552dd 100644
--- a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-http2-webapp/pom.xml
+++ b/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-http2-webapp/pom.xml
@@ -97,11 +97,6 @@
jetty-http2-server
test
-
- org.eclipse.jetty
- jetty-slf4j-impl
- test
-
org.eclipse.jetty.toolchain
jetty-test-helper
diff --git a/pom.xml b/pom.xml
index b6c986f1415..58fd854ea7c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,9 +36,9 @@
1.11.1
4.5.14
4.4.16
- 2.2.8
+ 2.2.9
2.5.10
- 2.2.1
+ 2.2.2
9.5
4.2.0
6.4.1
@@ -46,7 +46,7 @@
10.6.0
1.16.0
1.23.0
- 2.12.0
+ 2.13.0
3.12.0
2.5.2
3.4.2
@@ -140,12 +140,11 @@
4.0.2
2.0.7
1.3.6
- 2.1.1.RELEASE
1.2.5
1.2.5
1.18.3
1.6.0.Final
- 2.2.0.Final
+ 2.2.1.Final
2.4.7
@@ -162,7 +161,7 @@
3.1.0
3.6.0
5.1.9
- 3.2.0
+ 3.3.1
3.3.0
3.11.0
3.6.0
@@ -171,19 +170,19 @@
3.1.0
3.1.0
3.1.1
- 3.5.1
+ 3.6.0
4.0.6
3.3.0
3.5.0
3.9.0
3.9.0
- 3.0.0
+ 3.0.1
3.1.0
3.3.1
- 3.4.1
- 3.1.0
+ 3.5.0
+ 3.1.2
3.3.0
- 3.3.2
+ 3.4.0
4.7.2.0
2.14.2