You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by oh...@apache.org on 2009/03/30 21:25:13 UTC
svn commit: r760116 - in
/commons/proper/configuration/branches/configuration2_experimental:
src/main/java/org/apache/commons/configuration2/
src/test/java/org/apache/commons/configuration2/ src/test/resources/ xdocs/
xdocs/userguide/
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>