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/28 21:27:11 UTC
svn commit: r759578 - in /commons/proper/configuration/trunk: conf/
src/java/org/apache/commons/configuration/
src/test/org/apache/commons/configuration/
Author: oheger
Date: Sat Mar 28 20:27:10 2009
New Revision: 759578
URL: http://svn.apache.org/viewvc?rev=759578&view=rev
Log:
CONFIGURATION-371: The separators for the properties are now stored by PropertiesConfigurationLayout. When saving the configuration they are restored.
Modified:
commons/proper/configuration/trunk/conf/test.properties
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfigurationLayout.java
commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java
commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfigurationLayout.java
Modified: commons/proper/configuration/trunk/conf/test.properties
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/conf/test.properties?rev=759578&r1=759577&r2=759578&view=diff
==============================================================================
--- commons/proper/configuration/trunk/conf/test.properties (original)
+++ commons/proper/configuration/trunk/conf/test.properties Sat Mar 28 20:27:10 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/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java?rev=759578&r1=759577&r2=759578&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfiguration.java Sat Mar 28 20:27:10 2009
@@ -177,6 +177,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.
@@ -602,6 +605,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;
@@ -741,6 +747,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
@@ -755,6 +774,7 @@
String[] property = doParseProperty(line);
initPropertyName(property[0]);
initPropertyValue(property[1]);
+ initPropertySeparator(property[2]);
}
/**
@@ -786,6 +806,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.
*
@@ -804,19 +838,20 @@
}
/**
- * 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
+ * @return an array with the property's key, value, and separator
*/
private static String[] doParseProperty(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];
+ String[] result = new String[3];
StringBuffer key = new StringBuffer();
StringBuffer value = new StringBuffer();
+ StringBuffer separator = new StringBuffer();
// state of the automaton:
// 0: key parsing
@@ -839,11 +874,13 @@
else if (ArrayUtils.contains(WHITE_SPACE, c))
{
// switch to the separator crossing state
+ separator.append(c);
state = 2;
}
else if (ArrayUtils.contains(SEPARATORS, c))
{
// switch to the value parsing state
+ separator.append(c);
state = 3;
}
else
@@ -872,19 +909,14 @@
break;
case 2:
- if (ArrayUtils.contains(WHITE_SPACE, c))
+ if (ArrayUtils.contains(WHITE_SPACE, c) || ArrayUtils.contains(SEPARATORS, c))
{
- // do nothing, eat all white spaces
- state = 2;
- }
- else if (ArrayUtils.contains(SEPARATORS, c))
- {
- // switch to the value parsing state
- state = 3;
+ // record the separator
+ separator.append(c);
}
else
{
- // any other character indicates we encoutered the beginning of the value
+ // any other character indicates we encountered the beginning of the value
value.append(c);
// switch to the value parsing state
@@ -901,19 +933,25 @@
result[0] = key.toString().trim();
result[1] = value.toString().trim();
+ result[2] = separator.toString();
return result;
}
} // 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;
+
/**
* Constructor.
*
@@ -927,6 +965,29 @@
}
/**
+ * 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;
+ }
+
+ /**
* Write a property.
*
* @param key the key of the property
@@ -991,7 +1052,7 @@
}
write(escapeKey(key));
- write(" = ");
+ write(fetchSeparator(key, value));
write(v);
writeln(null);
@@ -1108,6 +1169,24 @@
write(LINE_SEPARATOR);
}
+ /**
+ * 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 separator returned by <code>getCurrentSeparator()</code>
+ * is returned, 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 getCurrentSeparator();
+ }
} // class PropertiesWriter
/**
Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfigurationLayout.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfigurationLayout.java?rev=759578&r1=759577&r2=759578&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfigurationLayout.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PropertiesConfigurationLayout.java Sat Mar 28 20:27:10 2009
@@ -359,6 +359,39 @@
}
/**
+ * 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 a set with all property keys managed by this object.
*
* @return a set with all contained property keys
@@ -416,6 +449,7 @@
{
data.setComment(comment);
data.setBlancLines(blancLines);
+ data.setSeparator(reader.getPropertySeparator());
}
}
}
@@ -475,6 +509,7 @@
// Output the property and its value
boolean singleLine = (isForceSingleLine() || isSingleLine(key))
&& !getConfiguration().isDelimiterParsingDisabled();
+ writer.setCurrentSeparator(getSeparator(key));
writer.writeProperty(key, getConfiguration().getProperty(
key), singleLine);
}
@@ -738,6 +773,9 @@
/** Stores the comment for the property. */
private StringBuffer comment;
+ /** The separator to be used for this property. */
+ private String separator;
+
/** Stores the number of blanc lines before this property. */
private int blancLines;
@@ -750,6 +788,7 @@
public PropertyLayoutData()
{
singleLine = true;
+ separator = PropertiesConfiguration.DEFAULT_SEPARATOR;
}
/**
@@ -842,6 +881,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/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java?rev=759578&r1=759577&r2=759578&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java (original)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfiguration.java Sat Mar 28 20:27:10 2009
@@ -17,8 +17,10 @@
package org.apache.commons.configuration;
+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;
@@ -916,8 +920,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(
@@ -929,22 +934,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 foundLines = new HashSet();
+ 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
@@ -1123,8 +1158,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/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfigurationLayout.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfigurationLayout.java?rev=759578&r1=759577&r2=759578&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfigurationLayout.java (original)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestPropertiesConfigurationLayout.java Sat Mar 28 20:27:10 2009
@@ -21,10 +21,10 @@
import java.io.StringWriter;
import java.util.Iterator;
-import org.apache.commons.configuration.event.ConfigurationEvent;
-
import junit.framework.TestCase;
+import org.apache.commons.configuration.event.ConfigurationEvent;
+
/**
* Test class for PropertiesConfigurationLayout.
*
@@ -257,6 +257,7 @@
assertEquals("Blanc lines before new property", 0, layout
.getBlancLinesBefore(TEST_KEY));
assertTrue("No single line property", layout.isSingleLine(TEST_KEY));
+ assertEquals("Wrong separator", " = ", layout.getSeparator(TEST_KEY));
}
/**
@@ -578,7 +579,7 @@
}
/**
- * Tests if the copy and the original are independend from each other.
+ * Tests if the copy and the original are independent from each other.
*/
public void testInitCopyModify()
{
@@ -597,6 +598,16 @@
}
/**
+ * 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);
+ }
+
+ /**
* Helper method for filling the layout object with some properties.
*/
private void fillLayout()