From f84fdfa44367c63a6b7886ba0da889f5ce7cbee2 Mon Sep 17 00:00:00 2001 From: eeichinger Date: Sat, 21 Feb 2009 11:27:39 +0000 Subject: [PATCH] prepared support for SPRNET-1167 (Properties class now supports reading in null values) --- src/Spring/Spring.Core/Util/Properties.cs | 51 ++++++++++++++---- src/Spring/Spring.Core/Util/StringUtils.cs | 1 + .../VariablePlaceholderConfigurerTests.cs | 52 ++++++++++++++++++- .../Spring.Core.Tests/Util/PropertiesTests.cs | 17 +++++- 4 files changed, 108 insertions(+), 13 deletions(-) diff --git a/src/Spring/Spring.Core/Util/Properties.cs b/src/Spring/Spring.Core/Util/Properties.cs index c61b9725..3d466a0f 100644 --- a/src/Spring/Spring.Core/Util/Properties.cs +++ b/src/Spring/Spring.Core/Util/Properties.cs @@ -30,7 +30,25 @@ namespace Spring.Util { /// /// An implementation of the Java Properties class. - /// + /// + /// + /// For the complete syntax see java.util.Properties JavaDoc. + /// This class supports an extended syntax. There may also be sole keys on a line, in that case values are treated as null. + /// + /// + /// key1 = value + /// key2: + /// key3 + /// + /// will result in the name/value pairs: + /// + /// key1:="value" + /// key2:=string.Empty + /// key3:=<null> + /// + /// note, that to specify a null value, the key must not be followed by any character except newline. + /// + /// /// Simon White [Serializable] public class Properties : Hashtable @@ -122,7 +140,7 @@ namespace Spring.Util key = keyvalue[0]; value = keyvalue[1]; - if (value.EndsWith("\\")) + if (value != null && value.EndsWith("\\")) { value = value.Substring(0, value.Length - 1); isContinuation = true; @@ -155,8 +173,10 @@ namespace Spring.Util /// The string. /// The string with all leading whitespace removed. private static string RemoveLeadingWhitespace(string line) - { - string trimmed = null; + { + if (line == null) return null; + + string trimmed = string.Empty; for (int i = 0; i < line.Length; i++) { if (Whitespace.IndexOf(line[i]) == -1) @@ -175,7 +195,7 @@ namespace Spring.Util /// An array containing the key / value pair. private static string[] SplitLine(string line) { - string key = null; + string key = line; string value = null; int index = 0; @@ -202,14 +222,23 @@ namespace Spring.Util // first ignore leading whitespace and initial separator // (if one's there) index++; - if (index >= len) + if (index > len) { - return null; - } - value = line.Substring(index); - value = RemoveLeadingWhitespace(value); + // this is an extension to support key-only lines and specifying null values + value = null; + } + else if (index == len) + { + value = string.Empty; + } + else + { + value = line.Substring(index); + value = RemoveLeadingWhitespace(value); + } - if (Separators.IndexOf(value[0]) != -1) + if (value != null && value.Length > 0 + && Separators.IndexOf(value[0]) != -1) { value = value.Substring(1); value = RemoveLeadingWhitespace(value); diff --git a/src/Spring/Spring.Core/Util/StringUtils.cs b/src/Spring/Spring.Core/Util/StringUtils.cs index 29f89d73..74e741c4 100644 --- a/src/Spring/Spring.Core/Util/StringUtils.cs +++ b/src/Spring/Spring.Core/Util/StringUtils.cs @@ -672,6 +672,7 @@ namespace Spring.Util /// The converted string. public static string ConvertEscapedCharacters(string inputString) { + if (inputString == null) return null; StringBuilder sb = new StringBuilder(inputString.Length); for (int i = 0; i < inputString.Length; i++) { diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs index fe91ceb7..42b22904 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs @@ -20,6 +20,7 @@ #region Imports +using System; using System.Collections; using NUnit.Framework; using Spring.Context.Support; @@ -115,6 +116,55 @@ namespace Spring.Objects.Factory.Config TestObject tb1 = (TestObject)ac.GetObject("tb1"); Assert.AreEqual(35, tb1.Age); Assert.AreEqual("Erich", tb1.Name); - } + } + + [Test] + [Ignore("Does not work yet because IVariableSource cannot differentiate between invalid key and key with a null value")] + public void WhitespaceHandling() + { + StaticApplicationContext ac = new StaticApplicationContext(); + + MutablePropertyValues pvs = new MutablePropertyValues(); + pvs.Add("name", "${name}"); + pvs.Add("nickname", "${nickname}"); + ac.RegisterSingleton("tb1", typeof(TestObject), pvs); + + IList variableSources = new ArrayList(); + variableSources.Add(new DictionaryVariableSource(new string[] { "name", string.Empty, "nickname", null })); + pvs = new MutablePropertyValues(); + pvs.Add("VariableSources", variableSources); + ac.RegisterSingleton("configurer", typeof(VariablePlaceholderConfigurer), pvs); + ac.Refresh(); + + TestObject tb1 = (TestObject)ac.GetObject("tb1"); + Assert.AreEqual(string.Empty, tb1.Name); + Assert.AreEqual(null, tb1.Nickname); + } + + [Test] + public void BailsOnUnresolvableVariable() + { + StaticApplicationContext ac = new StaticApplicationContext(); + + MutablePropertyValues pvs = new MutablePropertyValues(); + pvs.Add("nickname", "${nickname}"); + ac.RegisterSingleton("tb1", typeof(TestObject), pvs); + + IList variableSources = new ArrayList(); + variableSources.Add(new DictionaryVariableSource(new string[] { })); + pvs = new MutablePropertyValues(); + pvs.Add("VariableSources", variableSources); + ac.RegisterSingleton("configurer", typeof(VariablePlaceholderConfigurer), pvs); + + try + { + ac.Refresh(); + Assert.Fail("something changed wrt VariablePlaceholder resolution"); + } + catch (ObjectDefinitionStoreException ex) + { + Assert.IsTrue( ex.Message.IndexOf("nickname") > -1 ); + } + } } } \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Util/PropertiesTests.cs b/test/Spring/Spring.Core.Tests/Util/PropertiesTests.cs index db78ba66..5e7eab27 100644 --- a/test/Spring/Spring.Core.Tests/Util/PropertiesTests.cs +++ b/test/Spring/Spring.Core.Tests/Util/PropertiesTests.cs @@ -101,7 +101,7 @@ namespace Spring.Util } [Test] - public void ListAndLoad () + public void ListAndLoad() { Properties props = new Properties(); props.Add ("foo", "this"); @@ -151,6 +151,21 @@ namespace Spring.Util Assert.IsTrue("true".Equals(props["leadingspace"])); } + [Test] + public void WhitespaceProperties() + { + string input = "key1 =\t\nkey2:\nkey3"; + + Stream s = new MemoryStream(Encoding.ASCII.GetBytes(input)); + Properties props = new Properties(); + props.Load(s); + + Assert.AreEqual(string.Empty, props["key1"], "key1 should have empty value"); + Assert.AreEqual(string.Empty, props["key2"], "key2 should have empty value"); + Assert.IsTrue(props.ContainsKey("key3")); + Assert.IsNull(props["key3"]); + } + [Test] public void Continuation() {