Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x
This commit is contained in:
commit
277ce5f3a5
|
@ -199,7 +199,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||||
|
|
||||||
private final List<EventListener> _programmaticListeners = new CopyOnWriteArrayList<>();
|
private final List<EventListener> _programmaticListeners = new CopyOnWriteArrayList<>();
|
||||||
private final List<ServletContextListener> _servletContextListeners = new CopyOnWriteArrayList<>();
|
private final List<ServletContextListener> _servletContextListeners = new CopyOnWriteArrayList<>();
|
||||||
private final List<ServletContextListener> _destroySerletContextListeners = new ArrayList<>();
|
private final List<ServletContextListener> _destroyServletContextListeners = new ArrayList<>();
|
||||||
private final List<ServletContextAttributeListener> _servletContextAttributeListeners = new CopyOnWriteArrayList<>();
|
private final List<ServletContextAttributeListener> _servletContextAttributeListeners = new CopyOnWriteArrayList<>();
|
||||||
private final List<ServletRequestListener> _servletRequestListeners = new CopyOnWriteArrayList<>();
|
private final List<ServletRequestListener> _servletRequestListeners = new CopyOnWriteArrayList<>();
|
||||||
private final List<ServletRequestAttributeListener> _servletRequestAttributeListeners = new CopyOnWriteArrayList<>();
|
private final List<ServletRequestAttributeListener> _servletRequestAttributeListeners = new CopyOnWriteArrayList<>();
|
||||||
|
@ -646,7 +646,10 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||||
_contextListeners.remove(listener);
|
_contextListeners.remove(listener);
|
||||||
|
|
||||||
if (listener instanceof ServletContextListener)
|
if (listener instanceof ServletContextListener)
|
||||||
|
{
|
||||||
_servletContextListeners.remove(listener);
|
_servletContextListeners.remove(listener);
|
||||||
|
_destroyServletContextListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
if (listener instanceof ServletContextAttributeListener)
|
if (listener instanceof ServletContextAttributeListener)
|
||||||
_servletContextAttributeListeners.remove(listener);
|
_servletContextAttributeListeners.remove(listener);
|
||||||
|
@ -838,14 +841,14 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||||
super.doStart();
|
super.doStart();
|
||||||
|
|
||||||
// Call context listeners
|
// Call context listeners
|
||||||
_destroySerletContextListeners.clear();
|
_destroyServletContextListeners.clear();
|
||||||
if (!_servletContextListeners.isEmpty())
|
if (!_servletContextListeners.isEmpty())
|
||||||
{
|
{
|
||||||
ServletContextEvent event = new ServletContextEvent(_scontext);
|
ServletContextEvent event = new ServletContextEvent(_scontext);
|
||||||
for (ServletContextListener listener : _servletContextListeners)
|
for (ServletContextListener listener : _servletContextListeners)
|
||||||
{
|
{
|
||||||
callContextInitialized(listener, event);
|
callContextInitialized(listener, event);
|
||||||
_destroySerletContextListeners.add(listener);
|
_destroyServletContextListeners.add(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -854,9 +857,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
||||||
{
|
{
|
||||||
// Call the context listeners
|
// Call the context listeners
|
||||||
ServletContextEvent event = new ServletContextEvent(_scontext);
|
ServletContextEvent event = new ServletContextEvent(_scontext);
|
||||||
Collections.reverse(_destroySerletContextListeners);
|
Collections.reverse(_destroyServletContextListeners);
|
||||||
MultiException ex = new MultiException();
|
MultiException ex = new MultiException();
|
||||||
for (ServletContextListener listener : _destroySerletContextListeners)
|
for (ServletContextListener listener : _destroyServletContextListeners)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -239,7 +239,7 @@ public class DateCache
|
||||||
// recheck the tick, to save multiple formats
|
// recheck the tick, to save multiple formats
|
||||||
if (tick == null || tick._seconds != seconds)
|
if (tick == null || tick._seconds != seconds)
|
||||||
{
|
{
|
||||||
String s = ZonedDateTime.ofInstant(Instant.now(), _zoneId).format(_tzFormat);
|
String s = ZonedDateTime.ofInstant(Instant.ofEpochMilli(now), _zoneId).format(_tzFormat);
|
||||||
_tick = new Tick(seconds, s);
|
_tick = new Tick(seconds, s);
|
||||||
tick = _tick;
|
tick = _tick;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.Parameter;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -97,20 +98,47 @@ public class XmlConfiguration
|
||||||
};
|
};
|
||||||
private static final Iterable<ConfigurationProcessorFactory> PROCESSOR_FACTORIES = ServiceLoader.load(ConfigurationProcessorFactory.class);
|
private static final Iterable<ConfigurationProcessorFactory> PROCESSOR_FACTORIES = ServiceLoader.load(ConfigurationProcessorFactory.class);
|
||||||
private static final XmlParser PARSER = initParser();
|
private static final XmlParser PARSER = initParser();
|
||||||
private static final Comparator<Executable> EXECUTABLE_COMPARATOR = (o1, o2) ->
|
public static final Comparator<Executable> EXECUTABLE_COMPARATOR = (e1, e2) ->
|
||||||
{
|
{
|
||||||
int p1 = o1.getParameterCount();
|
// Favour methods with less parameters
|
||||||
int p2 = o2.getParameterCount();
|
int count = e1.getParameterCount();
|
||||||
int compare = Integer.compare(p1, p2);
|
int compare = Integer.compare(count, e2.getParameterCount());
|
||||||
if (compare == 0 && p1 > 0)
|
if (compare == 0 && count > 0)
|
||||||
{
|
{
|
||||||
boolean a1 = o1.getParameterTypes()[p1 - 1].isArray();
|
Parameter[] p1 = e1.getParameters();
|
||||||
boolean a2 = o2.getParameterTypes()[p2 - 1].isArray();
|
Parameter[] p2 = e2.getParameters();
|
||||||
if (a1 && !a2)
|
|
||||||
compare = 1;
|
// Favour methods without varargs
|
||||||
else if (!a1 && a2)
|
compare = Boolean.compare(p1[count - 1].isVarArgs(), p2[count - 1].isVarArgs());
|
||||||
compare = -1;
|
if (compare == 0)
|
||||||
|
{
|
||||||
|
// Rank by differences in the parameters
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Class<?> t1 = p1[i].getType();
|
||||||
|
Class<?> t2 = p2[i].getType();
|
||||||
|
if (t1 != t2)
|
||||||
|
{
|
||||||
|
// Favour derived type over base type
|
||||||
|
compare = Boolean.compare(t1.isAssignableFrom(t2), t2.isAssignableFrom(t1));
|
||||||
|
if (compare == 0)
|
||||||
|
{
|
||||||
|
// favour primitive type over reference
|
||||||
|
compare = Boolean.compare(!t1.isPrimitive(), !t2.isPrimitive());
|
||||||
|
if (compare == 0)
|
||||||
|
// Use name to avoid non determinant sorting
|
||||||
|
compare = t1.getName().compareTo(t2.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// break on the first different parameter (should always be true)
|
||||||
|
if (compare != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compare = Math.min(1, Math.max(compare, -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
return compare;
|
return compare;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1610,7 +1638,7 @@ public class XmlConfiguration
|
||||||
{
|
{
|
||||||
// Could this be an empty varargs match?
|
// Could this be an empty varargs match?
|
||||||
int count = executable.getParameterCount();
|
int count = executable.getParameterCount();
|
||||||
if (count > 0 && executable.getParameterTypes()[count - 1].isArray())
|
if (count > 0 && executable.getParameters()[count - 1].isVarArgs())
|
||||||
{
|
{
|
||||||
// There is not a no varArgs alternative so let's try a an empty varArgs match
|
// There is not a no varArgs alternative so let's try a an empty varArgs match
|
||||||
args = asEmptyVarArgs(executable.getParameterTypes()[count - 1]).matchArgsToParameters(executable);
|
args = asEmptyVarArgs(executable.getParameterTypes()[count - 1]).matchArgsToParameters(executable);
|
||||||
|
@ -1641,47 +1669,54 @@ public class XmlConfiguration
|
||||||
return new Object[0];
|
return new Object[0];
|
||||||
|
|
||||||
// If no arg names are specified, keep the arg order
|
// If no arg names are specified, keep the arg order
|
||||||
|
Object[] args;
|
||||||
if (_names.stream().noneMatch(Objects::nonNull))
|
if (_names.stream().noneMatch(Objects::nonNull))
|
||||||
return _arguments.toArray(new Object[0]);
|
|
||||||
|
|
||||||
// If we don't have any parameters with names, then no match
|
|
||||||
Annotation[][] parameterAnnotations = executable.getParameterAnnotations();
|
|
||||||
if (parameterAnnotations == null || parameterAnnotations.length == 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// Find the position of all named parameters from the executable
|
|
||||||
Map<String, Integer> position = new HashMap<>();
|
|
||||||
int p = 0;
|
|
||||||
for (Annotation[] paramAnnotation : parameterAnnotations)
|
|
||||||
{
|
{
|
||||||
Integer pos = p++;
|
args = _arguments.toArray(new Object[0]);
|
||||||
Arrays.stream(paramAnnotation)
|
|
||||||
.filter(Name.class::isInstance)
|
|
||||||
.map(Name.class::cast)
|
|
||||||
.findFirst().ifPresent(n -> position.put(n.value(), pos));
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
List<Object> arguments = new ArrayList<>(_arguments);
|
|
||||||
List<String> names = new ArrayList<>(_names);
|
|
||||||
// Map the actual arguments to the names
|
|
||||||
for (p = 0; p < count; p++)
|
|
||||||
{
|
{
|
||||||
String name = names.get(p);
|
// If we don't have any parameters with names, then no match
|
||||||
if (name != null)
|
Annotation[][] parameterAnnotations = executable.getParameterAnnotations();
|
||||||
|
if (parameterAnnotations == null || parameterAnnotations.length == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Find the position of all named parameters from the executable
|
||||||
|
Map<String, Integer> position = new HashMap<>();
|
||||||
|
int p = 0;
|
||||||
|
for (Annotation[] paramAnnotation : parameterAnnotations)
|
||||||
{
|
{
|
||||||
Integer pos = position.get(name);
|
Integer pos = p++;
|
||||||
if (pos == null)
|
Arrays.stream(paramAnnotation)
|
||||||
return null;
|
.filter(Name.class::isInstance)
|
||||||
if (pos != p)
|
.map(Name.class::cast)
|
||||||
|
.findFirst().ifPresent(n -> position.put(n.value(), pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object> arguments = new ArrayList<>(_arguments);
|
||||||
|
List<String> names = new ArrayList<>(_names);
|
||||||
|
// Map the actual arguments to the names
|
||||||
|
for (p = 0; p < count; p++)
|
||||||
|
{
|
||||||
|
String name = names.get(p);
|
||||||
|
if (name != null)
|
||||||
{
|
{
|
||||||
// adjust position of parameter
|
Integer pos = position.get(name);
|
||||||
arguments.add(pos, arguments.remove(p));
|
if (pos == null)
|
||||||
names.add(pos, names.remove(p));
|
return null;
|
||||||
p = Math.min(p, pos);
|
if (pos != p)
|
||||||
|
{
|
||||||
|
// adjust position of parameter
|
||||||
|
arguments.add(pos, arguments.remove(p));
|
||||||
|
names.add(pos, names.remove(p));
|
||||||
|
p = Math.min(p, pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
args = arguments.toArray(new Object[0]);
|
||||||
}
|
}
|
||||||
return arguments.toArray(new Object[0]);
|
|
||||||
|
return args;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,21 @@ public class AnnotatedTestConfiguration
|
||||||
this.third = theRest.length > 1 ? theRest[1] : null;
|
this.third = theRest.length > 1 ? theRest[1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void call(Integer value)
|
||||||
|
{
|
||||||
|
this.first = String.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void call(String value)
|
||||||
|
{
|
||||||
|
this.second = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E> void call(E value)
|
||||||
|
{
|
||||||
|
this.third = String.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
public String getFirst()
|
public String getFirst()
|
||||||
{
|
{
|
||||||
return first;
|
return first;
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class TestConfiguration extends HashMap<String, Object>
|
||||||
private Set set;
|
private Set set;
|
||||||
private ConstructorArgTestClass constructorArgTestClass;
|
private ConstructorArgTestClass constructorArgTestClass;
|
||||||
public Map map;
|
public Map map;
|
||||||
|
public Double number;
|
||||||
|
|
||||||
public TestConfiguration()
|
public TestConfiguration()
|
||||||
{
|
{
|
||||||
|
@ -65,6 +66,16 @@ public class TestConfiguration extends HashMap<String, Object>
|
||||||
name = n;
|
name = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNumber(Object value)
|
||||||
|
{
|
||||||
|
testObject = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNumber(double value)
|
||||||
|
{
|
||||||
|
number = value;
|
||||||
|
}
|
||||||
|
|
||||||
public void setTest(Object value)
|
public void setTest(Object value)
|
||||||
{
|
{
|
||||||
testObject = value;
|
testObject = value;
|
||||||
|
|
|
@ -23,10 +23,12 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -41,11 +43,14 @@ import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.util.log.StdErrLog;
|
import org.eclipse.jetty.util.log.StdErrLog;
|
||||||
import org.eclipse.jetty.util.resource.PathResource;
|
import org.eclipse.jetty.util.resource.PathResource;
|
||||||
import org.eclipse.jetty.util.resource.Resource;
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.RepeatedTest;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
@ -633,6 +638,72 @@ public class XmlConfigurationTest
|
||||||
assertEquals("arg3", atc.getNested().getThird(), "nested third parameter not wired correctly");
|
assertEquals("arg3", atc.getNested().getThird(), "nested third parameter not wired correctly");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class TestOrder
|
||||||
|
{
|
||||||
|
public void call()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void call(int o)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void call(Object o)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void call(String s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void call(String... ss)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void call(String s, String... ss)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RepeatedTest(10)
|
||||||
|
public void testMethodOrdering() throws Exception
|
||||||
|
{
|
||||||
|
List<Method> methods = Arrays.stream(TestOrder.class.getMethods()).filter(m -> "call".equals(m.getName())).collect(Collectors.toList());
|
||||||
|
Collections.shuffle(methods);
|
||||||
|
Collections.sort(methods, XmlConfiguration.EXECUTABLE_COMPARATOR);
|
||||||
|
assertThat(methods, Matchers.contains(
|
||||||
|
TestOrder.class.getMethod("call"),
|
||||||
|
TestOrder.class.getMethod("call", int.class),
|
||||||
|
TestOrder.class.getMethod("call", String.class),
|
||||||
|
TestOrder.class.getMethod("call", Object.class),
|
||||||
|
TestOrder.class.getMethod("call", String[].class),
|
||||||
|
TestOrder.class.getMethod("call", String.class, String[].class)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverloadedCall() throws Exception
|
||||||
|
{
|
||||||
|
XmlConfiguration xmlConfiguration = asXmlConfiguration(
|
||||||
|
"<Configure class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||||
|
" <Call name=\"call\">" +
|
||||||
|
" <Arg type=\"int\">1</Arg>" +
|
||||||
|
" </Call>" +
|
||||||
|
" <Call name=\"call\">" +
|
||||||
|
" <Arg>2</Arg>" +
|
||||||
|
" </Call>" +
|
||||||
|
" <Call name=\"call\">" +
|
||||||
|
" <Arg type=\"Long\">3</Arg>" +
|
||||||
|
" </Call>" +
|
||||||
|
"</Configure>");
|
||||||
|
|
||||||
|
AnnotatedTestConfiguration atc = (AnnotatedTestConfiguration)xmlConfiguration.configure();
|
||||||
|
|
||||||
|
assertEquals("1", atc.getFirst());
|
||||||
|
assertEquals("2", atc.getSecond());
|
||||||
|
assertEquals("3", atc.getThird());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNestedConstructorNamedInjectionUnOrdered() throws Exception
|
public void testNestedConstructorNamedInjectionUnOrdered() throws Exception
|
||||||
{
|
{
|
||||||
|
@ -820,6 +891,38 @@ public class XmlConfigurationTest
|
||||||
assertNull(atc.getThird());
|
assertNull(atc.getThird());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<String> typeTestData()
|
||||||
|
{
|
||||||
|
return Arrays.asList(
|
||||||
|
"byte",
|
||||||
|
"int",
|
||||||
|
"short",
|
||||||
|
"long",
|
||||||
|
"float",
|
||||||
|
"double",
|
||||||
|
"Byte",
|
||||||
|
"Integer",
|
||||||
|
"Short",
|
||||||
|
"Long",
|
||||||
|
"Float",
|
||||||
|
"Double");
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("typeTestData")
|
||||||
|
public void testCallNumberConversion(String type) throws Exception
|
||||||
|
{
|
||||||
|
XmlConfiguration xmlConfiguration = asXmlConfiguration(
|
||||||
|
"<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\">" +
|
||||||
|
" <Call name=\"setNumber\">" +
|
||||||
|
" <Arg type=\"" + type + "\">42</Arg>" +
|
||||||
|
" </Call>" +
|
||||||
|
"</Configure>");
|
||||||
|
|
||||||
|
TestConfiguration tc = (TestConfiguration)xmlConfiguration.configure();
|
||||||
|
assertEquals(42.0D, tc.number);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testArgumentsGetIgnoredMissingDTD() throws Exception
|
public void testArgumentsGetIgnoredMissingDTD() throws Exception
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue