You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/11/06 20:08:21 UTC

[commons-configuration] branch master updated: CONFIGURATION-822: Fix ambiguity on the section determining (#229)

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 f01f557f CONFIGURATION-822: Fix ambiguity on the section determining (#229)
f01f557f is described below

commit f01f557fe53b2e1acc383e87fdb9dc5bb911ef18
Author: Branislav Beňo <57...@users.noreply.github.com>
AuthorDate: Sun Nov 6 21:08:16 2022 +0100

    CONFIGURATION-822: Fix ambiguity on the section determining (#229)
    
    * CONFIGURATION-822: Fix ambiguity on the section determining
    
    * CONFIGURATION-822: Introduce flag for granting backward compatibility
    
    * CONFIGURATION-822: Revert unnecessary formatting changes.
    
    * CONFIGURATION-822: Add planned version
    
    * CONFIGURATION-822: Revert another unnecessary changes
    
    Co-authored-by: Branislav Beno <br...@gmail.com>
---
 .../commons/configuration2/INIConfiguration.java   | 38 +++++++++++-
 .../configuration2/TestINIConfiguration.java       | 72 ++++++++++++++++++++--
 2 files changed, 104 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/apache/commons/configuration2/INIConfiguration.java b/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
index 65442256..4d3745eb 100644
--- a/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/INIConfiguration.java
@@ -236,12 +236,27 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements F
      */
     private String commentCharsUsedInInput = COMMENT_CHARS;
 
+    /**
+     * The flag for decision, whether inline comments on the section line are allowed.
+     */
+    private boolean sectionInLineCommentsAllowed;
+
     /**
      * Create a new empty INI Configuration.
      */
     public INIConfiguration() {
     }
 
+    /**
+     * Create a new empty INI Configuration with option to allow inline comments on the section line.
+     *
+     * @param sectionInLineCommentsAllowed when true inline comments on the section line are allowed
+     * @since 2.9.0
+     */
+    public INIConfiguration(boolean sectionInLineCommentsAllowed) {
+        this.sectionInLineCommentsAllowed = sectionInLineCommentsAllowed;
+    }
+
     /**
      * Creates a new instance of {@code INIConfiguration} with the content of the specified
      * {@code HierarchicalConfiguration}.
@@ -430,7 +445,8 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements F
             line = line.trim();
             if (!isCommentLine(line)) {
                 if (isSectionLine(line)) {
-                    final String section = line.substring(1, line.length() - 1);
+                    int length = sectionInLineCommentsAllowed ? line.indexOf("]") : line.length() - 1;
+                    final String section = line.substring(1, length);
                     sectionBuilder = sectionBuilders.get(section);
                     if (sectionBuilder == null) {
                         sectionBuilder = new ImmutableNode.Builder();
@@ -736,9 +752,29 @@ public class INIConfiguration extends BaseHierarchicalConfiguration implements F
         if (line == null) {
             return false;
         }
+        return sectionInLineCommentsAllowed ? isNonStrictSection(line) : isStrictSection(line);
+    }
+
+    /**
+     * Determine if the entire given line is a section - inline comments are not allowed.
+     *
+     * @param line The line to check.
+     * @return true if the entire line is a section
+     */
+    private static boolean isStrictSection(String line) {
         return line.startsWith("[") && line.endsWith("]");
     }
 
+    /**
+     * Determine if the given line contains a section - inline comments are allowed.
+     *
+     * @param line The line to check.
+     * @return true if the line contains a section
+     */
+    private static boolean isNonStrictSection(String line) {
+        return line.startsWith("[") && line.contains("]");
+    }
+
     /**
      * Return a set containing the sections in this ini configuration. Note that changes to this set do not affect the
      * configuration.
diff --git a/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java b/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
index ce1c290d..04778c43 100644
--- a/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
+++ b/src/test/java/org/apache/commons/configuration2/TestINIConfiguration.java
@@ -41,6 +41,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Stream;
 
 import org.apache.commons.configuration2.SynchronizerTestImpl.Methods;
 import org.apache.commons.configuration2.builder.FileBasedBuilderParametersImpl;
@@ -56,6 +57,9 @@ import org.apache.commons.configuration2.tree.NodeHandler;
 import org.apache.commons.configuration2.tree.NodeNameMatchers;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 /**
  * Test class for {@code INIConfiguration}.
@@ -119,6 +123,18 @@ public class TestINIConfiguration {
     private static final String INI_DATA4 = "[section6]" + LINE_SEPARATOR + "key1{0}value1" + LINE_SEPARATOR + "key2{0}value2" + LINE_SEPARATOR + LINE_SEPARATOR
         + "[section7]" + LINE_SEPARATOR + "key3{0}value3" + LINE_SEPARATOR;
 
+    private static final String INI_DATA5 = "[section4]" + LINE_SEPARATOR + "var1 = \"quoted value\"" + LINE_SEPARATOR
+        + "var2 = \"quoted value\\nwith \\\"quotes\\\"\"" + LINE_SEPARATOR + "var3 = 123 # comment" + LINE_SEPARATOR + "var4 = \"1#2;3\" # comment"
+        + LINE_SEPARATOR + "var5 = '\\'quoted\\' \"value\"' # comment" + LINE_SEPARATOR + "var6 = \"\"" + LINE_SEPARATOR;
+
+    /** Constant for the content of an ini file - with section inline comment defined with semicolon */
+    private static final String INI_DATA6 = "[section1]; main section" + LINE_SEPARATOR + "var1 = foo" + LINE_SEPARATOR + LINE_SEPARATOR
+        + "[section11] ; sub-section related to [section1]" + LINE_SEPARATOR + "var1 = 123.45" + LINE_SEPARATOR;
+
+    /** Constant for the content of an ini file - with section inline comment defined with number sign */
+    private static final String INI_DATA7 = "[section1]# main section" + LINE_SEPARATOR + "var1 = foo" + LINE_SEPARATOR + LINE_SEPARATOR
+        + "[section11] # sub-section related to [section1]" + LINE_SEPARATOR + "var1 = 123.45" + LINE_SEPARATOR;
+
     private static final String INI_DATA_SEPARATORS = "[section]" + LINE_SEPARATOR + "var1 = value1" + LINE_SEPARATOR + "var2 : value2" + LINE_SEPARATOR
         + "var3=value3" + LINE_SEPARATOR + "var4:value4" + LINE_SEPARATOR + "var5 : value=5" + LINE_SEPARATOR + "var:6=value" + LINE_SEPARATOR
         + "var:7=\"value7\"" + LINE_SEPARATOR + "var:8 =  \"value8\"" + LINE_SEPARATOR;
@@ -170,7 +186,19 @@ public class TestINIConfiguration {
      * @throws ConfigurationException if an error occurs
      */
     private static INIConfiguration setUpConfig(final String data) throws ConfigurationException {
-        final INIConfiguration instance = new INIConfiguration();
+        return setUpConfig(data, false);
+    }
+
+    /**
+     * Creates a INIConfiguration object that is initialized from the given data.
+     *
+     * @param data the data of the configuration (an ini file as string)
+     * @param inLineCommentsAllowed when true, inline comments on section line are allowed
+     * @return the initialized configuration
+     * @throws ConfigurationException if an error occurs
+     */
+    private static INIConfiguration setUpConfig(final String data, boolean inLineCommentsAllowed) throws ConfigurationException {
+        final INIConfiguration instance = new INIConfiguration(inLineCommentsAllowed);
         instance.setListDelimiterHandler(new DefaultListDelimiterHandler(','));
         load(instance, data);
         return instance;
@@ -967,10 +995,25 @@ public class TestINIConfiguration {
         assertEquals(expectedOutput, result);
     }
 
-    @Test
-    public void testValueWithComment() throws Exception {
-        final INIConfiguration config = setUpConfig(INI_DATA2);
-        assertEquals("123", config.getString("section4.var3"));
+    /**
+     * Test correct handling of in line comments on value line
+     */
+    @ParameterizedTest
+    @MethodSource("provideValuesWithComments")
+    public void testValueWithComment(String source, String key, String value) throws Exception {
+        final INIConfiguration config = setUpConfig(source);
+        assertEquals(value, config.getString(key));
+    }
+
+    private static Stream<Arguments> provideValuesWithComments() {
+        return Stream.of(
+                Arguments.of(INI_DATA2, "section4.var3", "123"),
+                Arguments.of(INI_DATA2, "section4.var4", "1;2;3"),
+                Arguments.of(INI_DATA2, "section4.var5", "'quoted' \"value\""),
+                Arguments.of(INI_DATA5, "section4.var3", "123"),
+                Arguments.of(INI_DATA5, "section4.var4", "1#2;3"),
+                Arguments.of(INI_DATA5, "section4.var5", "'quoted' \"value\"")
+        );
     }
 
     /**
@@ -1025,6 +1068,25 @@ public class TestINIConfiguration {
         assertEquals("1;2;3", config2.getString("section.key1"));
     }
 
+    /**
+     * Tests whether a section with inline comment is correctly parsed.
+     */
+    @ParameterizedTest
+    @MethodSource("provideSectionsWithComments")
+    public void testGetSectionsWithInLineComment(String source, boolean allowComments, String[] results) throws ConfigurationException {
+        final INIConfiguration config = setUpConfig(source, allowComments);
+        checkSectionNames(config, results);
+    }
+
+    private static Stream<Arguments> provideSectionsWithComments() {
+        return Stream.of(
+                Arguments.of(INI_DATA6, false, new String[]{null, "section11] ; sub-section related to [section1"}),
+                Arguments.of(INI_DATA7, false, new String[]{null, "section11] # sub-section related to [section1"}),
+                Arguments.of(INI_DATA6, true, new String[]{"section1", "section11"}),
+                Arguments.of(INI_DATA7, true, new String[]{"section1", "section11"})
+        );
+    }
+
     /**
      * Writes a test ini file.
      *