From 337e0bd8c91559d8caada47dd35a67a92fadfec0 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Tue, 14 Apr 2015 15:56:18 +0200 Subject: [PATCH] 464606 - Support property expansion in "default" attribute of Property. --- .../eclipse/jetty/xml/XmlConfiguration.java | 92 ++++++++++++------- .../jetty/xml/XmlConfigurationTest.java | 76 ++++++++++----- 2 files changed, 113 insertions(+), 55 deletions(-) diff --git a/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java b/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java index 3852c8635ec1..f5c404a79c13 100644 --- a/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java +++ b/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java @@ -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; @@ -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 __factoryLoader = ServiceLoader.load(ConfigurationProcessorFactory.class); private static final XmlParser __parser = initParser(); private static XmlParser initParser() @@ -629,7 +628,7 @@ private void put(Object obj, XmlParser.Node node) throws Exception Map map = (Map)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 + ")"); @@ -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; } @@ -891,7 +890,7 @@ private Object newMap(Object obj, XmlParser.Node node) throws Exception Map map = new HashMap<>(); if (id != null) - _configuration.getIdMap().put(id,map); + _configuration.getIdMap().put(id, map); for (Object o : node) { @@ -949,32 +948,12 @@ private Object propertyObj(XmlParser.Node node) throws Exception String defaultValue = node.getAttribute("default"); Object value = null; - boolean present = false; Map 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); @@ -985,6 +964,57 @@ private Object propertyObj(XmlParser.Node node) throws Exception return value; } + private String resolve(Map 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 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 diff --git a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java index c94f0069556b..1cc9a61c836c 100644 --- a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java +++ b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java @@ -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; @@ -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"; @@ -219,8 +219,8 @@ public void testStringConfiguration() throws Exception new XmlConfiguration("SetValue2"); 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 @@ -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 @@ -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) @@ -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) @@ -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 @@ -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) @@ -310,7 +310,7 @@ public void testNotSupportedLinkedListSetter() throws Exception XmlConfiguration xmlConfiguration = new XmlConfiguration("" + INT_ARRAY_XML + ""); 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); } @@ -320,9 +320,9 @@ public void testArrayListSetter() throws Exception XmlConfiguration xmlConfiguration = new XmlConfiguration("" + INT_ARRAY_XML + ""); 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 @@ -331,9 +331,9 @@ public void testSetSetter() throws Exception XmlConfiguration xmlConfiguration = new XmlConfiguration("" + STRING_ARRAY_XML + ""); 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 @@ -342,9 +342,9 @@ public void testSetSetterWithPrimitiveArray() throws Exception XmlConfiguration xmlConfiguration = new XmlConfiguration("" + INT_ARRAY_XML + ""); 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 @@ -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 @@ -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 @@ -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 @@ -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("" + + "" + + " " + + ""); + 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("" + + "" + + " " + + ""); + DefaultTestConfiguration config = (DefaultTestConfiguration)xmlConfiguration.configure(); + assertEquals(value, config.getFirst()); + } }