This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-configuration.git
The following commit(s) were added to refs/heads/master by this push: new f9e8b41 [CONFIGURATION-731] Allow user to specify the comments & separator chars. f9e8b41 is described below commit f9e8b415cf9d3cf34cd911eac9d89c955fdd2785 Author: Gary Gregory <ggreg...@rocketsoftware.com> AuthorDate: Thu Feb 28 10:01:50 2019 -0500 [CONFIGURATION-731] Allow user to specify the comments & separator chars. Apply a different version of the patch that does not break compatibility by using Java 8 default methods. --- src/changes/changes.xml | 6 ++ .../commons/configuration2/INIConfiguration.java | 118 ++++++++++++++++++--- .../builder/INIBuilderParametersImpl.java | 18 ++++ .../builder/INIBuilderProperties.java | 34 +++++- .../configuration2/TestINIConfiguration.java | 52 +++++++++ 5 files changed, 212 insertions(+), 16 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 1cad9bd..ffe6c27 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -25,6 +25,12 @@ </properties> <body> + <release version="2.5" date="2019-MM-DD" + description="Minor release with new features and updated dependencies."> + <action dev="ggregory" type="fix" issue="CONFIGURATION-731" due-to="Shuai Zhang, Gary Gregory"> + Allow user to specify the comments & separator chars. + </action> + </release> <release version="2.4" date="2018-10-23" description="Minor release with new features and updated dependencies."> <action dev="oheger" type="fix" issue="CONFIGURATION-710" due-to="thc202"> diff --git a/src/main/java/org/apache/commons/configuration2/INIConfiguration.java b/src/main/java/org/apache/commons/configuration2/INIConfiguration.java index c343245..af62d66 100644 --- a/src/main/java/org/apache/commons/configuration2/INIConfiguration.java +++ b/src/main/java/org/apache/commons/configuration2/INIConfiguration.java @@ -227,12 +227,12 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements FileBasedConfiguration { /** - * The characters that signal the start of a comment line. + * The default characters that signal the start of a comment line. */ protected static final String COMMENT_CHARS = "#;"; /** - * The characters used to separate keys from values. + * The default characters used to separate keys from values. */ protected static final String SEPARATOR_CHARS = "=:"; @@ -257,6 +257,17 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements private String separatorUsedInOutput = " = "; /** + * The separator used when reading an INI file. + */ + private String separatorUsedInInput = SEPARATOR_CHARS; + + /** + * The characters used to separate keys from values + * when reading an INI file. + */ + private String commentCharsUsedInInput = COMMENT_CHARS; + + /** * Create a new empty INI Configuration. */ public INIConfiguration() @@ -317,6 +328,86 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements } /** + * Get separator used in INI reading. see {@code setSeparatorUsedInInput} + * for further explanation + * + * @return the current separator for reading the INI input + * @since 2.5 + */ + public String getSeparatorUsedInInput() + { + beginRead(false); + try + { + return separatorUsedInInput; + } + finally + { + endRead(); + } + } + + /** + * Allows setting the key and value separator which is used in reading + * an INI file + * + * @param separator String of the new separator for INI reading + * @since 2.5 + */ + public void setSeparatorUsedInInput(final String separator) + { + beginRead(false); + try + { + this.separatorUsedInInput = separator; + } + finally + { + endRead(); + } + } + + /** + * Get comment leading separator used in INI reading. + * see {@code setCommentLeadingCharsUsedInInput} for further explanation + * + * @return the current separator for reading the INI input + * @since 2.5 + */ + public String getCommentLeadingCharsUsedInInput() + { + beginRead(false); + try + { + return commentCharsUsedInInput; + } + finally + { + endRead(); + } + } + + /** + * Allows setting the leading comment separator which is used in reading + * an INI file + * + * @param separator String of the new separator for INI reading + * @since 2.5 + */ + public void setCommentLeadingCharsUsedInInput(final String separator) + { + beginRead(false); + try + { + this.commentCharsUsedInInput = separator; + } + finally + { + endRead(); + } + } + + /** * Save the configuration to the specified writer. * * @param writer - The writer to save the configuration to. @@ -530,7 +621,8 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements * @param reader the reader (needed if multiple lines have to be read) * @throws IOException if an IO error occurs */ - private static String parseValue(final String val, final BufferedReader reader) throws IOException + private String parseValue(final String val, final BufferedReader reader) + throws IOException { final StringBuilder propertyValue = new StringBuilder(); boolean lineContinues; @@ -645,7 +737,7 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements * @param pos the start position * @return a flag whether this line continues */ - private static boolean lineContinues(final String line, final int pos) + private boolean lineContinues(final String line, final int pos) { String s; @@ -672,9 +764,9 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements * @param c the character * @return a flag whether this character starts a comment */ - private static boolean isCommentChar(final char c) + private boolean isCommentChar(final char c) { - return COMMENT_CHARS.indexOf(c) >= 0; + return getCommentLeadingCharsUsedInInput().indexOf(c) >= 0; } /** @@ -687,14 +779,14 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements * @param line the line to be checked * @return the index of the separator character or -1 if none is found */ - private static int findSeparator(final String line) + private int findSeparator(final String line) { int index = findSeparatorBeforeQuote(line, findFirstOccurrence(line, QUOTE_CHARACTERS)); if (index < 0) { - index = findFirstOccurrence(line, SEPARATOR_CHARS); + index = findFirstOccurrence(line, getSeparatorUsedInInput()); } return index; } @@ -774,13 +866,14 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements * @param value the value to be escaped * @return the value with comment characters escaped */ - private static String escapeComments(final String value) + private String escapeComments(final String value) { + final String commentChars = getCommentLeadingCharsUsedInInput(); boolean quoted = false; - for (int i = 0; i < COMMENT_CHARS.length() && !quoted; i++) + for (int i = 0; i < commentChars.length() && !quoted; i++) { - final char c = COMMENT_CHARS.charAt(i); + final char c = commentChars.charAt(i); if (value.indexOf(c) != -1) { quoted = true; @@ -808,7 +901,8 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements return false; } // blank lines are also treated as comment lines - return line.length() < 1 || COMMENT_CHARS.indexOf(line.charAt(0)) >= 0; + return line.length() < 1 + || getCommentLeadingCharsUsedInInput().indexOf(line.charAt(0)) >= 0; } /** diff --git a/src/main/java/org/apache/commons/configuration2/builder/INIBuilderParametersImpl.java b/src/main/java/org/apache/commons/configuration2/builder/INIBuilderParametersImpl.java index fef9cfe..43c6481 100644 --- a/src/main/java/org/apache/commons/configuration2/builder/INIBuilderParametersImpl.java +++ b/src/main/java/org/apache/commons/configuration2/builder/INIBuilderParametersImpl.java @@ -40,12 +40,18 @@ public class INIBuilderParametersImpl extends HierarchicalBuilderParametersImpl /** The key for the separatorUsedInINIOutput property. */ private static final String PROP_SEPARATOR_USED_IN_INI_OUTPUT = "separatorUsedInOutput"; + private static final String PROP_SEPARATOR_USED_IN_INI_INPUT + = "separatorUsedInInput"; + private static final String PROP_COMMENT_LEADING_SEPARATOR_USED_IN_INI_INPUT + = "commentLeadingCharsUsedInInput"; @Override public void inheritFrom(final Map<String, ?> source) { super.inheritFrom(source); copyPropertiesFrom(source, PROP_SEPARATOR_USED_IN_INI_OUTPUT); + copyPropertiesFrom(source, PROP_SEPARATOR_USED_IN_INI_INPUT); + copyPropertiesFrom(source, PROP_COMMENT_LEADING_SEPARATOR_USED_IN_INI_INPUT); } @Override @@ -54,4 +60,16 @@ public class INIBuilderParametersImpl extends HierarchicalBuilderParametersImpl storeProperty(PROP_SEPARATOR_USED_IN_INI_OUTPUT, separator); return this; } + + @Override + public INIBuilderParametersImpl setSeparatorUsedInInput(String separator) { + storeProperty(PROP_SEPARATOR_USED_IN_INI_INPUT, separator); + return this; + } + + @Override + public INIBuilderParametersImpl setCommentLeadingCharsUsedInInput(String separator) { + storeProperty(PROP_COMMENT_LEADING_SEPARATOR_USED_IN_INI_INPUT, separator); + return this; + } } diff --git a/src/main/java/org/apache/commons/configuration2/builder/INIBuilderProperties.java b/src/main/java/org/apache/commons/configuration2/builder/INIBuilderProperties.java index 6c58a92..6b2a86c 100644 --- a/src/main/java/org/apache/commons/configuration2/builder/INIBuilderProperties.java +++ b/src/main/java/org/apache/commons/configuration2/builder/INIBuilderProperties.java @@ -33,11 +33,37 @@ package org.apache.commons.configuration2.builder; * @since 2.2 * @param <T> the type of the result of all set methods for method chaining */ -public interface INIBuilderProperties<T> -{ +public interface INIBuilderProperties<T> { + /** - * Allows setting the separator between key and value to be used when - * writing an INI file. + * Allows setting the leading comment separator which is used in reading an INI + * file + * + * @param separator String of the new separator for INI reading + * @return a reference to this object for method chaining + * @since 2.5 + */ + default T setCommentLeadingCharsUsedInInput(String separator) { + // NoOp + return (T) this; + } + + /** + * Allows setting the key and value separator which is used in reading an INI + * file + * + * @param separator String of the new separator for INI reading + * @return a reference to this object for method chaining + * @since 2.5 + */ + default T setSeparatorUsedInInput(String separator) { + // NoOp + return (T) this; + } + + /** + * Allows setting the separator between key and value to be used when writing an + * INI file. * * @param separator the new separator for INI output * @return a reference to this object for method chaining diff --git a/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java b/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java index 92a1ca4..2d1263d 100644 --- a/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java +++ b/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java @@ -20,6 +20,7 @@ package org.apache.commons.configuration2; import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -254,6 +255,57 @@ public class TestINIConfiguration } /** + * Test of read method with changed separator. + */ + @Test + public void testSeparatorUsedInINIInput() throws Exception + { + final String inputSeparator = "="; + final String input = "[section]" + LINE_SEPARATOR + + "k1:v1$key1=value1" + LINE_SEPARATOR + + "k1:v1,k2:v2$key2=value2" + LINE_SEPARATOR + + "key3:value3" + LINE_SEPARATOR + + "key4 = value4" + LINE_SEPARATOR; + + final INIConfiguration instance = new FileBasedConfigurationBuilder<>( + INIConfiguration.class) + .configure(new Parameters().ini().setSeparatorUsedInInput(inputSeparator)) + .getConfiguration(); + load(instance, input); + + assertEquals("value1", instance.getString("section.k1:v1$key1")); + assertEquals("value2", instance.getString("section.k1:v1,k2:v2$key2")); + assertEquals("", instance.getString("section.key3:value3")); + assertEquals("value4", instance.getString("section.key4").trim()); + } + + /** + * Test of read method with changed comment leading separator + */ + @Test + public void testCommentLeadingSeparatorUsedInINIInput() throws Exception + { + final String inputCommentLeadingSeparator = ";"; + final String input = "[section]" + LINE_SEPARATOR + + "key1=a;b;c" + LINE_SEPARATOR + + "key2=a#b#c" + LINE_SEPARATOR + + ";key3=value3" + LINE_SEPARATOR + + "#key4=value4" + LINE_SEPARATOR; + + final INIConfiguration instance = new FileBasedConfigurationBuilder<>( + INIConfiguration.class) + .configure(new Parameters().ini() + .setCommentLeadingCharsUsedInInput(inputCommentLeadingSeparator)) + .getConfiguration(); + load(instance, input); + + assertEquals("a;b;c", instance.getString("section.key1")); + assertEquals("a#b#c", instance.getString("section.key2")); + assertNull("", instance.getString("section.;key3")); + assertEquals("value4", instance.getString("section.#key4")); + } + + /** * Helper method for testing a save operation. This method constructs a * configuration from the specified content string. Then it saves this * configuration and checks whether the result matches the original content.