Skip to content

Commit

Permalink
464606 - Support property expansion in "default" attribute of Property.
Browse files Browse the repository at this point in the history
  • Loading branch information
sbordet committed Apr 14, 2015
1 parent 55e74c6 commit 337e0bd
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 55 deletions.
92 changes: 61 additions & 31 deletions jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java
Expand Up @@ -46,6 +46,8 @@
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jetty.util.ArrayQueue;
import org.eclipse.jetty.util.LazyList;
Expand Down Expand Up @@ -79,16 +81,13 @@
public class XmlConfiguration
{
private static final Logger LOG = Log.getLogger(XmlConfiguration.class);

private static final Class<?>[] __primitives =
{Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE};

private static final Class<?>[] __boxedPrimitives =
{Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class};

private static final Class<?>[] __supportedCollections =
{ArrayList.class, ArrayQueue.class, HashSet.class, Queue.class, List.class, Set.class, Collection.class,};

{ArrayList.class, ArrayQueue.class, HashSet.class, Queue.class, List.class, Set.class, Collection.class};
private static final Pattern __propertyPattern = Pattern.compile("\\$\\{([^\\}]+)\\}");
private static final Iterable<ConfigurationProcessorFactory> __factoryLoader = ServiceLoader.load(ConfigurationProcessorFactory.class);
private static final XmlParser __parser = initParser();
private static XmlParser initParser()
Expand Down Expand Up @@ -629,7 +628,7 @@ private void put(Object obj, XmlParser.Node node) throws Exception
Map<Object, Object> map = (Map<Object, Object>)obj;

String name = node.getAttribute("name");
Object value = value(obj,node);
Object value = value(obj, node);
map.put(name,value);
if (LOG.isDebugEnabled())
LOG.debug("XML " + obj + ".put(" + name + "," + value + ")");
Expand Down Expand Up @@ -674,7 +673,7 @@ private Object get(Object obj, XmlParser.Node node) throws Exception
}
}
if (id != null)
_configuration.getIdMap().put(id,obj);
_configuration.getIdMap().put(id, obj);
return obj;
}

Expand Down Expand Up @@ -891,7 +890,7 @@ private Object newMap(Object obj, XmlParser.Node node) throws Exception

Map<Object, Object> map = new HashMap<>();
if (id != null)
_configuration.getIdMap().put(id,map);
_configuration.getIdMap().put(id, map);

for (Object o : node)
{
Expand Down Expand Up @@ -949,32 +948,12 @@ private Object propertyObj(XmlParser.Node node) throws Exception
String defaultValue = node.getAttribute("default");

Object value = null;
boolean present = false;
Map<String,String> properties = _configuration.getProperties();
if (properties != null && nameAttr != null)
{
String preferredName = null;
String[] names = nameAttr.split(",");
for (String name : names)
{
name = name.trim();
if (name.length() == 0)
continue;
if (preferredName == null)
preferredName = name;
value = resolve(properties, nameAttr);

if (properties.containsKey(name))
{
if (!name.equals(preferredName))
LOG.warn("Property '{}' is deprecated, use '{}' instead", name, preferredName);
present = true;
value = properties.get(name);
break;
}
}
}
if (!present)
value = defaultValue;
if (value == null && defaultValue != null)
value = interpolate(properties, defaultValue);

if (idAttr != null)
_configuration.getIdMap().put(idAttr, value);
Expand All @@ -985,6 +964,57 @@ private Object propertyObj(XmlParser.Node node) throws Exception
return value;
}

private String resolve(Map<String, String> properties, String nameAttr)
{
String preferredName = null;
String[] names = nameAttr.split(",");
for (String name : names)
{
name = name.trim();
if (name.length() == 0)
continue;
if (preferredName == null)
preferredName = name;

String value = properties.get(name);
if (value != null)
{
if (!name.equals(preferredName))
LOG.warn("Property '{}' is deprecated, use '{}' instead", name, preferredName);
return value;
}
}
return null;
}

private String interpolate(Map<String, String> properties, String text)
{
StringBuilder result = new StringBuilder();
Matcher matcher = __propertyPattern.matcher(text);
int start = 0;
while (matcher.find(start))
{
int match = matcher.start();
result.append(text.substring(start, match));
String name = matcher.group(1);
String dftValue = null;
int bar = name.indexOf('|');
if (bar > 0)
{
dftValue = name.substring(bar + 1).trim();
name = name.substring(0, bar).trim();
}
String value = resolve(properties, name);
if (value == null)
value = dftValue;
result.append(value);
start = matcher.end();
}
result.append(text.substring(start, text.length()));
String r = result.toString();
return r.isEmpty() ? null : r;
}

/*
* Get the value of an element. If no value type is specified, then white space is trimmed out of the value. If it contains multiple value elements they
* are added as strings before being converted to any specified type. @param node
Expand Down
Expand Up @@ -18,13 +18,6 @@

package org.eclipse.jetty.xml;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
Expand All @@ -36,6 +29,13 @@
import org.junit.Ignore;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

public class XmlConfigurationTest
{
protected String _configure="org/eclipse/jetty/xml/configure.xml";
Expand Down Expand Up @@ -219,8 +219,8 @@ public void testStringConfiguration() throws Exception
new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"Test\">SetValue</Set><Set name=\"Test\" type=\"int\">2</Set></Configure>");
TestConfiguration tc = new TestConfiguration();
configuration.configure(tc);
assertEquals("Set String 3","SetValue",tc.testObject);
assertEquals("Set Type 3",2,tc.testInt);
assertEquals("Set String 3", "SetValue", tc.testObject);
assertEquals("Set Type 3", 2, tc.testInt);
}

@Test
Expand All @@ -233,7 +233,7 @@ public void testListConstructorArg() throws Exception
assertThat("tc.getList() returns null as it's not configured yet",tc.getList(),is(nullValue()));
xmlConfiguration.configure(tc);
assertThat("tc.getList() returns not null",tc.getList(),not(nullValue()));
assertThat("tc.getList() has two entries as specified in the xml",tc.getList().size(),is(2));
assertThat("tc.getList() has two entries as specified in the xml", tc.getList().size(), is(2));
}

@Test
Expand All @@ -248,7 +248,7 @@ public void testTwoArgumentListConstructorArg() throws Exception
assertThat("tc.getList() returns null as it's not configured yet",tc.getList(),is(nullValue()));
xmlConfiguration.configure(tc);
assertThat("tc.getList() returns not null",tc.getList(),not(nullValue()));
assertThat("tc.getList() has two entries as specified in the xml",tc.getList().size(),is(2));
assertThat("tc.getList() has two entries as specified in the xml", tc.getList().size(), is(2));
}

@Test(expected = IllegalArgumentException.class)
Expand All @@ -270,7 +270,7 @@ public void testSetConstructorArg() throws Exception
assertThat("tc.getList() returns null as it's not configured yet",tc.getSet(),is(nullValue()));
xmlConfiguration.configure(tc);
assertThat("tc.getList() returns not null",tc.getSet(),not(nullValue()));
assertThat("tc.getList() has two entries as specified in the xml",tc.getSet().size(),is(2));
assertThat("tc.getList() has two entries as specified in the xml", tc.getSet().size(), is(2));
}

@Test(expected = IllegalArgumentException.class)
Expand All @@ -290,7 +290,7 @@ public void testListSetterWithStringArray() throws Exception
TestConfiguration tc = new TestConfiguration();
assertThat("tc.getList() returns null as it's not configured yet",tc.getList(),is(nullValue()));
xmlConfiguration.configure(tc);
assertThat("tc.getList() has two entries as specified in the xml",tc.getList().size(),is(2));
assertThat("tc.getList() has two entries as specified in the xml", tc.getList().size(), is(2));
}

@Test
Expand All @@ -301,7 +301,7 @@ public void testListSetterWithPrimitiveArray() throws Exception
TestConfiguration tc = new TestConfiguration();
assertThat("tc.getList() returns null as it's not configured yet",tc.getList(),is(nullValue()));
xmlConfiguration.configure(tc);
assertThat("tc.getList() has two entries as specified in the xml",tc.getList().size(),is(2));
assertThat("tc.getList() has two entries as specified in the xml", tc.getList().size(), is(2));
}

@Test(expected=NoSuchMethodException.class)
Expand All @@ -310,7 +310,7 @@ public void testNotSupportedLinkedListSetter() throws Exception
XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"LinkedList\">"
+ INT_ARRAY_XML + "</Set></Configure>");
TestConfiguration tc = new TestConfiguration();
assertThat("tc.getSet() returns null as it's not configured yet",tc.getList(),is(nullValue()));
assertThat("tc.getSet() returns null as it's not configured yet", tc.getList(), is(nullValue()));
xmlConfiguration.configure(tc);
}

Expand All @@ -320,9 +320,9 @@ public void testArrayListSetter() throws Exception
XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"ArrayList\">"
+ INT_ARRAY_XML + "</Set></Configure>");
TestConfiguration tc = new TestConfiguration();
assertThat("tc.getSet() returns null as it's not configured yet",tc.getList(),is(nullValue()));
assertThat("tc.getSet() returns null as it's not configured yet", tc.getList(), is(nullValue()));
xmlConfiguration.configure(tc);
assertThat("tc.getSet() has two entries as specified in the xml",tc.getList().size(),is(2));
assertThat("tc.getSet() has two entries as specified in the xml", tc.getList().size(), is(2));
}

@Test
Expand All @@ -331,9 +331,9 @@ public void testSetSetter() throws Exception
XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"Set\">"
+ STRING_ARRAY_XML + "</Set></Configure>");
TestConfiguration tc = new TestConfiguration();
assertThat("tc.getSet() returns null as it's not configured yet",tc.getSet(),is(nullValue()));
assertThat("tc.getSet() returns null as it's not configured yet", tc.getSet(), is(nullValue()));
xmlConfiguration.configure(tc);
assertThat("tc.getSet() has two entries as specified in the xml",tc.getSet().size(),is(2));
assertThat("tc.getSet() has two entries as specified in the xml", tc.getSet().size(), is(2));
}

@Test
Expand All @@ -342,9 +342,9 @@ public void testSetSetterWithPrimitiveArray() throws Exception
XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"Set\">"
+ INT_ARRAY_XML + "</Set></Configure>");
TestConfiguration tc = new TestConfiguration();
assertThat("tc.getSet() returns null as it's not configured yet",tc.getSet(),is(nullValue()));
assertThat("tc.getSet() returns null as it's not configured yet", tc.getSet(), is(nullValue()));
xmlConfiguration.configure(tc);
assertThat("tc.getSet() has two entries as specified in the xml",tc.getSet().size(),is(2));
assertThat("tc.getSet() has two entries as specified in the xml", tc.getSet().size(), is(2));
}

@Test
Expand Down Expand Up @@ -590,7 +590,7 @@ public void testArgumentsGetIgnoredMissingDTD() throws Exception
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());
Assert.assertEquals("nested third parameter not wired correctly", "arg3", atc.getNested().getThird());
}

@Test
Expand Down Expand Up @@ -618,7 +618,7 @@ public void testSetGetIgnoredMissingDTD() throws Exception
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());
Assert.assertEquals("nested third parameter not wired correctly", "arg3", atc.getNested().getThird());
}

@Test
Expand All @@ -645,7 +645,7 @@ public void testNestedConstructorNamedInjectionUnorderedMixed() throws Exception
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());
Assert.assertEquals("nested third parameter not wired correctly", "arg3", atc.getNested().getThird());
}

public static class NativeHolder
Expand Down Expand Up @@ -820,4 +820,32 @@ public void testWithMultiplePropertyNamesWithSecondPropertyThenSecondIsChosen()
DefaultTestConfiguration config = (DefaultTestConfiguration)xmlConfiguration.configure();
assertEquals(value, config.getFirst());
}

@Test
public void testPropertyNotFoundWithPropertyInDefaultValue() throws Exception
{
String name = "bar";
String value = "bar";
String defaultValue = "_${bar}_${bar}_";
String expectedValue = "_" + value + "_" + value + "_";
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
"<Configure class=\"org.eclipse.jetty.xml.DefaultTestConfiguration\">" +
" <Set name=\"first\"><Property name=\"not_found\" default=\"" + defaultValue + "\"/></Set> " +
"</Configure>");
xmlConfiguration.getProperties().put(name, value);
DefaultTestConfiguration config = (DefaultTestConfiguration)xmlConfiguration.configure();
assertEquals(expectedValue, config.getFirst());
}

@Test
public void testPropertyNotFoundWithPropertyInDefaultValueNotFoundWithDefault() throws Exception
{
String value = "bar";
XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
"<Configure class=\"org.eclipse.jetty.xml.DefaultTestConfiguration\">" +
" <Set name=\"first\"><Property name=\"not_found\" default=\"${not_found|" + value + "}\"/></Set> " +
"</Configure>");
DefaultTestConfiguration config = (DefaultTestConfiguration)xmlConfiguration.configure();
assertEquals(value, config.getFirst());
}
}

0 comments on commit 337e0bd

Please sign in to comment.