Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x
This commit is contained in:
commit
28d6009ac5
|
@ -3,7 +3,7 @@
|
|||
|
||||
<!-- =============================================================== -->
|
||||
<!-- Documentation of this file format can be found at: -->
|
||||
<!-- https://www.eclipse.org/jetty/documentation/current/ -->
|
||||
<!-- https://www.eclipse.org/jetty/documentation/current/ -->
|
||||
<!-- -->
|
||||
<!-- Additional configuration files are available in $JETTY_HOME/etc -->
|
||||
<!-- and can be mixed in. See start.ini file for the default -->
|
||||
|
|
|
@ -345,6 +345,8 @@ public class XmlConfiguration
|
|||
*/
|
||||
public Object configure() throws Exception
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Configure {}", _location);
|
||||
return _processor.configure();
|
||||
}
|
||||
|
||||
|
@ -385,7 +387,12 @@ public class XmlConfiguration
|
|||
String id = _root.getAttribute("id");
|
||||
if (id != null)
|
||||
_configuration.getIdMap().put(id, obj);
|
||||
configure(obj, _root, 0);
|
||||
|
||||
AttrOrElementNode aoeNode = new AttrOrElementNode(obj, _root, "Arg");
|
||||
// The Object already existed, if it has <Arg> nodes, warn about them not being used.
|
||||
aoeNode.getNodes("Arg")
|
||||
.forEach((node) -> LOG.warn("Ignored arg {} in {}", node, this._configuration._location));
|
||||
configure(obj, _root, aoeNode.getNext());
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -397,23 +404,32 @@ public class XmlConfiguration
|
|||
String id = _root.getAttribute("id");
|
||||
Object obj = id == null ? null : _configuration.getIdMap().get(id);
|
||||
|
||||
int index = 0;
|
||||
AttrOrElementNode aoeNode;
|
||||
|
||||
if (obj == null && oClass != null)
|
||||
{
|
||||
aoeNode = new AttrOrElementNode(_root, "Arg");
|
||||
try
|
||||
{
|
||||
obj = construct(oClass, new Args(null, oClass, XmlConfiguration.getNodes(_root, "Arg")));
|
||||
obj = construct(oClass, new Args(null, oClass, aoeNode.getNodes("Arg")));
|
||||
}
|
||||
catch (NoSuchMethodException x)
|
||||
{
|
||||
throw new IllegalStateException(String.format("No matching constructor %s in %s", oClass, _configuration));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aoeNode = new AttrOrElementNode(obj, _root, "Arg");
|
||||
// The Object already existed, if it has <Arg> nodes, warn about them not being used.
|
||||
aoeNode.getNodes("Arg")
|
||||
.forEach((node) -> LOG.warn("Ignored arg {} in {}", node, this._configuration._location));
|
||||
}
|
||||
if (id != null)
|
||||
_configuration.getIdMap().put(id, obj);
|
||||
|
||||
_configuration.initializeDefaults(obj);
|
||||
configure(obj, _root, index);
|
||||
configure(obj, _root, aoeNode.getNext());
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -436,21 +452,6 @@ public class XmlConfiguration
|
|||
*/
|
||||
public void configure(Object obj, XmlParser.Node cfg, int i) throws Exception
|
||||
{
|
||||
// Object already constructed so skip any arguments
|
||||
for (; i < cfg.size(); i++)
|
||||
{
|
||||
Object o = cfg.get(i);
|
||||
if (o instanceof String)
|
||||
continue;
|
||||
XmlParser.Node node = (XmlParser.Node)o;
|
||||
if ("Arg".equals(node.getTag()))
|
||||
{
|
||||
LOG.warn("Ignored arg: " + node);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Process real arguments
|
||||
for (; i < cfg.size(); i++)
|
||||
{
|
||||
|
@ -464,6 +465,10 @@ public class XmlConfiguration
|
|||
String tag = node.getTag();
|
||||
switch (tag)
|
||||
{
|
||||
case "Arg":
|
||||
case "Class":
|
||||
case "Id":
|
||||
throw new IllegalStateException("Element '" + tag + "' not skipped");
|
||||
case "Set":
|
||||
set(obj, node);
|
||||
break;
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.stream.Collectors;
|
|||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
|
||||
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
|
@ -54,7 +55,10 @@ import org.xml.sax.SAXException;
|
|||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
@ -257,7 +261,12 @@ public class XmlConfigurationTest
|
|||
|
||||
public XmlConfiguration asXmlConfiguration(String rawXml) throws IOException, SAXException
|
||||
{
|
||||
Path testFile = workDir.getEmptyPathDir().resolve("raw.xml");
|
||||
return asXmlConfiguration("raw.xml", rawXml);
|
||||
}
|
||||
|
||||
public XmlConfiguration asXmlConfiguration(String filename, String rawXml) throws IOException, SAXException
|
||||
{
|
||||
Path testFile = workDir.getEmptyPathDir().resolve(filename);
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(testFile, UTF_8))
|
||||
{
|
||||
writer.write(rawXml);
|
||||
|
@ -1337,6 +1346,185 @@ public class XmlConfigurationTest
|
|||
}
|
||||
}
|
||||
|
||||
public static class BarNamed
|
||||
{
|
||||
private String foo;
|
||||
private List<String> zeds;
|
||||
|
||||
public BarNamed(@Name("foo") String foo)
|
||||
{
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public void addZed(String zed)
|
||||
{
|
||||
if (zeds == null)
|
||||
zeds = new ArrayList<>();
|
||||
zeds.add(zed);
|
||||
}
|
||||
|
||||
public List<String> getZeds()
|
||||
{
|
||||
return zeds;
|
||||
}
|
||||
|
||||
public String getFoo()
|
||||
{
|
||||
return foo;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfiguredWithNamedArg() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlFoo = asXmlConfiguration("foo.xml",
|
||||
"<Configure>\n" +
|
||||
" <New id=\"foo\" class=\"java.lang.String\">\n" +
|
||||
" <Arg>foozball</Arg>\n" +
|
||||
" </New>\n" +
|
||||
"</Configure>");
|
||||
XmlConfiguration xmlBar = asXmlConfiguration("bar.xml",
|
||||
"<Configure id=\"bar\" class=\"" + BarNamed.class.getName() + "\">\n" +
|
||||
" <Arg name=\"foo\"><Ref refid=\"foo\"/></Arg>\n" +
|
||||
"</Configure>");
|
||||
|
||||
try (StdErrCapture logCapture = new StdErrCapture(XmlConfiguration.class))
|
||||
{
|
||||
Map<String, Object> idMap = mimicXmlConfigurationMain(xmlFoo, xmlBar);
|
||||
Object obj = idMap.get("bar");
|
||||
assertThat("BarNamed instance created", obj, instanceOf(BarNamed.class));
|
||||
BarNamed bar = (BarNamed)obj;
|
||||
assertThat("BarNamed has foo", bar.getFoo(), is("foozball"));
|
||||
|
||||
List<String> warnLogs = logCapture.getLines()
|
||||
.stream().filter(line -> line.contains(":WARN:"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat("WARN logs size", warnLogs.size(), is(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfiguredWithArgNotUsingName() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlFoo = asXmlConfiguration("foo.xml",
|
||||
"<Configure>\n" +
|
||||
" <New id=\"foo\" class=\"java.lang.String\">\n" +
|
||||
" <Arg>foozball</Arg>\n" +
|
||||
" </New>\n" +
|
||||
"</Configure>");
|
||||
XmlConfiguration xmlBar = asXmlConfiguration("bar.xml",
|
||||
"<Configure id=\"bar\" class=\"" + BarNamed.class.getName() + "\">\n" +
|
||||
" <Arg><Ref refid=\"foo\"/></Arg>\n" + // no name specified
|
||||
"</Configure>");
|
||||
|
||||
try (StdErrCapture logCapture = new StdErrCapture(XmlConfiguration.class))
|
||||
{
|
||||
Map<String, Object> idMap = mimicXmlConfigurationMain(xmlFoo, xmlBar);
|
||||
Object obj = idMap.get("bar");
|
||||
assertThat("BarNamed instance created", obj, instanceOf(BarNamed.class));
|
||||
BarNamed bar = (BarNamed)obj;
|
||||
assertThat("BarNamed has foo", bar.getFoo(), is("foozball"));
|
||||
|
||||
List<String> warnLogs = logCapture.getLines()
|
||||
.stream().filter(line -> line.contains(":WARN:"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat("WARN logs size", warnLogs.size(), is(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfiguredWithBadNamedArg() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlBar = asXmlConfiguration("bar.xml",
|
||||
"<Configure id=\"bar\" class=\"" + BarNamed.class.getName() + "\">\n" +
|
||||
" <Arg name=\"foozball\">foozball</Arg>\n" + // wrong name specified
|
||||
"</Configure>");
|
||||
|
||||
IllegalStateException cause = assertThrows(IllegalStateException.class, () ->
|
||||
mimicXmlConfigurationMain(xmlBar));
|
||||
|
||||
assertThat("Cause message", cause.getMessage(), containsString("No matching constructor"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfiguredWithTooManyNamedArgs() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlBar = asXmlConfiguration("bar.xml",
|
||||
"<Configure id=\"bar\" class=\"" + BarNamed.class.getName() + "\">\n" +
|
||||
" <Arg name=\"foo\">foozball</Arg>\n" +
|
||||
" <Arg name=\"foo\">soccer</Arg>\n" + // neither should win
|
||||
"</Configure>");
|
||||
|
||||
IllegalStateException cause = assertThrows(IllegalStateException.class, () ->
|
||||
mimicXmlConfigurationMain(xmlBar));
|
||||
|
||||
assertThat("Cause message", cause.getMessage(), containsString("No matching constructor"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfiguredSameWithNamedArgTwice() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlFoo = asXmlConfiguration("foo.xml",
|
||||
"<Configure>\n" +
|
||||
" <New id=\"foo\" class=\"java.lang.String\">\n" +
|
||||
" <Arg>foozball</Arg>\n" +
|
||||
" </New>\n" +
|
||||
"</Configure>");
|
||||
XmlConfiguration xmlBar = asXmlConfiguration("bar.xml",
|
||||
"<Configure id=\"bar\" class=\"" + BarNamed.class.getName() + "\">\n" +
|
||||
" <Arg name=\"foo\"><Ref refid=\"foo\"/></Arg>\n" +
|
||||
"</Configure>");
|
||||
XmlConfiguration xmlAddZed = asXmlConfiguration("zed.xml",
|
||||
"<Configure id=\"bar\" class=\"" + BarNamed.class.getName() + "\">\n" +
|
||||
" <Arg name=\"foo\">baz</Arg>\n" + // the invalid line
|
||||
" <Call name=\"addZed\">\n" +
|
||||
" <Arg>plain-zero</Arg>\n" +
|
||||
" </Call>\n" +
|
||||
"</Configure>");
|
||||
|
||||
try (StdErrCapture logCapture = new StdErrCapture(XmlConfiguration.class))
|
||||
{
|
||||
Map<String, Object> idMap = mimicXmlConfigurationMain(xmlFoo, xmlBar, xmlAddZed);
|
||||
Object obj = idMap.get("bar");
|
||||
assertThat("BarNamed instance created", obj, instanceOf(BarNamed.class));
|
||||
BarNamed bar = (BarNamed)obj;
|
||||
assertThat("BarNamed has foo", bar.getFoo(), is("foozball"));
|
||||
List<String> zeds = bar.getZeds();
|
||||
assertThat("BarNamed has zeds", zeds, not(empty()));
|
||||
assertThat("Zeds[0]", zeds.get(0), is("plain-zero"));
|
||||
|
||||
List<String> warnLogs = logCapture.getLines()
|
||||
.stream().filter(line -> line.contains(":WARN:"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat("WARN logs count", warnLogs.size(), is(1));
|
||||
|
||||
String actualWarn = warnLogs.get(0);
|
||||
assertThat("WARN logs", actualWarn,
|
||||
allOf(containsString("Ignored arg <Arg name="),
|
||||
containsString("zed.xml")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This mimics the XML load behavior in XmlConfiguration.main(String ... args)
|
||||
*/
|
||||
private Map<String, Object> mimicXmlConfigurationMain(XmlConfiguration... configurations) throws Exception
|
||||
{
|
||||
XmlConfiguration last = null;
|
||||
for (XmlConfiguration configuration : configurations)
|
||||
{
|
||||
if (last != null)
|
||||
configuration.getIdMap().putAll(last.getIdMap());
|
||||
configuration.configure();
|
||||
last = configuration;
|
||||
}
|
||||
return last.getIdMap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJettyStandardIdsAndPropertiesJettyWebappsUri() throws Exception
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue