[Bug 380924] xmlconfiguration <Configure and <New supports named constructors, including dynamic ordering of parameters
This commit is contained in:
parent
b5f7e054be
commit
6d3d7b0df8
|
@ -15,6 +15,7 @@ package org.eclipse.jetty.util;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
@ -23,7 +24,9 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
@ -565,4 +568,65 @@ public class TypeUtil
|
|||
}
|
||||
throw new NoSuchMethodException("<init>");
|
||||
}
|
||||
|
||||
public static Object construct(Class<?> klass, Object[] arguments, Map<String, Object> namedArgMap) throws InvocationTargetException, NoSuchMethodException
|
||||
{
|
||||
for (Constructor<?> constructor : klass.getConstructors())
|
||||
{
|
||||
if (constructor.getParameterTypes().length != arguments.length)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
Annotation[][] parameterAnnotations = constructor.getParameterAnnotations();
|
||||
|
||||
// target has no annotations
|
||||
if ( parameterAnnotations == null || parameterAnnotations.length == 0 )
|
||||
{
|
||||
LOG.debug("Target has no parameter annotations");
|
||||
return constructor.newInstance(arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
Object[] swizzled = new Object[arguments.length];
|
||||
|
||||
int count = 0;
|
||||
for ( Annotation[] annotations : parameterAnnotations )
|
||||
{
|
||||
for ( Annotation annotation : annotations)
|
||||
{
|
||||
if ( annotation instanceof Name )
|
||||
{
|
||||
Name param = (Name)annotation;
|
||||
|
||||
if (namedArgMap.containsKey(param.value()))
|
||||
{
|
||||
LOG.debug("placing named {} in position {}", param.value(), count);
|
||||
swizzled[count] = namedArgMap.get(param.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug("placing {} in position {}", arguments[count], count);
|
||||
swizzled[count] = arguments[count];
|
||||
}
|
||||
++count;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug("passing on annotation {}", annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return constructor.newInstance(swizzled);
|
||||
}
|
||||
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException | IllegalArgumentException e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
throw new NoSuchMethodException("<init>");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.Collection;
|
|||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
@ -49,6 +50,7 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.xml.XmlParser.Node;
|
||||
import org.junit.Assert;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
|
@ -341,29 +343,50 @@ public class XmlConfiguration
|
|||
String id = _config.getAttribute("id");
|
||||
Object obj = id == null ? null : _idMap.get(id);
|
||||
|
||||
|
||||
|
||||
int index = _config.size();
|
||||
if (obj == null && oClass != null)
|
||||
{
|
||||
List<Object> arguments = new ArrayList<>();
|
||||
Map<String, Object> namedArgMap = new HashMap<String, Object>();
|
||||
|
||||
List<Object> arguments = new LinkedList<>();
|
||||
for (int i = 0; i < _config.size(); i++)
|
||||
{
|
||||
Object o = _config.get(i);
|
||||
if (o instanceof String)
|
||||
{
|
||||
continue;
|
||||
if (!((XmlParser.Node)o).getTag().equals("Arg"))
|
||||
}
|
||||
XmlParser.Node node = (XmlParser.Node)o;
|
||||
|
||||
if (!(node.getTag().equals("Arg")))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
String namedAttribute = node.getAttribute("name");
|
||||
if ( namedAttribute != null )
|
||||
{
|
||||
namedArgMap.put(namedAttribute,value(obj,(XmlParser.Node)o));
|
||||
}
|
||||
|
||||
arguments.add(value(obj, (XmlParser.Node)o));
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
obj = TypeUtil.construct(oClass, arguments.toArray());
|
||||
if ( namedArgMap.size() > 0 )
|
||||
{
|
||||
obj = TypeUtil.construct(oClass, arguments.toArray(), namedArgMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = TypeUtil.construct(oClass, arguments.toArray());
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException x)
|
||||
{
|
||||
|
@ -780,13 +803,29 @@ public class XmlConfiguration
|
|||
size++;
|
||||
}
|
||||
|
||||
Map<String, Object> namedArgMap = new HashMap<String, Object>();
|
||||
List<Object> arguments = new LinkedList<>();
|
||||
|
||||
Object[] arg = new Object[size];
|
||||
for (int i = 0, j = 0; j < size; i++)
|
||||
{
|
||||
Object o = node.get(i);
|
||||
|
||||
XmlParser.Node argNode = (XmlParser.Node)o;
|
||||
if (o instanceof String)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
arg[j++] = value(obj,(XmlParser.Node)o);
|
||||
|
||||
String namedAttribute = argNode.getAttribute("name");
|
||||
if ( namedAttribute != null )
|
||||
{
|
||||
namedArgMap.put(namedAttribute,value(obj,(XmlParser.Node)o));
|
||||
}
|
||||
|
||||
arguments.add(value(obj,(XmlParser.Node)o));
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -794,7 +833,18 @@ public class XmlConfiguration
|
|||
|
||||
try
|
||||
{
|
||||
Object n = TypeUtil.construct(oClass, arg);
|
||||
Object n;
|
||||
if ( namedArgMap.size() > 0 )
|
||||
{
|
||||
LOG.debug("using named mapping");
|
||||
n = TypeUtil.construct(oClass, arguments.toArray(), namedArgMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug("using normal mapping");
|
||||
n = TypeUtil.construct(oClass, arguments.toArray());
|
||||
}
|
||||
|
||||
configure(n,node,argi);
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ public class AnnotatedTestConfiguration
|
|||
private String second;
|
||||
private String third;
|
||||
|
||||
AnnotatedTestConfiguration nested;
|
||||
|
||||
public AnnotatedTestConfiguration(@Name("first") String first, @Name("second") String second, @Name("third") String third)
|
||||
{
|
||||
this.first = first;
|
||||
|
@ -45,6 +47,14 @@ public class AnnotatedTestConfiguration
|
|||
this.third = third;
|
||||
}
|
||||
|
||||
|
||||
public AnnotatedTestConfiguration getNested()
|
||||
{
|
||||
return nested;
|
||||
}
|
||||
|
||||
public void setNested(AnnotatedTestConfiguration nested)
|
||||
{
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -377,6 +377,7 @@ public class XmlConfigurationTest
|
|||
Assert.assertEquals("third parameter not wired correctly","arg3", atc.getThird());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorNamedInjectionUnOrdered() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
|
||||
|
@ -393,6 +394,7 @@ public class XmlConfigurationTest
|
|||
Assert.assertEquals("third parameter not wired correctly","arg3", atc.getThird());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorNamedInjectionOrderedMixed() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
|
||||
|
@ -409,6 +411,7 @@ public class XmlConfigurationTest
|
|||
Assert.assertEquals("third parameter not wired correctly","arg3", atc.getThird());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorNamedInjectionUnorderedMixed() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
|
||||
|
@ -424,4 +427,140 @@ public class XmlConfigurationTest
|
|||
Assert.assertEquals("second parameter not wired correctly","arg2", atc.getSecond());
|
||||
Assert.assertEquals("third parameter not wired correctly","arg3", atc.getThird());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedConstructorNamedInjection() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
|
||||
"<Configure class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg>arg1</Arg> " +
|
||||
" <Arg>arg2</Arg> " +
|
||||
" <Arg>arg3</Arg> " +
|
||||
" <Set name=\"nested\"> " +
|
||||
" <New class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg>arg1</Arg> " +
|
||||
" <Arg>arg2</Arg> " +
|
||||
" <Arg>arg3</Arg> " +
|
||||
" </New>" +
|
||||
" </Set>" +
|
||||
"</Configure>");
|
||||
|
||||
AnnotatedTestConfiguration atc = (AnnotatedTestConfiguration)xmlConfiguration.configure();
|
||||
|
||||
Assert.assertEquals("first parameter not wired correctly","arg1", atc.getFirst());
|
||||
Assert.assertEquals("second parameter not wired correctly","arg2", atc.getSecond());
|
||||
Assert.assertEquals("third parameter not wired correctly","arg3", atc.getThird());
|
||||
Assert.assertEquals("nested first parameter not wired correctly","arg1", atc.getNested().getFirst());
|
||||
Assert.assertEquals("nested second parameter not wired correctly","arg2", atc.getNested().getSecond());
|
||||
Assert.assertEquals("nested third parameter not wired correctly","arg3", atc.getNested().getThird());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedConstructorNamedInjectionOrdered() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
|
||||
"<Configure class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg name=\"first\">arg1</Arg> " +
|
||||
" <Arg name=\"second\">arg2</Arg> " +
|
||||
" <Arg name=\"third\">arg3</Arg> " +
|
||||
" <Set name=\"nested\"> " +
|
||||
" <New class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg name=\"first\">arg1</Arg> " +
|
||||
" <Arg name=\"second\">arg2</Arg> " +
|
||||
" <Arg name=\"third\">arg3</Arg> " +
|
||||
" </New>" +
|
||||
" </Set>" +
|
||||
"</Configure>");
|
||||
|
||||
AnnotatedTestConfiguration atc = (AnnotatedTestConfiguration)xmlConfiguration.configure();
|
||||
|
||||
Assert.assertEquals("first parameter not wired correctly","arg1", atc.getFirst());
|
||||
Assert.assertEquals("second parameter not wired correctly","arg2", atc.getSecond());
|
||||
Assert.assertEquals("third parameter not wired correctly","arg3", atc.getThird());
|
||||
Assert.assertEquals("nested first parameter not wired correctly","arg1", atc.getNested().getFirst());
|
||||
Assert.assertEquals("nested second parameter not wired correctly","arg2", atc.getNested().getSecond());
|
||||
Assert.assertEquals("nested third parameter not wired correctly","arg3", atc.getNested().getThird());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedConstructorNamedInjectionUnOrdered() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
|
||||
"<Configure class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg name=\"first\">arg1</Arg> " +
|
||||
" <Arg name=\"third\">arg3</Arg> " +
|
||||
" <Arg name=\"second\">arg2</Arg> " +
|
||||
" <Set name=\"nested\"> " +
|
||||
" <New class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg name=\"first\">arg1</Arg> " +
|
||||
" <Arg name=\"third\">arg3</Arg> " +
|
||||
" <Arg name=\"second\">arg2</Arg> " +
|
||||
" </New>" +
|
||||
" </Set>" +
|
||||
"</Configure>");
|
||||
|
||||
AnnotatedTestConfiguration atc = (AnnotatedTestConfiguration)xmlConfiguration.configure();
|
||||
|
||||
Assert.assertEquals("first parameter not wired correctly","arg1", atc.getFirst());
|
||||
Assert.assertEquals("second parameter not wired correctly","arg2", atc.getSecond());
|
||||
Assert.assertEquals("third parameter not wired correctly","arg3", atc.getThird());
|
||||
Assert.assertEquals("nested first parameter not wired correctly","arg1", atc.getNested().getFirst());
|
||||
Assert.assertEquals("nested second parameter not wired correctly","arg2", atc.getNested().getSecond());
|
||||
Assert.assertEquals("nested third parameter not wired correctly","arg3", atc.getNested().getThird());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedConstructorNamedInjectionOrderedMixed() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
|
||||
"<Configure class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg name=\"first\">arg1</Arg> " +
|
||||
" <Arg>arg2</Arg> " +
|
||||
" <Arg name=\"third\">arg3</Arg> " +
|
||||
" <Set name=\"nested\"> " +
|
||||
" <New class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg name=\"first\">arg1</Arg> " +
|
||||
" <Arg>arg2</Arg> " +
|
||||
" <Arg name=\"third\">arg3</Arg> " +
|
||||
" </New>" +
|
||||
" </Set>" +
|
||||
"</Configure>");
|
||||
|
||||
AnnotatedTestConfiguration atc = (AnnotatedTestConfiguration)xmlConfiguration.configure();
|
||||
|
||||
Assert.assertEquals("first parameter not wired correctly","arg1", atc.getFirst());
|
||||
Assert.assertEquals("second parameter not wired correctly","arg2", atc.getSecond());
|
||||
Assert.assertEquals("third parameter not wired correctly","arg3", atc.getThird());
|
||||
Assert.assertEquals("nested first parameter not wired correctly","arg1", atc.getNested().getFirst());
|
||||
Assert.assertEquals("nested second parameter not wired correctly","arg2", atc.getNested().getSecond());
|
||||
Assert.assertEquals("nested third parameter not wired correctly","arg3", atc.getNested().getThird());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedConstructorNamedInjectionUnorderedMixed() throws Exception
|
||||
{
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
|
||||
"<Configure class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg name=\"third\">arg3</Arg> " +
|
||||
" <Arg>arg2</Arg> " +
|
||||
" <Arg name=\"first\">arg1</Arg> " +
|
||||
" <Set name=\"nested\"> " +
|
||||
" <New class=\"org.eclipse.jetty.xml.AnnotatedTestConfiguration\">" +
|
||||
" <Arg name=\"third\">arg3</Arg> " +
|
||||
" <Arg>arg2</Arg> " +
|
||||
" <Arg name=\"first\">arg1</Arg> " +
|
||||
" </New>" +
|
||||
" </Set>" +
|
||||
"</Configure>");
|
||||
|
||||
AnnotatedTestConfiguration atc = (AnnotatedTestConfiguration)xmlConfiguration.configure();
|
||||
|
||||
Assert.assertEquals("first parameter not wired correctly","arg1", atc.getFirst());
|
||||
Assert.assertEquals("second parameter not wired correctly","arg2", atc.getSecond());
|
||||
Assert.assertEquals("third parameter not wired correctly","arg3", atc.getThird());
|
||||
Assert.assertEquals("nested first parameter not wired correctly","arg1", atc.getNested().getFirst());
|
||||
Assert.assertEquals("nested second parameter not wired correctly","arg2", atc.getNested().getSecond());
|
||||
Assert.assertEquals("nested third parameter not wired correctly","arg3", atc.getNested().getThird());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
org.eclipse.jetty.xml.LEVEL=DEBUG
|
||||
org.eclipse.jetty.util.LEVEL=DEBUG
|
Loading…
Reference in New Issue