Author: oheger Date: Mon Mar 30 19:25:12 2009 New Revision: 760116 URL: http://svn.apache.org/viewvc?rev=760116&view=rev Log: CONFIGURATION-371, CONFIGURATION-314: Ported changes to configuration2 branch.
Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfiguration.java commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java commons/proper/configuration/branches/configuration2_experimental/src/test/resources/test.properties commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_properties.xml Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfiguration.java?rev=760116&r1=760115&r2=760116&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfiguration.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfiguration.java Mon Mar 30 19:25:12 2009 @@ -179,6 +179,9 @@ /** Constant for the supported comment characters.*/ static final String COMMENT_CHARS = "#!"; + /** Constant for the default properties separator.*/ + static final String DEFAULT_SEPARATOR = " = "; + /** * Constant for the default <code>IOFactory</code>. This instance is used * when no specific factory was set. @@ -600,7 +603,7 @@ { /** The regular expression to parse the key and the value of a property. */ private static final Pattern PROPERTY_PATTERN - = Pattern.compile("(([\\S&&[^\\\\" + new String(SEPARATORS) + "]]|\\\\.)*)\\s*(\\s+|[" + new String(SEPARATORS) +"])(.*)"); + = Pattern.compile("(([\\S&&[^\\\\" + new String(SEPARATORS) + "]]|\\\\.)*)(\\s*(\\s+|[" + new String(SEPARATORS) +"])\\s*)(.*)"); /** Stores the comment lines for the currently processed property.*/ private List<String> commentLines; @@ -611,6 +614,9 @@ /** Stores the value of the last read property.*/ private String propertyValue; + /** Stores the property separator of the last read property.*/ + private String propertySeparator = DEFAULT_SEPARATOR; + /** Stores the list delimiter character.*/ private char delimiter; @@ -750,6 +756,19 @@ } /** + * Returns the separator that was used for the last read property. The + * separator can be stored so that it can later be restored when saving + * the configuration. + * + * @return the separator for the last read property + * @since 1.7 + */ + public String getPropertySeparator() + { + return propertySeparator; + } + + /** * Parses a line read from the properties file. This method is called * for each non-comment line read from the source file. Its task is to * split the passed in line into the property key and its value. The @@ -764,6 +783,7 @@ String[] property = doParseProperty(line); initPropertyName(property[0]); initPropertyValue(property[1]); + initPropertySeparator(property[2]); } /** @@ -795,6 +815,20 @@ } /** + * Sets the separator of the current property. This method can be called + * by <code>parseProperty()</code>. It allows the associated layout + * object to keep track of the property separators. When saving the + * configuration the separators can be restored. + * + * @param value the separator used for the current property + * @since 1.7 + */ + protected void initPropertySeparator(String value) + { + propertySeparator = value; + } + + /** * Checks if the passed in line should be combined with the following. * This is true, if the line ends with an odd number of backslashes. * @@ -813,7 +847,7 @@ } /** - * Parse a property line and return the key and the value in an array. + * Parse a property line and return the key, the value, and the separator in an array. * * @param line the line to parse * @return an array with the property's key and value @@ -822,11 +856,12 @@ { Matcher matcher = PROPERTY_PATTERN.matcher(line); - String[] result = {"", ""}; + String[] result = {"", "", ""}; if (matcher.matches()) { result[0] = matcher.group(1).trim(); - result[1] = matcher.group(4).trim(); + result[1] = matcher.group(5).trim(); + result[2] = matcher.group(3); } return result; @@ -834,13 +869,24 @@ } // class PropertiesReader /** - * This class is used to write properties lines. + * This class is used to write properties lines. The most important method + * is <code>writeProperty(String, Object, boolean)</code>, which is called + * during a save operation for each property found in the configuration. */ public static class PropertiesWriter extends FilterWriter { /** The delimiter for multi-valued properties.*/ private char delimiter; + /** The separator to be used for the current property. */ + private String currentSeparator; + + /** The global separator. If set, it overrides the current separator.*/ + private String globalSeparator; + + /** The line separator.*/ + private String lineSeparator; + /** * Constructor. * @@ -854,6 +900,79 @@ } /** + * Returns the current property separator. + * + * @return the current property separator + * @since 1.7 + */ + public String getCurrentSeparator() + { + return currentSeparator; + } + + /** + * Sets the current property separator. This separator is used when + * writing the next property. + * + * @param currentSeparator the current property separator + * @since 1.7 + */ + public void setCurrentSeparator(String currentSeparator) + { + this.currentSeparator = currentSeparator; + } + + /** + * Returns the global property separator. + * + * @return the global property separator + * @since 1.7 + */ + public String getGlobalSeparator() + { + return globalSeparator; + } + + /** + * Sets the global property separator. This separator corresponds to the + * <code>globalSeparator</code> property of + * {...@link PropertiesConfigurationLayout}. It defines the separator to be + * used for all properties. If it is undefined, the current separator is + * used. + * + * @param globalSeparator the global property separator + * @since 1.7 + */ + public void setGlobalSeparator(String globalSeparator) + { + this.globalSeparator = globalSeparator; + } + + /** + * Returns the line separator. + * + * @return the line separator + * @since 1.7 + */ + public String getLineSeparator() + { + return (lineSeparator != null) ? lineSeparator : LINE_SEPARATOR; + } + + /** + * Sets the line separator. Each line written by this writer is + * terminated with this separator. If not set, the platform-specific + * line separator is used. + * + * @param lineSeparator the line separator to be used + * @since 1.7 + */ + public void setLineSeparator(String lineSeparator) + { + this.lineSeparator = lineSeparator; + } + + /** * Write a property. * * @param key the key of the property @@ -918,7 +1037,7 @@ } write(escapeKey(key)); - write(" = "); + write(fetchSeparator(key, value)); write(v); writeln(null); @@ -1032,9 +1151,29 @@ { write(s); } - write(LINE_SEPARATOR); + write(getLineSeparator()); } + /** + * Returns the separator to be used for the given property. This method + * is called by <code>writeProperty()</code>. The string returned here + * is used as separator between the property key and its value. Per + * default the method checks whether a global separator is set. If this + * is the case, it is returned. Otherwise the separator returned by + * <code>getCurrentSeparator()</code> is used, which was set by the + * associated layout object. Derived classes may implement a different + * strategy for defining the separator. + * + * @param key the property key + * @param value the value + * @return the separator to be used + * @since 1.7 + */ + protected String fetchSeparator(String key, Object value) + { + return (getGlobalSeparator() != null) ? getGlobalSeparator() + : getCurrentSeparator(); + } } // class PropertiesWriter /** Modified: commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java?rev=760116&r1=760115&r2=760116&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2/PropertiesConfigurationLayout.java Mon Mar 30 19:25:12 2009 @@ -102,7 +102,7 @@ * which has multiple values defined in one line using the separator character.</li> * <li>The <code>AppVendor</code> property appears twice. The comment lines * are concatenated, so that <code>layout.getComment("AppVendor");</code> will - * result in <code>Application vendor<CR>Another vendor</code>, whith + * result in <code>Application vendor<CR>Another vendor</code>, with * <code><CR></code> meaning the line separator. In addition the * "single line" flag is set to <b>false</b> for this property. When * the file is saved, two property definitions will be written (in series).</li> @@ -118,7 +118,7 @@ public class PropertiesConfigurationLayout implements ConfigurationListener { /** Constant for the line break character. */ - private static final String CR = System.getProperty("line.separator"); + private static final String CR = "\n"; /** Constant for the default comment prefix. */ private static final String COMMENT_PREFIX = "# "; @@ -132,6 +132,12 @@ /** Stores the header comment. */ private String headerComment; + /** The global separator that will be used for all properties. */ + private String globalSeparator; + + /** The line separator.*/ + private String lineSeparator; + /** A counter for determining nested load calls. */ private int loadCounter; @@ -359,6 +365,93 @@ } /** + * Returns the separator for the property with the given key. + * + * @param key the property key + * @return the property separator for this property + * @since 1.7 + */ + public String getSeparator(String key) + { + return fetchLayoutData(key).getSeparator(); + } + + /** + * Sets the separator to be used for the property with the given key. The + * separator is the string between the property key and its value. For new + * properties " = " is used. When a properties file is read, the + * layout tries to determine the separator for each property. With this + * method the separator can be changed. To be compatible with the properties + * format only the characters <code>=</code> and <code>:</code> (with or + * without whitespace) should be used, but this method does not enforce this + * - it accepts arbitrary strings. If the key refers to a property with + * multiple values that are written on multiple lines, this separator will + * be used on all lines. + * + * @param key the key for the property + * @param sep the separator to be used for this property + * @since 1.7 + */ + public void setSeparator(String key, String sep) + { + fetchLayoutData(key).setSeparator(sep); + } + + /** + * Returns the global separator. + * + * @return the global properties separator + * @since 1.7 + */ + public String getGlobalSeparator() + { + return globalSeparator; + } + + /** + * Sets the global separator for properties. With this method a separator + * can be set that will be used for all properties when writing the + * configuration. This is an easy way of determining the properties + * separator globally. To be compatible with the properties format only the + * characters <code>=</code> and <code>:</code> (with or without whitespace) + * should be used, but this method does not enforce this - it accepts + * arbitrary strings. If the global separator is set to <b>null</b>, + * property separators are not changed. This is the default behavior as it + * produces results that are closer to the original properties file. + * + * @param globalSeparator the separator to be used for all properties + * @since 1.7 + */ + public void setGlobalSeparator(String globalSeparator) + { + this.globalSeparator = globalSeparator; + } + + /** + * Returns the line separator. + * + * @return the line separator + * @since 1.7 + */ + public String getLineSeparator() + { + return lineSeparator; + } + + /** + * Sets the line separator. When writing the properties configuration, all + * lines are terminated with this separator. If no separator was set, the + * platform-specific default line separator is used. + * + * @param lineSeparator the line separator + * @since 1.7 + */ + public void setLineSeparator(String lineSeparator) + { + this.lineSeparator = lineSeparator; + } + + /** * Returns a set with all property keys managed by this object. * * @return a set with all contained property keys @@ -416,6 +509,7 @@ { data.setComment(comment); data.setBlancLines(blancLines); + data.setSeparator(reader.getPropertySeparator()); } } } @@ -448,9 +542,15 @@ : getConfiguration().getListDelimiter(); PropertiesConfiguration.PropertiesWriter writer = getConfiguration() .getIOFactory().createPropertiesWriter(out, delimiter); + writer.setGlobalSeparator(getGlobalSeparator()); + if (getLineSeparator() != null) + { + writer.setLineSeparator(getLineSeparator()); + } + if (headerComment != null) { - writer.writeln(getCanonicalHeaderComment(true)); + writeComment(writer, getCanonicalHeaderComment(true)); writer.writeln(null); } @@ -466,14 +566,12 @@ } // Output the comment - if (getComment(key) != null) - { - writer.writeln(getCanonicalComment(key, true)); - } + writeComment(writer, getCanonicalComment(key, true)); // Output the property and its value boolean singleLine = (isForceSingleLine() || isSingleLine(key)) && !getConfiguration().isDelimiterParsingDisabled(); + writer.setCurrentSeparator(getSeparator(key)); writer.writeProperty(key, getConfiguration().getProperty( key), singleLine); } @@ -728,6 +826,25 @@ } /** + * Helper method for writing a comment line. This method ensures that the + * correct line separator is used if the comment spans multiple lines. + * + * @param writer the writer + * @param comment the comment to write + * @throws IOException if an IO error occurs + */ + private static void writeComment( + PropertiesConfiguration.PropertiesWriter writer, String comment) + throws IOException + { + if (comment != null) + { + writer.writeln(StringUtils.replace(comment, CR, writer + .getLineSeparator())); + } + } + + /** * A helper class for storing all layout related information for a * configuration property. */ @@ -736,6 +853,9 @@ /** Stores the comment for the property. */ private StringBuilder comment; + /** The separator to be used for this property. */ + private String separator; + /** Stores the number of blanc lines before this property. */ private int blancLines; @@ -748,6 +868,7 @@ public PropertyLayoutData() { singleLine = true; + separator = PropertiesConfiguration.DEFAULT_SEPARATOR; } /** @@ -840,6 +961,26 @@ } /** + * Returns the separator that was used for this property. + * + * @return the property separator + */ + public String getSeparator() + { + return separator; + } + + /** + * Sets the separator to be used for the represented property. + * + * @param separator the property separator + */ + public void setSeparator(String separator) + { + this.separator = separator; + } + + /** * Creates a copy of this object. * * @return the copy Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java?rev=760116&r1=760115&r2=760116&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java Mon Mar 30 19:25:12 2009 @@ -17,8 +17,10 @@ package org.apache.commons.configuration2; +import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; @@ -33,8 +35,10 @@ import java.net.URLConnection; import java.net.URLStreamHandler; import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import junit.framework.TestCase; @@ -913,8 +917,9 @@ /** * Tests setting an IOFactory that uses a specialized writer. */ - public void testSetIOFactoryWriter() throws ConfigurationException + public void testSetIOFactoryWriter() throws ConfigurationException, IOException { + final PropertiesWriterTestImpl testWriter = new PropertiesWriterTestImpl(','); conf.setIOFactory(new PropertiesConfiguration.IOFactory() { public PropertiesConfiguration.PropertiesReader createPropertiesReader( @@ -926,22 +931,52 @@ public PropertiesConfiguration.PropertiesWriter createPropertiesWriter( Writer out, char delimiter) { - try - { - return new PropertiesWriterTestImpl(out, delimiter); - } - catch (IOException ioex) - { - fail("Unexpected exception: " + ioex); - return null; - } + return testWriter; } }); conf.save(new StringWriter()); + testWriter.close(); checkSavedConfig(); } /** + * Tests that the property separators are retained when saving the + * configuration. + */ + public void testKeepSeparators() throws ConfigurationException, IOException + { + conf.save(testSavePropertiesFile); + final String[] separatorTests = { + "test.separator.equal = foo", "test.separator.colon : foo", + "test.separator.tab\tfoo", "test.separator.whitespace foo", + "test.separator.no.space=foo" + }; + Set<String> foundLines = new HashSet<String>(); + BufferedReader in = new BufferedReader(new FileReader( + testSavePropertiesFile)); + try + { + String s; + while ((s = in.readLine()) != null) + { + for (int i = 0; i < separatorTests.length; i++) + { + if (separatorTests[i].equals(s)) + { + foundLines.add(s); + } + } + } + } + finally + { + in.close(); + } + assertEquals("No all separators were found: " + foundLines, + separatorTests.length, foundLines.size()); + } + + /** * Creates a configuration that can be used for testing copy operations. * * @return the configuration to be copied @@ -1130,8 +1165,7 @@ private static class PropertiesWriterTestImpl extends PropertiesConfiguration.PropertiesWriter { - public PropertiesWriterTestImpl(Writer writer, char delimiter) - throws IOException + public PropertiesWriterTestImpl(char delimiter) throws IOException { super(new FileWriter(testSavePropertiesFile), delimiter); } Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java?rev=760116&r1=760115&r2=760116&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2/TestPropertiesConfigurationLayout.java Mon Mar 30 19:25:12 2009 @@ -36,7 +36,10 @@ public class TestPropertiesConfigurationLayout extends TestCase { /** Constant for the line break character. */ - static final String CR = System.getProperty("line.separator"); + private static final String CR = System.getProperty("line.separator"); + + /** Constant for the normalized line break character. */ + private static final String CRNORM = "\n"; /** Constant for a test property key. */ static final String TEST_KEY = "myProperty"; @@ -138,7 +141,7 @@ layout.load(builder.getReader()); assertEquals("Wrong number of blanc lines", 2, layout .getBlancLinesBefore(TEST_KEY)); - assertEquals("Wrong comment", TEST_COMMENT + CR, layout + assertEquals("Wrong comment", TEST_COMMENT + CRNORM, layout .getCanonicalComment(TEST_KEY, false)); assertEquals("Wrong property value", TEST_VALUE, config .getString(TEST_KEY)); @@ -182,7 +185,7 @@ builder.addProperty(TEST_KEY, TEST_VALUE + "2"); layout.load(builder.getReader()); assertEquals("Wrong combined comment", - TEST_COMMENT + CR + TEST_COMMENT, layout.getCanonicalComment( + TEST_COMMENT + CRNORM + TEST_COMMENT, layout.getCanonicalComment( TEST_KEY, false)); assertEquals("Wrong combined blanc numbers", 0, layout .getBlancLinesBefore(TEST_KEY)); @@ -214,7 +217,7 @@ builder.addComment(null); builder.addProperty(TEST_KEY, TEST_VALUE); layout.load(builder.getReader()); - assertEquals("Wrong header comment", TEST_COMMENT + CR + CR + assertEquals("Wrong header comment", TEST_COMMENT + CRNORM + CRNORM + TEST_COMMENT, layout.getCanonicalHeaderComment(false)); assertNull("Wrong comment for property", layout.getComment(TEST_KEY)); } @@ -233,7 +236,7 @@ builder.addComment(TEST_COMMENT); builder.addProperty(TEST_KEY, TEST_VALUE); layout.load(builder.getReader()); - assertEquals("Wrong header comment", TEST_COMMENT + CR + CR + assertEquals("Wrong header comment", TEST_COMMENT + CRNORM + CRNORM + TEST_COMMENT, layout.getCanonicalHeaderComment(false)); assertEquals("Wrong comment for property", TEST_COMMENT, layout .getCanonicalComment(TEST_KEY, false)); @@ -422,9 +425,9 @@ .getCanonicalHeaderComment(false)); assertFalse("Include property was stored", layout.getKeys().contains( PropertiesConfiguration.getInclude())); - assertEquals("Wrong comment for property", TEST_COMMENT + CR - + "A nested header comment." + CR + "With multiple lines" + CR - + CR + "Second comment", layout.getCanonicalComment(TEST_KEY, + assertEquals("Wrong comment for property", TEST_COMMENT + CRNORM + + "A nested header comment." + CRNORM + "With multiple lines" + CRNORM + + CRNORM + "Second comment", layout.getCanonicalComment(TEST_KEY, false)); } @@ -460,7 +463,7 @@ layout.setComment("AnotherProperty", "AnotherComment"); layout.setBlancLinesBefore("AnotherProperty", 2); layout.setSingleLine("AnotherProperty", true); - layout.setHeaderComment("A header comment" + CR + "for my properties"); + layout.setHeaderComment("A header comment" + CRNORM + "for my properties"); checkLayoutString("# A header comment" + CR + "# for my properties" + CR + CR + "# " + TEST_COMMENT + CR + TEST_KEY + " = " + TEST_VALUE + CR + TEST_KEY + " = " + TEST_VALUE + "2" + CR @@ -616,6 +619,62 @@ } /** + * Tests changing the separator for a property. + */ + public void testSetSeparator() throws ConfigurationException + { + config.addProperty(TEST_KEY, TEST_VALUE); + layout.setSeparator(TEST_KEY, ":"); + checkLayoutString(TEST_KEY + ":" + TEST_VALUE + CR); + } + + /** + * Tests setting the global separator. This separator should override the + * separators for all properties. + */ + public void testSetGlobalSeparator() throws ConfigurationException + { + final String sep = "="; + config.addProperty(TEST_KEY, TEST_VALUE); + config.addProperty("key2", "value2"); + layout.setSeparator(TEST_KEY, " : "); + layout.setGlobalSeparator(sep); + checkLayoutString(TEST_KEY + sep + TEST_VALUE + CR + "key2" + sep + + "value2" + CR); + } + + /** + * Tests setting the line separator. + */ + public void testSetLineSeparator() throws ConfigurationException + { + final String lf = CR + CR; + config.addProperty(TEST_KEY, TEST_VALUE); + layout.setBlancLinesBefore(TEST_KEY, 2); + layout.setComment(TEST_KEY, TEST_COMMENT); + layout.setHeaderComment("Header comment"); + layout.setLineSeparator(lf); + checkLayoutString("# Header comment" + lf + lf + lf + lf + "# " + + TEST_COMMENT + lf + TEST_KEY + " = " + TEST_VALUE + lf); + } + + /** + * Tests whether the line separator is also taken into account within + * comments. + */ + public void testSetLineSeparatorInComments() throws ConfigurationException + { + final String lf = "<-\n"; + config.addProperty(TEST_KEY, TEST_VALUE); + layout.setComment(TEST_KEY, TEST_COMMENT + "\nMore comment"); + layout.setHeaderComment("Header\ncomment"); + layout.setLineSeparator(lf); + checkLayoutString("# Header" + lf + "# comment" + lf + lf + "# " + + TEST_COMMENT + lf + "# More comment" + lf + TEST_KEY + " = " + + TEST_VALUE + lf); + } + + /** * Helper method for filling the layout object with some properties. */ private void fillLayout() @@ -722,6 +781,7 @@ * * @return the buffer as string */ + @Override public String toString() { return buf.toString(); @@ -741,6 +801,7 @@ * Simulates the propertyLoaded() callback. If a builder was set, a * load() call on the layout is invoked. */ + @Override boolean propertyLoaded(String key, String value) throws ConfigurationException { Modified: commons/proper/configuration/branches/configuration2_experimental/src/test/resources/test.properties URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/src/test/resources/test.properties?rev=760116&r1=760115&r2=760116&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/src/test/resources/test.properties (original) +++ commons/proper/configuration/branches/configuration2_experimental/src/test/resources/test.properties Mon Mar 30 19:25:12 2009 @@ -100,3 +100,5 @@ test.separator.tab foo test.separator.formfeedfoo test.separator.whitespace foo +test.separator.no.space=foo + Modified: commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml?rev=760116&r1=760115&r2=760116&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml (original) +++ commons/proper/configuration/branches/configuration2_experimental/xdocs/changes.xml Mon Mar 30 19:25:12 2009 @@ -89,7 +89,17 @@ File system access has been abstracted to a FileSystem interface. Two implementations are provided, DefaultFileSystem that behaves in a backward compatible manner and VFSFileSystem which uses Commons VFS to retreive and store files. - </action> + </action> + <action dev="oheger" type="add" issue="CONFIGURATION-314"> + PropertiesConfigurationLayout now allows setting the line separator to + be used when writing the properties file. + </action> + <action dev="oheger" type="add" issue="CONFIGURATION-371"> + PropertiesConfigurationLayout now also stores the property separators used for + the single properties. It is also possible to change them for specific + properties or set a global properties separator. In earlier versions + the separator was hard-coded to " = ". + </action> <action dev="oheger" type="add" issue="CONFIGURATION-370"> PropertiesConfiguration now defines a nested interface IOFactory. Using this interface it is possible to inject custom PropertiesReader and Modified: commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_properties.xml URL: http://svn.apache.org/viewvc/commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_properties.xml?rev=760116&r1=760115&r2=760116&view=diff ============================================================================== --- commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_properties.xml (original) +++ commons/proper/configuration/branches/configuration2_experimental/xdocs/userguide/howto_properties.xml Mon Mar 30 19:25:12 2009 @@ -197,14 +197,58 @@ </p> <p> Normally a developer does not have to deal with these layout objects. - However there are some methods that might be of interest in certain use - cases. For instance <code>PropertiesConfigurationLayout</code> defines - methods for obtaining and setting the comment for a property key. A - header comment for the whole properties file is also supported. If the - values of multi-valued properties should always be written on a - single line rather than adding a new property definition for each value - (which would be incompatible with <code>java.util.Properties</code>) - the <code>setForceSingleLine()</code> method can be used. + However, there are some methods that might be of interest if enhanced + control over the output of properties files is needed. The following + list describes these methods (note that corresponding get methods are + of course also provided): + <ul> + <li><code>setComment()</code><br/> + With this method a comment can be set for a specified property. When + storing the configuration the comment is output before the property, + followed by a line break. The comment can span multiple lines; in this + case the newline character "\n" must be used as line + separator.</li> + <li><code>setHeaderComment()</code><br/> + With <code>setHeaderComment()</code> a global comment can be set for the + properties file. This comment is written at the very start of the file, + followed by an empty line.</li> + <li><code>setBlancLinesBefore()</code><br/> + This methods allows defining the number of empty lines to be written + before the specified property. It can be used, for instance, for + deviding the properties file into multiple logic sections.</li> + <li><code>setSingleLine()</code><br/> + If a property has multiple values, with <code>setSingleLine()</code> it + can be specified that all these values should be written into a single + line separated by the default list separator. It is also possible to + write multiple definitions for this property (i.e. multiple lines of the + form <code>property = value1</code>, <code>property = value2</code> etc.). + This is supported by <code>PropertiesConfiguration</code>, but will + probably not work when processing the properties file with other tools. + </li> + <li><code>setForceSingleLine()</code><br/> + This is similar to <code>setSingleLine()</code>, but sets a global + single line flag. If set to <b>true</b>, all properties with multiple + values are always written on a single line.</li> + <li><code>setGlobalSeparator()</code><br/> + Sometimes it may be necessary to define the properties separator, i.e. + the string that separates the property key from the value. This can be + done using <code>setGlobalSeparator()</code>. Here an arbitrary string + can be specified that will be used as separator. (Note: In order to + produce valid properties files only the characters <code>=</code> and + <code>:</code> should be used as separators (with or without leading or + trailing whitespace), but the method does not enforce this.</li> + <li><code>setSeparator()</code><br/> + This method is similar to <code>setGlobalSeparator()</code>, but + allows setting the property separator for a specific property.</li> + <li><code>setLineSeparator()</code><br/> + Using this method the line separator can be specified. Per default the + platform-specific line separator is used (e.g. <code>\n</code> on unix). + </li> + </ul> + The default settings of <code>PropertiesConfigurationLayout</code> are + chosen in a way that most of the original layout of a properties file + is retained. With the methods listed above specific layout restrictions + can be enforced. </p> </subsection>