Author: ebourg
Date: Wed Jul 27 07:12:59 2005 New Revision: 225522 URL: http://svn.apache.org/viewcvs?rev=225522&view=rev Log: PropertiesConfiguration now supports all key/value separators supported by java.util.Properties (Bug 29171) PropertiesConfiguration now supports escaped key/value separators in the keys (Bug 29192). Updated the dependency on Commons Lang (2.1 instead of 2.0) Modified: jakarta/commons/proper/configuration/trunk/conf/test.properties jakarta/commons/proper/configuration/trunk/project.xml jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java jakarta/commons/proper/configuration/trunk/xdocs/changes.xml Modified: jakarta/commons/proper/configuration/trunk/conf/test.properties URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/conf/test.properties?rev=225522&r1=225521&r2=225522&view=diff ============================================================================== --- jakarta/commons/proper/configuration/trunk/conf/test.properties (original) +++ jakarta/commons/proper/configuration/trunk/conf/test.properties Wed Jul 27 07:12:59 2005 @@ -75,6 +75,25 @@ test.path = C:\\path3\\\ complex\\test\\ +# +# Test for the comment lines +# #comment = this is not a property but a comment line starting with '#' !comment = this is not a property but a comment line starting with '!' + +# +# Tests for the key/value separators ('=', ':' or white space, escaped or not) +# + +test.separator\=in.key = foo +test.separator\:in.key = bar +test.separator\ in.key = foo +test.separator\in.key = bar +test.separator\ in.key = foo + +test.separator.equal = foo +test.separator.colon : foo +test.separator.tab foo +test.separator.formfeedfoo +test.separator.whitespace foo Modified: jakarta/commons/proper/configuration/trunk/project.xml URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/project.xml?rev=225522&r1=225521&r2=225522&view=diff ============================================================================== --- jakarta/commons/proper/configuration/trunk/project.xml (original) +++ jakarta/commons/proper/configuration/trunk/project.xml Wed Jul 27 07:12:59 2005 @@ -209,7 +209,7 @@ <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> - <version>2.0</version> + <version>2.1</version> <properties> <war.bundle>true</war.bundle> </properties> Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java?rev=225522&r1=225521&r2=225522&view=diff ============================================================================== --- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java (original) +++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java Wed Jul 27 07:12:59 2005 @@ -29,6 +29,7 @@ import java.util.Iterator; import java.util.List; +import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; @@ -42,14 +43,24 @@ * added and later saved. include statements are (obviously) not supported * if you don't construct a PropertyConfiguration from a file. * - * <p>The properties file syntax is explained here: + * <p>The properties file syntax is explained here, basically it follows + * the syntax of the stream parsed by {@link java.util.Properties#load} and + * adds several useful extensions: * * <ul> * <li> - * Each property has the syntax <code>key = value</code> + * Each property has the syntax <code>key <separator> value</code>. The + * separators accepted are <code>'='</code>, <code>':'</code> and any white + * space character. Examples: + * <pre> + * key1 = value1 + * key2 : value2 + * key3 value3</pre> * </li> * <li> - * The <i>key</i> may use any character but the equal sign '='. + * The <i>key</i> may use any character, separators must be escaped: + * <pre> + * key\:foo = bar</pre> * </li> * <li> * <i>value</i> may be separated on different lines if a backslash @@ -108,7 +119,7 @@ * tokens_on_multiple_lines = second token * * # commas may be escaped in tokens - * commas.excaped = Hi\, what'up? + * commas.escaped = Hi\, what'up? * * # properties can reference other properties * base.prop = /base @@ -116,7 +127,8 @@ * second.prop = ${first.prop}/second * </pre> * - * @author <a href="mailto:[hidden email]">Emmanuel Bourg</a> + * @see java.util.Properties#load + * * @author <a href="mailto:[hidden email]">Stefano Mazzocchi</a> * @author <a href="mailto:[hidden email]">Jon S. Stevens</a> * @author <a href="mailto:daveb@miceda-data">Dave Bryson</a> @@ -130,10 +142,17 @@ * @author <a href="mailto:[hidden email]">Henning P. Schmiedehausen</a> * @author <a href="mailto:[hidden email]">Eric Pugh</a> * @author <a href="mailto:[hidden email]">Oliver Heger</a> + * @author <a href="mailto:[hidden email]">Emmanuel Bourg</a> * @version $Id$ */ public class PropertiesConfiguration extends AbstractFileConfiguration { + /** The list of possible key/value separators */ + private static final char[] SEPARATORS = new char[] { '=', ':' }; + + /** The white space characters used as key/value separators. */ + private static final char[] WHITE_SPACE = new char[] { ' ', '\t', '\f' }; + /** * This is the name of the property that can point to other * properties file for including other properties files. @@ -286,34 +305,32 @@ break; // EOF } - int equalSign = line.indexOf('='); - if (equalSign > 0) - { - String key = line.substring(0, equalSign).trim(); - String value = line.substring(equalSign + 1).trim(); - - // Though some software (e.g. autoconf) may produce - // empty values like foo=\n, emulate the behavior of - // java.util.Properties by setting the value to the - // empty string. + // parse the line + String[] property = parseProperty(line); + String key = property[0]; + String value = property[1]; + + // Though some software (e.g. autoconf) may produce + // empty values like foo=\n, emulate the behavior of + // java.util.Properties by setting the value to the + // empty string. - if (StringUtils.isNotEmpty(getInclude()) - && key.equalsIgnoreCase(getInclude())) + if (StringUtils.isNotEmpty(getInclude()) && key.equalsIgnoreCase(getInclude())) + { + if (getIncludesAllowed()) { - if (getIncludesAllowed()) + String [] files = StringUtils.split(value, getDelimiter()); + for (int i = 0; i < files.length; i++) { - String [] files = StringUtils.split(value, getDelimiter()); - for (int i = 0; i < files.length; i++) - { - load(ConfigurationUtils.locate(getBasePath(), files[i].trim())); - } + load(ConfigurationUtils.locate(getBasePath(), files[i].trim())); } } - else - { - addProperty(key, unescapeJava(value, getDelimiter())); - } } + else + { + addProperty(key, unescapeJava(value, getDelimiter())); + } + } } catch (IOException ioe) @@ -498,7 +515,7 @@ */ public void writeProperty(String key, Object value) throws IOException { - write(key); + write(escapeKey(key)); write(" = "); if (value != null) { @@ -534,6 +551,33 @@ { write("# " + comment + "\n"); } + + /** + * Escape the separators in the key. + */ + private String escapeKey(String key) + { + StringBuffer newkey = new StringBuffer(); + + for (int i = 0; i < key.length(); i++) + { + char c = key.charAt(i); + + if (ArrayUtils.contains(SEPARATORS, c) || ArrayUtils.contains(WHITE_SPACE, c)) + { + // escape the separator + newkey.append('\\'); + newkey.append(c); + } + else + { + newkey.append(c); + } + } + + return newkey.toString(); + } + } // class PropertiesWriter /** @@ -644,6 +688,104 @@ } return out.toString(); + } + + /** + * Parse a property line and return the key and the value in an array. + */ + private String[] parseProperty(String line) + { + // sorry for this spaghetti code, please replace it as soon as + // possible with a regexp when the Java 1.3 requirement is dropped + + String[] result = new String[2]; + StringBuffer key = new StringBuffer(); + StringBuffer value = new StringBuffer(); + + // state of the automaton: + // 0: key parsing + // 1: antislash found while parsing the key + // 2: separator crossing + // 3: value parsing + int state = 0; + + for (int pos = 0; pos < line.length(); pos++) + { + char c = line.charAt(pos); + + switch (state) + { + case 0: + if (c == '\\') + { + state = 1; + } + else if (ArrayUtils.contains(WHITE_SPACE, c)) + { + // switch to the separator crossing state + state = 2; + } + else if (ArrayUtils.contains(SEPARATORS, c)) + { + // switch to the value parsing state + state = 3; + } + else + { + key.append(c); + } + + break; + + case 1: + if (ArrayUtils.contains(SEPARATORS, c) || ArrayUtils.contains(WHITE_SPACE, c)) + { + // this is an escaped separator or white space + key.append(c); + } + else + { + // another escaped character, the '\' is preserved + key.append('\\'); + key.append(c); + } + + // return to the key parsing state + state = 0; + + break; + + case 2: + if (ArrayUtils.contains(WHITE_SPACE, c)) + { + // do nothing, eat all white spaces + } + else if (ArrayUtils.contains(SEPARATORS, c)) + { + // switch to the value parsing state + state = 3; + } + else + { + // any other character indicates we encoutered the beginning of the value + value.append(c); + + // switch to the value parsing state + state = 3; + } + + break; + + case 3: + value.append(c); + break; + } + } + + result[0] = key.toString().trim(); + result[1] = value.toString().trim(); + + return result; } } Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java?rev=225522&r1=225521&r2=225522&view=diff ============================================================================== --- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java (original) +++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java Wed Jul 27 07:12:59 2005 @@ -371,4 +371,27 @@ assertFalse("comment line starting with '#' parsed as a property", conf.containsKey("#comment")); assertFalse("comment line starting with '!' parsed as a property", conf.containsKey("!comment")); } + + /** + * Check that key/value separators can be part of a key. + */ + public void testEscapedKeyValueSeparator() + { + assertEquals("Escaped separator '=' not supported in keys", "foo", conf.getProperty("test.separator=in.key")); + assertEquals("Escaped separator ':' not supported in keys", "bar", conf.getProperty("test.separator:in.key")); + assertEquals("Escaped separator '\\t' not supported in keys", "foo", conf.getProperty("test.separator\tin.key")); + assertEquals("Escaped separator '\\f' not supported in keys", "bar", conf.getProperty("test.separator\fin.key")); + assertEquals("Escaped separator ' ' not supported in keys" , "foo", conf.getProperty("test.separator in.key")); + } + + /** + * Test all acceptable key/value separators ('=', ':' or white spaces). + */ + public void testKeyValueSeparators() { + assertEquals("equal separator not properly parsed", "foo", conf.getProperty("test.separator.equal")); + assertEquals("colon separator not properly parsed", "foo", conf.getProperty("test.separator.colon")); + assertEquals("tab separator not properly parsed", "foo", conf.getProperty("test.separator.tab")); + assertEquals("formfeed separator not properly parsed", "foo", conf.getProperty("test.separator.formfeed")); + assertEquals("whitespace separator not properly parsed", "foo", conf.getProperty("test.separator.whitespace")); + } } Modified: jakarta/commons/proper/configuration/trunk/xdocs/changes.xml URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/xdocs/changes.xml?rev=225522&r1=225521&r2=225522&view=diff ============================================================================== --- jakarta/commons/proper/configuration/trunk/xdocs/changes.xml (original) +++ jakarta/commons/proper/configuration/trunk/xdocs/changes.xml Wed Jul 27 07:12:59 2005 @@ -23,6 +23,17 @@ <body> <release version="1.2-dev" date="in SVN"> + <action dev="ebourg" type="add" issue="29192"> + PropertiesConfiguration now supports escaped key/value separators in the keys + (i.e foo\:key = bar). + </action> + <action dev="ebourg" type="add" issue="29171"> + PropertiesConfiguration now supports all key/value separators supported by java.util.Properties + ('=', ':' and white space characters). + </action> + <action dev="ebourg" type="update"> + Commons Configuration now depends on Commons Lang 2.1 instead of 2.0 + </action> <action dev="ebourg" type="update" issue="35888"> Comment lines for PropertiesConfiguration can start with the '!' char (compatibility with java.util.Properties) </action> --------------------------------------------------------------------- To unsubscribe, e-mail: [hidden email] For additional commands, e-mail: [hidden email] |
Free forum by Nabble | Edit this page |