/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.configuration2;

import java.io.FileNotFoundException;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.configuration2.convert.ListDelimiterHandler;
import org.apache.commons.configuration2.convert.ValueTransformer;
import org.apache.commons.configuration2.event.ConfigurationEvent;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.apache.commons.configuration2.io.FileHandler;
import org.apache.commons.configuration2.io.FileLocator;
import org.apache.commons.configuration2.io.FileLocatorAware;
import org.apache.commons.configuration2.io.FileLocatorUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.commons.text.translate.AggregateTranslator;
import org.apache.commons.text.translate.CharSequenceTranslator;
import org.apache.commons.text.translate.EntityArrays;
import org.apache.commons.text.translate.LookupTranslator;
import org.apache.commons.text.translate.UnicodeEscaper;

/**
 * This is the "classic" Properties loader which loads the values from a single or multiple files (which can be chained
 * with "include =". All given path references are either absolute or relative to the file name supplied in the
 * constructor.
 * <p>
 * In this class, empty PropertyConfigurations can be built, properties added and later saved. include statements are
 * (obviously) not supported if you don't construct a PropertyConfiguration from a file.
 *
 * <p>
 * The properties file syntax is explained here, basically it follows the syntax of the stream parsed by
 * {@link java.util.Properties#load} and adds several useful extensions:
 *
 * <ul>
 * <li>Each property has the syntax {@code key &lt;separator&gt; value}. The separators accepted are {@code '='},
 * {@code ':'} and any white space character. Examples:
 *
 * <pre>
 *  key1 = value1
 *  key2 : value2
 *  key3   value3
 * </pre>
 *
 * </li>
 * <li>The <i>key</i> may use any character, separators must be escaped:
 *
 * <pre>
 *  key\:foo = bar
 * </pre>
 *
 * </li>
 * <li><i>value</i> may be separated on different lines if a backslash is placed at the end of the line that continues
 * below.</li>
 * <li>The list delimiter facilities provided by {@link AbstractConfiguration} are supported, too. If an appropriate
 * {@link ListDelimiterHandler} is set (for instance a
 * {@link org.apache.commons.configuration2.convert.DefaultListDelimiterHandler D efaultListDelimiterHandler} object
 * configured with a comma as delimiter character), <i>value</i> can contain <em>value delimiters</em> and will then be
 * interpreted as a list of tokens. So the following property definition
 *
 * <pre>
 *  key = This property, has multiple, values
 * </pre>
 *
 * will result in a property with three values. You can change the handling of delimiters using the
 * {@link AbstractConfiguration#setListDelimiterHandler(ListDelimiterHandler)} method. Per default, list splitting is
 * disabled.</li>
 * <li>Commas in each token are escaped placing a backslash right before the comma.</li>
 * <li>If a <i>key</i> is used more than once, the values are appended like if they were on the same line separated with
 * commas. <em>Note</em>: When the configuration file is written back to disk the associated
 * {@link PropertiesConfigurationLayout} object (see below) will try to preserve as much of the original format as
 * possible, i.e. properties with multiple values defined on a single line will also be written back on a single line,
 * and multiple occurrences of a single key will be written on multiple lines. If the {@code addProperty()} method was
 * called multiple times for adding multiple values to a property, these properties will per default be written on
 * multiple lines in the output file, too. Some options of the {@code PropertiesConfigurationLayout} class have
 * influence on that behavior.</li>
 * <li>Blank lines and lines starting with character '#' or '!' are skipped.</li>
 * <li>If a property is named "include" (or whatever is defined by setInclude() and getInclude() and the value of that
 * property is the full path to a file on disk, that file will be included into the configuration. You can also pull in
 * files relative to the parent configuration file. So if you have something like the following:
 *
 * include = additional.properties
 *
 * Then "additional.properties" is expected to be in the same directory as the parent configuration file.
 *
 * The properties in the included file are added to the parent configuration, they do not replace existing properties
 * with the same key.
 *
 * </li>
 * <li>You can define custom error handling for the special key {@code "include"} by using
 * {@link #setIncludeListener(ConfigurationConsumer)}.</li>
 * </ul>
 *
 * <p>
 * Here is an example of a valid extended properties file:
 * </p>
 *
 * <pre>
 *      # lines starting with # are comments
 *
 *      # This is the simplest property
 *      key = value
 *
 *      # A long property may be separated on multiple lines
 *      longvalue = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
 *                  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 *
 *      # This is a property with many tokens
 *      tokens_on_a_line = first token, second token
 *
 *      # This sequence generates exactly the same result
 *      tokens_on_multiple_lines = first token
 *      tokens_on_multiple_lines = second token
 *
 *      # commas may be escaped in tokens
 *      commas.escaped = Hi\, what'up?
 *
 *      # properties can reference other properties
 *      base.prop = /base
 *      first.prop = ${base.prop}/first
 *      second.prop = ${first.prop}/second
 * </pre>
 *
 * <p>
 * A {@code PropertiesConfiguration} object is associated with an instance of the {@link PropertiesConfigurationLayout}
 * class, which is responsible for storing the layout of the parsed properties file (i.e. empty lines, comments, and
 * such things). The {@code getLayout()} method can be used to obtain this layout object. With {@code setLayout()} a new
 * layout object can be set. This should be done before a properties file was loaded.
 * <p>
 * Like other {@code Configuration} implementations, this class uses a {@code Synchronizer} object to control concurrent
 * access. By choosing a suitable implementation of the {@code Synchronizer} interface, an instance can be made
 * thread-safe or not. Note that access to most of the properties typically set through a builder is not protected by
 * the {@code Synchronizer}. The intended usage is that these properties are set once at construction time through the
 * builder and after that remain constant. If you wish to change such properties during life time of an instance, you
 * have to use the {@code lock()} and {@code unlock()} methods manually to ensure that other threads see your changes.
 * <p>
 * As this class extends {@link AbstractConfiguration}, all basic features like variable interpolation, list handling,
 * or data type conversions are available as well. This is described in the chapter
 * <a href="https://commons.apache.org/proper/commons-configuration/userguide/howto_basicfeatures.html"> Basic features
 * and AbstractConfiguration</a> of the user's guide. There is also a separate chapter dealing with
 * <a href="commons.apache.org/proper/commons-configuration/userguide/howto_properties.html"> Properties files</a> in
 * special.
 *
 * @see java.util.Properties#load
 */
public class PropertiesConfiguration extends BaseConfiguration implements FileBasedConfiguration, FileLocatorAware {

    /**
     * <p>
     * A default implementation of the {@code IOFactory} interface.
     * </p>
     * <p>
     * This class implements the {@code createXXXX()} methods defined by the {@code IOFactory} interface in a way that the
     * default objects (i.e. {@code PropertiesReader} and {@code PropertiesWriter} are returned. Customizing either the
     * reader or the writer (or both) can be done by extending this class and overriding the corresponding
     * {@code createXXXX()} method.
     * </p>
     *
     * @since 1.7
     */
    public static class DefaultIOFactory implements IOFactory {
        /**
         * The singleton instance.
         */
        static final DefaultIOFactory INSTANCE = new DefaultIOFactory();

        @Override
        public PropertiesReader createPropertiesReader(final Reader in) {
            return new PropertiesReader(in);
        }

        @Override
        public PropertiesWriter createPropertiesWriter(final Writer out, final ListDelimiterHandler handler) {
            return new PropertiesWriter(out, handler);
        }
    }

    /**
     * <p>
     * Definition of an interface that allows customization of read and write operations.
     * </p>
     * <p>
     * For reading and writing properties files the inner classes {@code PropertiesReader} and {@code PropertiesWriter} are
     * used. This interface defines factory methods for creating both a {@code PropertiesReader} and a
     * {@code PropertiesWriter}. An object implementing this interface can be passed to the {@code setIOFactory()} method of
     * {@code PropertiesConfiguration}. Every time the configuration is read or written the {@code IOFactory} is asked to
     * create the appropriate reader or writer object. This provides an opportunity to inject custom reader or writer
     * implementations.
     * </p>
     *
     * @since 1.7
     */
    public interface IOFactory {
        /**
         * Creates a {@code PropertiesReader} for reading a properties file. This method is called whenever the
         * {@code PropertiesConfiguration} is loaded. The reader returned by this method is then used for parsing the properties
         * file.
         *
         * @param in the underlying reader (of the properties file)
         * @return the {@code PropertiesReader} for loading the configuration
         */
        PropertiesReader createPropertiesReader(Reader in);

        /**
         * Creates a {@code PropertiesWriter} for writing a properties file. This method is called before the
         * {@code PropertiesConfiguration} is saved. The writer returned by this method is then used for writing the properties
         * file.
         *
         * @param out the underlying writer (to the properties file)
         * @param handler the list delimiter delimiter for list parsing
         * @return the {@code PropertiesWriter} for saving the configuration
         */
        PropertiesWriter createPropertiesWriter(Writer out, ListDelimiterHandler handler);
    }

    /**
     * An alternative {@link IOFactory} that tries to mimic the behavior of {@link java.util.Properties} (Jup) more closely.
     * The goal is to allow both of them be used interchangeably when reading and writing properties files without losing or
     * changing information.
     * <p>
     * It also has the option to <em>not</em> use Unicode escapes. When using UTF-8 encoding (which is e.g. the new default
     * for resource bundle properties files since Java 9), Unicode escapes are no longer required and avoiding them makes
     * properties files more readable with regular text editors.
     * <p>
     * Some of the ways this implementation differs from {@link DefaultIOFactory}:
     * <ul>
     * <li>Trailing whitespace will not be trimmed from each line.</li>
     * <li>Unknown escape sequences will have their backslash removed.</li>
     * <li>{@code \b} is not a recognized escape sequence.</li>
     * <li>Leading spaces in property values are preserved by escaping them.</li>
     * <li>All natural lines (i.e. in the file) of a logical property line will have their leading whitespace trimmed.</li>
     * <li>Natural lines that look like comment lines within a logical line are not treated as such; they're part of the
     * property value.</li>
     * </ul>
     *
     * @since 2.4
     */
    public static class JupIOFactory implements IOFactory {

        /**
         * Whether characters less than {@code \u0020} and characters greater than {@code \u007E} in property keys or values
         * should be escaped using Unicode escape sequences. Not necessary when e.g. writing as UTF-8.
         */
        private final boolean escapeUnicode;

        /**
         * Constructs a new {@link JupIOFactory} with Unicode escaping.
         */
        public JupIOFactory() {
            this(true);
        }

        /**
         * Constructs a new {@link JupIOFactory} with optional Unicode escaping. Whether Unicode escaping is required depends on
         * the encoding used to save the properties file. E.g. for ISO-8859-1 this must be turned on, for UTF-8 it's not
         * necessary. Unfortunately this factory can't determine the encoding on its own.
         *
         * @param escapeUnicode whether Unicode characters should be escaped
         */
        public JupIOFactory(final boolean escapeUnicode) {
            this.escapeUnicode = escapeUnicode;
        }

        @Override
        public PropertiesReader createPropertiesReader(final Reader in) {
            return new JupPropertiesReader(in);
        }

        @Override
        public PropertiesWriter createPropertiesWriter(final Writer out, final ListDelimiterHandler handler) {
            return new JupPropertiesWriter(out, handler, escapeUnicode);
        }

    }

    /**
     * A {@link PropertiesReader} that tries to mimic the behavior of {@link java.util.Properties}.
     *
     * @since 2.4
     */
    public static class JupPropertiesReader extends PropertiesReader {

        /**
         * Constructs a new instance.
         *
         * @param reader A Reader.
         */
        public JupPropertiesReader(final Reader reader) {
            super(reader);
        }

        @Override
        protected void parseProperty(final String line) {
            final String[] property = doParseProperty(line, false);
            initPropertyName(property[0]);
            initPropertyValue(property[1]);
            initPropertySeparator(property[2]);
        }

        @Override
        public String readProperty() throws IOException {
            getCommentLines().clear();
            final StringBuilder buffer = new StringBuilder();

            while (true) {
                String line = readLine();
                if (line == null) {
                    // EOF
                    if (buffer.length() > 0) {
                        break;
                    }
                    return null;
                }

                // while a property line continues there are no comments (even if the line from
                // the file looks like one)
                if (isCommentLine(line) && buffer.length() == 0) {
                    getCommentLines().add(line);
                    continue;
                }

                // while property line continues left trim all following lines read from the
                // file
                if (buffer.length() > 0) {
                    // index of the first non-whitespace character
                    int i;
                    for (i = 0; i < line.length(); i++) {
                        if (!Character.isWhitespace(line.charAt(i))) {
                            break;
                        }
                    }

                    line = line.substring(i);
                }

                if (!checkCombineLines(line)) {
                    buffer.append(line);
                    break;
                }
                line = line.substring(0, line.length() - 1);
                buffer.append(line);
            }
            return buffer.toString();
        }

        @Override
        protected String unescapePropertyValue(final String value) {
            return unescapeJava(value, true);
        }

    }

    /**
     * A {@link PropertiesWriter} that tries to mimic the behavior of {@link java.util.Properties}.
     *
     * @since 2.4
     */
    public static class JupPropertiesWriter extends PropertiesWriter {

        /**
         * The starting ASCII printable character.
         */
        private static final int PRINTABLE_INDEX_END = 0x7e;

        /**
         * The ending ASCII printable character.
         */
        private static final int PRINTABLE_INDEX_START = 0x20;

        /**
         * A UnicodeEscaper for characters outside the ASCII printable range.
         */
        private static final UnicodeEscaper ESCAPER = UnicodeEscaper.outsideOf(PRINTABLE_INDEX_START, PRINTABLE_INDEX_END);

        /**
         * Characters that need to be escaped when wring a properties file.
         */
        private static final Map<CharSequence, CharSequence> JUP_CHARS_ESCAPE;
        static {
            final Map<CharSequence, CharSequence> initialMap = new HashMap<>();
            initialMap.put("\\", "\\\\");
            initialMap.put("\n", "\\n");
            initialMap.put("\t", "\\t");
            initialMap.put("\f", "\\f");
            initialMap.put("\r", "\\r");
            JUP_CHARS_ESCAPE = Collections.unmodifiableMap(initialMap);
        }

        /**
         * Creates a new instance of {@code JupPropertiesWriter}.
         *
         * @param writer a Writer object providing the underlying stream
         * @param delHandler the delimiter handler for dealing with properties with multiple values
         * @param escapeUnicode whether Unicode characters should be escaped using Unicode escapes
         */
        public JupPropertiesWriter(final Writer writer, final ListDelimiterHandler delHandler, final boolean escapeUnicode) {
            super(writer, delHandler, value -> {
                String valueString = String.valueOf(value);

                final CharSequenceTranslator translator;
                if (escapeUnicode) {
                    translator = new AggregateTranslator(new LookupTranslator(JUP_CHARS_ESCAPE), ESCAPER);
                } else {
                    translator = new AggregateTranslator(new LookupTranslator(JUP_CHARS_ESCAPE));
                }

                valueString = translator.translate(valueString);

                // escape the first leading space to preserve it (and all after it)
                if (valueString.startsWith(" ")) {
                    valueString = "\\" + valueString;
                }

                return valueString;
            });
        }

    }

    /**
     * This class is used to read properties lines. These lines do not terminate with new-line chars but rather when there
     * is no backslash sign a the end of the line. This is used to concatenate multiple lines for readability.
     */
    public static class PropertiesReader extends LineNumberReader {

        /** 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) + "])\\s*)?(.*)");

        /** Constant for the index of the group for the key. */
        private static final int IDX_KEY = 1;

        /** Constant for the index of the group for the value. */
        private static final int IDX_VALUE = 5;

        /** Constant for the index of the group for the separator. */
        private static final int IDX_SEPARATOR = 3;

        /** Stores the comment lines for the currently processed property. */
        private final List<String> commentLines;

        /** Stores the name of the last read property. */
        private String propertyName;

        /** 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;

        /**
         * Constructs a new instance.
         *
         * @param reader A Reader.
         */
        public PropertiesReader(final Reader reader) {
            super(reader);
            commentLines = new ArrayList<>();
        }

        /**
         * 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.
         *
         * @param line the line
         * @return a flag if the lines should be combined
         */
        static boolean checkCombineLines(final String line) {
            return countTrailingBS(line) % 2 != 0;
        }

        /**
         * Parse a property line and return the key, the value, and the separator in an array.
         *
         * @param line the line to parse
         * @param trimValue flag whether the value is to be trimmed
         * @return an array with the property's key, value, and separator
         */
        static String[] doParseProperty(final String line, final boolean trimValue) {
            final Matcher matcher = PROPERTY_PATTERN.matcher(line);

            final String[] result = {"", "", ""};

            if (matcher.matches()) {
                result[0] = matcher.group(IDX_KEY).trim();

                String value = matcher.group(IDX_VALUE);
                if (trimValue) {
                    value = value.trim();
                }
                result[1] = value;

                result[2] = matcher.group(IDX_SEPARATOR);
            }

            return result;
        }

        /**
         * Gets the comment lines that have been read for the last property.
         *
         * @return the comment lines for the last property returned by {@code readProperty()}
         * @since 1.3
         */
        public List<String> getCommentLines() {
            return commentLines;
        }

        /**
         * Gets the name of the last read property. This method can be called after {@link #nextProperty()} was invoked and
         * its return value was <b>true</b>.
         *
         * @return the name of the last read property
         * @since 1.3
         */
        public String getPropertyName() {
            return propertyName;
        }

        /**
         * Gets 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;
        }

        /**
         * Gets the value of the last read property. This method can be called after {@link #nextProperty()} was invoked and
         * its return value was <b>true</b>.
         *
         * @return the value of the last read property
         * @since 1.3
         */
        public String getPropertyValue() {
            return propertyValue;
        }

        /**
         * Sets the name of the current property. This method can be called by {@code parseProperty()} for storing the results
         * of the parse operation. It also ensures that the property key is correctly escaped.
         *
         * @param name the name of the current property
         * @since 1.7
         */
        protected void initPropertyName(final String name) {
            propertyName = unescapePropertyName(name);
        }

        /**
         * Sets the separator of the current property. This method can be called by {@code parseProperty()}. 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(final String value) {
            propertySeparator = value;
        }

        /**
         * Sets the value of the current property. This method can be called by {@code parseProperty()} for storing the results
         * of the parse operation. It also ensures that the property value is correctly escaped.
         *
         * @param value the value of the current property
         * @since 1.7
         */
        protected void initPropertyValue(final String value) {
            propertyValue = unescapePropertyValue(value);
        }

        /**
         * Parses the next property from the input stream and stores the found name and value in internal fields. These fields
         * can be obtained using the provided getter methods. The return value indicates whether EOF was reached (<b>false</b>)
         * or whether further properties are available (<b>true</b>).
         *
         * @return a flag if further properties are available
         * @throws IOException if an error occurs
         * @since 1.3
         */
        public boolean nextProperty() throws IOException {
            final String line = readProperty();

            if (line == null) {
                return false; // EOF
            }

            // parse the line
            parseProperty(line);
            return true;
        }

        /**
         * 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 results of the parse operation
         * can be stored by calling the {@code initPropertyXXX()} methods.
         *
         * @param line the line read from the properties file
         * @since 1.7
         */
        protected void parseProperty(final String line) {
            final String[] property = doParseProperty(line, true);
            initPropertyName(property[0]);
            initPropertyValue(property[1]);
            initPropertySeparator(property[2]);
        }

        /**
         * Reads a property line. Returns null if Stream is at EOF. Concatenates lines ending with "\". Skips lines beginning
         * with "#" or "!" and empty lines. The return value is a property definition ({@code &lt;name&gt;} =
         * {@code &lt;value&gt;})
         *
         * @return A string containing a property value or null
         *
         * @throws IOException in case of an I/O error
         */
        public String readProperty() throws IOException {
            commentLines.clear();
            final StringBuilder buffer = new StringBuilder();

            while (true) {
                String line = readLine();
                if (line == null) {
                    // EOF
                    return null;
                }

                if (isCommentLine(line)) {
                    commentLines.add(line);
                    continue;
                }

                line = line.trim();

                if (!checkCombineLines(line)) {
                    buffer.append(line);
                    break;
                }
                line = line.substring(0, line.length() - 1);
                buffer.append(line);
            }
            return buffer.toString();
        }

        /**
         * Performs unescaping on the given property name.
         *
         * @param name the property name
         * @return the unescaped property name
         * @since 2.4
         */
        protected String unescapePropertyName(final String name) {
            return StringEscapeUtils.unescapeJava(name);
        }

        /**
         * Performs unescaping on the given property value.
         *
         * @param value the property value
         * @return the unescaped property value
         * @since 2.4
         */
        protected String unescapePropertyValue(final String value) {
            return unescapeJava(value);
        }
    } // class PropertiesReader

    /**
     * This class is used to write properties lines. The most important method is
     * {@code writeProperty(String, Object, boolean)}, which is called during a save operation for each property found in
     * the configuration.
     */
    public static class PropertiesWriter extends FilterWriter {

        /**
         * Properties escape map.
         */
        private static final Map<CharSequence, CharSequence> PROPERTIES_CHARS_ESCAPE;
        static {
            final Map<CharSequence, CharSequence> initialMap = new HashMap<>();
            initialMap.put("\\", "\\\\");
            PROPERTIES_CHARS_ESCAPE = Collections.unmodifiableMap(initialMap);
        }

        /**
         * A translator for escaping property values. This translator performs a subset of transformations done by the
         * ESCAPE_JAVA translator from Commons Lang 3.
         */
        private static final CharSequenceTranslator ESCAPE_PROPERTIES = new AggregateTranslator(new LookupTranslator(PROPERTIES_CHARS_ESCAPE),
            new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE), UnicodeEscaper.outsideOf(32, 0x7f));

        /**
         * A {@code ValueTransformer} implementation used to escape property values. This implementation applies the
         * transformation defined by the {@link #ESCAPE_PROPERTIES} translator.
         */
        private static final ValueTransformer DEFAULT_TRANSFORMER = value -> {
            final String strVal = String.valueOf(value);
            return ESCAPE_PROPERTIES.translate(strVal);
        };

        /** The value transformer used for escaping property values. */
        private final ValueTransformer valueTransformer;

        /** The list delimiter handler. */
        private final ListDelimiterHandler delimiterHandler;

        /** 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;

        /**
         * Creates a new instance of {@code PropertiesWriter}.
         *
         * @param writer a Writer object providing the underlying stream
         * @param delHandler the delimiter handler for dealing with properties with multiple values
         */
        public PropertiesWriter(final Writer writer, final ListDelimiterHandler delHandler) {
            this(writer, delHandler, DEFAULT_TRANSFORMER);
        }

        /**
         * Creates a new instance of {@code PropertiesWriter}.
         *
         * @param writer a Writer object providing the underlying stream
         * @param delHandler the delimiter handler for dealing with properties with multiple values
         * @param valueTransformer the value transformer used to escape property values
         */
        public PropertiesWriter(final Writer writer, final ListDelimiterHandler delHandler, final ValueTransformer valueTransformer) {
            super(writer);
            delimiterHandler = delHandler;
            this.valueTransformer = valueTransformer;
        }

        /**
         * Escapes the key of a property before it gets written to file. This method is called on saving a configuration for
         * each property key. It ensures that separator characters contained in the key are escaped.
         *
         * @param key the key
         * @return the escaped key
         * @since 2.0
         */
        protected String escapeKey(final String key) {
            final StringBuilder newkey = new StringBuilder();

            for (int i = 0; i < key.length(); i++) {
                final char c = key.charAt(i);

                if (ArrayUtils.contains(SEPARATORS, c) || ArrayUtils.contains(WHITE_SPACE, c) || c == '\\') {
                    // escape the separator
                    newkey.append('\\');
                }
                newkey.append(c);
            }

            return newkey.toString();
        }

        /**
         * Returns the separator to be used for the given property. This method is called by {@code writeProperty()}. 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()} 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(final String key, final Object value) {
            return getGlobalSeparator() != null ? getGlobalSeparator() : StringUtils.defaultString(getCurrentSeparator());
        }

        /**
         * Gets the current property separator.
         *
         * @return the current property separator
         * @since 1.7
         */
        public String getCurrentSeparator() {
            return currentSeparator;
        }

        /**
         * Gets the delimiter handler for properties with multiple values. This object is used to escape property values so
         * that they can be read in correctly the next time they are loaded.
         *
         * @return the delimiter handler for properties with multiple values
         * @since 2.0
         */
        public ListDelimiterHandler getDelimiterHandler() {
            return delimiterHandler;
        }

        /**
         * Gets the global property separator.
         *
         * @return the global property separator
         * @since 1.7
         */
        public String getGlobalSeparator() {
            return globalSeparator;
        }

        /**
         * Gets the line separator.
         *
         * @return the line separator
         * @since 1.7
         */
        public String getLineSeparator() {
            return lineSeparator != null ? lineSeparator : LINE_SEPARATOR;
        }

        /**
         * 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(final String currentSeparator) {
            this.currentSeparator = currentSeparator;
        }

        /**
         * Sets the global property separator. This separator corresponds to the {@code globalSeparator} 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(final String globalSeparator) {
            this.globalSeparator = globalSeparator;
        }

        /**
         * 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(final String lineSeparator) {
            this.lineSeparator = lineSeparator;
        }

        /**
         * Write a comment.
         *
         * @param comment the comment to write
         * @throws IOException if an I/O error occurs.
         */
        public void writeComment(final String comment) throws IOException {
            writeln("# " + comment);
        }

        /**
         * Helper method for writing a line with the platform specific line ending.
         *
         * @param s the content of the line (may be <b>null</b>)
         * @throws IOException if an error occurs
         * @since 1.3
         */
        public void writeln(final String s) throws IOException {
            if (s != null) {
                write(s);
            }
            write(getLineSeparator());
        }

        /**
         * Write a property.
         *
         * @param key The key of the property
         * @param values The array of values of the property
         *
         * @throws IOException if an I/O error occurs.
         */
        public void writeProperty(final String key, final List<?> values) throws IOException {
            for (final Object value : values) {
                writeProperty(key, value);
            }
        }

        /**
         * Write a property.
         *
         * @param key the key of the property
         * @param value the value of the property
         *
         * @throws IOException if an I/O error occurs.
         */
        public void writeProperty(final String key, final Object value) throws IOException {
            writeProperty(key, value, false);
        }

        /**
         * Writes the given property and its value. If the value happens to be a list, the {@code forceSingleLine} flag is
         * evaluated. If it is set, all values are written on a single line using the list delimiter as separator.
         *
         * @param key the property key
         * @param value the property value
         * @param forceSingleLine the &quot;force single line&quot; flag
         * @throws IOException if an error occurs
         * @since 1.3
         */
        public void writeProperty(final String key, final Object value, final boolean forceSingleLine) throws IOException {
            String v;

            if (value instanceof List) {
                v = null;
                final List<?> values = (List<?>) value;
                if (forceSingleLine) {
                    try {
                        v = String.valueOf(getDelimiterHandler().escapeList(values, valueTransformer));
                    } catch (final UnsupportedOperationException ignored) {
                        // the handler may not support escaping lists,
                        // then the list is written in multiple lines
                    }
                }
                if (v == null) {
                    writeProperty(key, values);
                    return;
                }
            } else {
                v = String.valueOf(getDelimiterHandler().escape(value, valueTransformer));
            }

            write(escapeKey(key));
            write(fetchSeparator(key, value));
            write(v);

            writeln(null);
        }
    } // class PropertiesWriter

    /**
     * Defines default error handling for the special {@code "include"} key by throwing the given exception.
     *
     * @since 2.6
     */
    public static final ConfigurationConsumer<ConfigurationException> DEFAULT_INCLUDE_LISTENER = e -> {
        throw e;
    };

    /**
     * Defines error handling as a noop for the special {@code "include"} key.
     *
     * @since 2.6
     */
    public static final ConfigurationConsumer<ConfigurationException> NOOP_INCLUDE_LISTENER = e -> { /* noop */ };

    /**
     * The default encoding (ISO-8859-1 as specified by https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html)
     */
    public static final String DEFAULT_ENCODING = StandardCharsets.ISO_8859_1.name();

    /** Constant for the supported comment characters. */
    static final String COMMENT_CHARS = "#!";

    /** Constant for the default properties separator. */
    static final String DEFAULT_SEPARATOR = " = ";

    /**
     * A string with special characters that need to be unescaped when reading a properties file.
     * {@link java.util.Properties} escapes these characters when writing out a properties file.
     */
    private static final String UNESCAPE_CHARACTERS = ":#=!\\\'\"";

    /**
     * This is the name of the property that can point to other properties file for including other properties files.
     */
    private static String include = "include";

    /**
     * This is the name of the property that can point to other properties file for including other properties files.
     * <p>
     * If the file is absent, processing continues normally.
     * </p>
     */
    private static String includeOptional = "includeoptional";

    /** The list of possible key/value separators */
    private static final char[] SEPARATORS = {'=', ':'};

    /** The white space characters used as key/value separators. */
    private static final char[] WHITE_SPACE = {' ', '\t', '\f'};

    /** Constant for the platform specific line separator. */
    private static final String LINE_SEPARATOR = System.lineSeparator();

    /** Constant for the radix of hex numbers. */
    private static final int HEX_RADIX = 16;

    /** Constant for the length of a unicode literal. */
    private static final int UNICODE_LEN = 4;

    /** Stores the layout object. */
    private PropertiesConfigurationLayout layout;

    /** The include listener for the special {@code "include"} key. */
    private ConfigurationConsumer<ConfigurationException> includeListener;

    /** The IOFactory for creating readers and writers. */
    private IOFactory ioFactory;

    /** The current {@code FileLocator}. */
    private FileLocator locator;

    /** Allow file inclusion or not */
    private boolean includesAllowed = true;

    /**
     * Creates an empty PropertyConfiguration object which can be used to synthesize a new Properties file by adding values
     * and then saving().
     */
    public PropertiesConfiguration() {
        installLayout(createLayout());
    }

    /**
     * Returns the number of trailing backslashes. This is sometimes needed for the correct handling of escape characters.
     *
     * @param line the string to investigate
     * @return the number of trailing backslashes
     */
    private static int countTrailingBS(final String line) {
        int bsCount = 0;
        for (int idx = line.length() - 1; idx >= 0 && line.charAt(idx) == '\\'; idx--) {
            bsCount++;
        }

        return bsCount;
    }

    /**
     * Gets the property value for including other properties files. By default it is "include".
     *
     * @return A String.
     */
    public static String getInclude() {
        return PropertiesConfiguration.include;
    }

    /**
     * Gets the property value for including other properties files. By default it is "includeoptional".
     * <p>
     * If the file is absent, processing continues normally.
     * </p>
     *
     * @return A String.
     * @since 2.5
     */
    public static String getIncludeOptional() {
        return PropertiesConfiguration.includeOptional;
    }

    /**
     * Tests whether a line is a comment, i.e. whether it starts with a comment character.
     *
     * @param line the line
     * @return a flag if this is a comment line
     * @since 1.3
     */
    static boolean isCommentLine(final String line) {
        final String s = line.trim();
        // blank lines are also treated as comment lines
        return s.isEmpty() || COMMENT_CHARS.indexOf(s.charAt(0)) >= 0;
    }

    /**
     * Checks whether the specified character needs to be unescaped. This method is called when during reading a property
     * file an escape character ('\') is detected. If the character following the escape character is recognized as a
     * special character which is escaped per default in a Java properties file, it has to be unescaped.
     *
     * @param ch the character in question
     * @return a flag whether this character has to be unescaped
     */
    private static boolean needsUnescape(final char ch) {
        return UNESCAPE_CHARACTERS.indexOf(ch) >= 0;
    }

    /**
     * Sets the property value for including other properties files. By default it is "include".
     *
     * @param inc A String.
     */
    public static void setInclude(final String inc) {
        PropertiesConfiguration.include = inc;
    }

    /**
     * Sets the property value for including other properties files. By default it is "include".
     * <p>
     * If the file is absent, processing continues normally.
     * </p>
     *
     * @param inc A String.
     * @since 2.5
     */
    public static void setIncludeOptional(final String inc) {
        PropertiesConfiguration.includeOptional = inc;
    }

    /**
     * <p>
     * Unescapes any Java literals found in the {@code String} to a {@code Writer}.
     * </p>
     * This is a slightly modified version of the StringEscapeUtils.unescapeJava() function in commons-lang that doesn't
     * drop escaped separators (i.e '\,').
     *
     * @param str the {@code String} to unescape, may be null
     * @return the processed string
     * @throws IllegalArgumentException if the Writer is {@code null}
     */
    protected static String unescapeJava(final String str) {
        return unescapeJava(str, false);
    }

    /**
     * Unescapes Java literals found in the {@code String} to a {@code Writer}.
     * <p>
     * When the parameter {@code jupCompatible} is {@code false}, the classic behavior is used (see
     * {@link #unescapeJava(String)}). When it's {@code true} a slightly different behavior that's compatible with
     * {@link java.util.Properties} is used (see {@link JupIOFactory}).
     * </p>
     *
     * @param str the {@code String} to unescape, may be null
     * @param jupCompatible whether unescaping is compatible with {@link java.util.Properties}; otherwise the classic
     *        behavior is used
     * @return the processed string
     * @throws IllegalArgumentException if the Writer is {@code null}
     */
    protected static String unescapeJava(final String str, final boolean jupCompatible) {
        if (str == null) {
            return null;
        }
        final int sz = str.length();
        final StringBuilder out = new StringBuilder(sz);
        final StringBuilder unicode = new StringBuilder(UNICODE_LEN);
        boolean hadSlash = false;
        boolean inUnicode = false;
        for (int i = 0; i < sz; i++) {
            final char ch = str.charAt(i);
            if (inUnicode) {
                // if in unicode, then we're reading unicode
                // values in somehow
                unicode.append(ch);
                if (unicode.length() == UNICODE_LEN) {
                    // unicode now contains the four hex digits
                    // which represents our unicode character
                    try {
                        final int value = Integer.parseInt(unicode.toString(), HEX_RADIX);
                        out.append((char) value);
                        unicode.setLength(0);
                        inUnicode = false;
                        hadSlash = false;
                    } catch (final NumberFormatException nfe) {
                        throw new ConfigurationRuntimeException("Unable to parse unicode value: " + unicode, nfe);
                    }
                }
                continue;
            }

            if (hadSlash) {
                // handle an escaped value
                hadSlash = false;

                switch (ch) {
                case 'r':
                    out.append('\r');
                    break;
                case 'f':
                    out.append('\f');
                    break;
                case 't':
                    out.append('\t');
                    break;
                case 'n':
                    out.append('\n');
                    break;
                default:
                    if (!jupCompatible && ch == 'b') {
                        out.append('\b');
                    } else if (ch == 'u') {
                        // uh-oh, we're in unicode country....
                        inUnicode = true;
                    } else {
                        // JUP simply throws away the \ of unknown escape sequences
                        if (!needsUnescape(ch) && !jupCompatible) {
                            out.append('\\');
                        }
                        out.append(ch);
                    }
                    break;
                }

                continue;
            }
            if (ch == '\\') {
                hadSlash = true;
                continue;
            }
            out.append(ch);
        }

        if (hadSlash) {
            // then we're in the weird case of a \ at the end of the
            // string, let's output it anyway.
            out.append('\\');
        }

        return out.toString();
    }

    /**
     * Creates a copy of this object.
     *
     * @return the copy
     */
    @Override
    public Object clone() {
        final PropertiesConfiguration copy = (PropertiesConfiguration) super.clone();
        if (layout != null) {
            copy.setLayout(new PropertiesConfigurationLayout(layout));
        }
        return copy;
    }

    /**
     * Creates a standard layout object. This configuration is initialized with such a standard layout.
     *
     * @return the newly created layout object
     */
    private PropertiesConfigurationLayout createLayout() {
        return new PropertiesConfigurationLayout();
    }

    /**
     * Gets the footer comment. This is a comment at the very end of the file.
     *
     * @return the footer comment
     * @since 2.0
     */
    public String getFooter() {
        beginRead(false);
        try {
            return getLayout().getFooterComment();
        } finally {
            endRead();
        }
    }

    /**
     * Gets the comment header.
     *
     * @return the comment header
     * @since 1.1
     */
    public String getHeader() {
        beginRead(false);
        try {
            return getLayout().getHeaderComment();
        } finally {
            endRead();
        }
    }

    /**
     * Gets the current include listener, never null.
     *
     * @return the current include listener, never null.
     * @since 2.6
     */
    public ConfigurationConsumer<ConfigurationException> getIncludeListener() {
        return includeListener != null ? includeListener : PropertiesConfiguration.DEFAULT_INCLUDE_LISTENER;
    }

    /**
     * Gets the {@code IOFactory} to be used for creating readers and writers when loading or saving this configuration.
     *
     * @return the {@code IOFactory}
     * @since 1.7
     */
    public IOFactory getIOFactory() {
        return ioFactory != null ? ioFactory : DefaultIOFactory.INSTANCE;
    }

    /**
     * Gets the associated layout object.
     *
     * @return the associated layout object
     * @since 1.3
     */
    public PropertiesConfigurationLayout getLayout() {
        return layout;
    }

    /**
     * Stores the current {@code FileLocator} for a following IO operation. The {@code FileLocator} is needed to resolve
     * include files with relative file names.
     *
     * @param locator the current {@code FileLocator}
     * @since 2.0
     */
    @Override
    public void initFileLocator(final FileLocator locator) {
        this.locator = locator;
    }

    /**
     * Installs a layout object. It has to be ensured that the layout is registered as change listener at this
     * configuration. If there is already a layout object installed, it has to be removed properly.
     *
     * @param layout the layout object to be installed
     */
    private void installLayout(final PropertiesConfigurationLayout layout) {
        // only one layout must exist
        if (this.layout != null) {
            removeEventListener(ConfigurationEvent.ANY, this.layout);
        }

        if (layout == null) {
            this.layout = createLayout();
        } else {
            this.layout = layout;
        }
        addEventListener(ConfigurationEvent.ANY, this.layout);
    }

    /**
     * Reports the status of file inclusion.
     *
     * @return True if include files are loaded.
     */
    public boolean isIncludesAllowed() {
        return this.includesAllowed;
    }

    /**
     * Helper method for loading an included properties file. This method is called by {@code load()} when an
     * {@code include} property is encountered. It tries to resolve relative file names based on the current base path. If
     * this fails, a resolution based on the location of this properties file is tried.
     *
     * @param fileName the name of the file to load
     * @param optional whether or not the {@code fileName} is optional
     * @param seenStack Stack of seen include URLs
     * @throws ConfigurationException if loading fails
     */
    private void loadIncludeFile(final String fileName, final boolean optional, final Deque<URL> seenStack) throws ConfigurationException {
        if (locator == null) {
            throw new ConfigurationException(
                "Load operation not properly " + "initialized! Do not call read(InputStream) directly," + " but use a FileHandler to load a configuration.");
        }

        URL url = locateIncludeFile(locator.getBasePath(), fileName);
        if (url == null) {
            final URL baseURL = locator.getSourceURL();
            if (baseURL != null) {
                url = locateIncludeFile(baseURL.toString(), fileName);
            }
        }

        if (optional && url == null) {
            return;
        }

        if (url == null) {
            getIncludeListener().accept(new ConfigurationException("Cannot resolve include file " + fileName, new FileNotFoundException(fileName)));
        } else {
            final FileHandler fh = new FileHandler(this);
            fh.setFileLocator(locator);
            final FileLocator orgLocator = locator;
            try {
                try {
                    // Check for cycles
                    if (seenStack.contains(url)) {
                        throw new ConfigurationException(String.format("Cycle detected loading %s, seen stack: %s", url, seenStack));
                    }
                    seenStack.add(url);
                    try {
                        fh.load(url);
                    } finally {
                        seenStack.pop();
                    }
                } catch (final ConfigurationException e) {
                    getIncludeListener().accept(e);
                }
            } finally {
                locator = orgLocator; // reset locator which is changed by load
            }
        }
    }

    /**
     * Tries to obtain the URL of an include file using the specified (optional) base path and file name.
     *
     * @param basePath the base path
     * @param fileName the file name
     * @return the URL of the include file or <b>null</b> if it cannot be resolved
     */
    private URL locateIncludeFile(final String basePath, final String fileName) {
        final FileLocator includeLocator = FileLocatorUtils.fileLocator(locator).sourceURL(null).basePath(basePath).fileName(fileName).create();
        return FileLocatorUtils.locate(includeLocator);
    }

    /**
     * This method is invoked by the associated {@link PropertiesConfigurationLayout} object for each property definition
     * detected in the parsed properties file. Its task is to check whether this is a special property definition (e.g. the
     * {@code include} property). If not, the property must be added to this configuration. The return value indicates
     * whether the property should be treated as a normal property. If it is <b>false</b>, the layout object will ignore
     * this property.
     *
     * @param key the property key
     * @param value the property value
     * @param seenStack the stack of seen include URLs
     * @return a flag whether this is a normal property
     * @throws ConfigurationException if an error occurs
     * @since 1.3
     */
    boolean propertyLoaded(final String key, final String value, final Deque<URL> seenStack) throws ConfigurationException {
        final boolean result;

        if (StringUtils.isNotEmpty(getInclude()) && key.equalsIgnoreCase(getInclude())) {
            if (isIncludesAllowed()) {
                final Collection<String> files = getListDelimiterHandler().split(value, true);
                for (final String f : files) {
                    loadIncludeFile(interpolate(f), false, seenStack);
                }
            }
            result = false;
        } else if (StringUtils.isNotEmpty(getIncludeOptional()) && key.equalsIgnoreCase(getIncludeOptional())) {
            if (isIncludesAllowed()) {
                final Collection<String> files = getListDelimiterHandler().split(value, true);
                for (final String f : files) {
                    loadIncludeFile(interpolate(f), true, seenStack);
                }
            }
            result = false;
        } else {
            addPropertyInternal(key, value);
            result = true;
        }

        return result;
    }

    /**
     * {@inheritDoc} This implementation delegates to the associated layout object which does the actual loading. Note that
     * this method does not do any synchronization. This lies in the responsibility of the caller. (Typically, the caller is
     * a {@code FileHandler} object which takes care for proper synchronization.)
     *
     * @since 2.0
     */
    @Override
    public void read(final Reader in) throws ConfigurationException, IOException {
        getLayout().load(this, in);
    }

    /**
     * Sets the footer comment. If set, this comment is written after all properties at the end of the file.
     *
     * @param footer the footer comment
     * @since 2.0
     */
    public void setFooter(final String footer) {
        beginWrite(false);
        try {
            getLayout().setFooterComment(footer);
        } finally {
            endWrite();
        }
    }

    /**
     * Sets the comment header.
     *
     * @param header the header to use
     * @since 1.1
     */
    public void setHeader(final String header) {
        beginWrite(false);
        try {
            getLayout().setHeaderComment(header);
        } finally {
            endWrite();
        }
    }

    /**
     * Sets the current include listener, may not be null.
     *
     * @param includeListener the current include listener, may not be null.
     * @throws IllegalArgumentException if the {@code includeListener} is null.
     * @since 2.6
     */
    public void setIncludeListener(final ConfigurationConsumer<ConfigurationException> includeListener) {
        if (includeListener == null) {
            throw new IllegalArgumentException("includeListener must not be null.");
        }
        this.includeListener = includeListener;
    }

    /**
     * Controls whether additional files can be loaded by the {@code include = <xxx>} statement or not. This is <b>true</b>
     * per default.
     *
     * @param includesAllowed True if Includes are allowed.
     */
    public void setIncludesAllowed(final boolean includesAllowed) {
        this.includesAllowed = includesAllowed;
    }

    /**
     * Sets the {@code IOFactory} to be used for creating readers and writers when loading or saving this configuration.
     * Using this method a client can customize the reader and writer classes used by the load and save operations. Note
     * that this method must be called before invoking one of the {@code load()} and {@code save()} methods. Especially, if
     * you want to use a custom {@code IOFactory} for changing the {@code PropertiesReader}, you cannot load the
     * configuration data in the constructor.
     *
     * @param ioFactory the new {@code IOFactory} (must not be <b>null</b>)
     * @throws IllegalArgumentException if the {@code IOFactory} is <b>null</b>
     * @since 1.7
     */
    public void setIOFactory(final IOFactory ioFactory) {
        if (ioFactory == null) {
            throw new IllegalArgumentException("IOFactory must not be null.");
        }

        this.ioFactory = ioFactory;
    }

    /**
     * Sets the associated layout object.
     *
     * @param layout the new layout object; can be <b>null</b>, then a new layout object will be created
     * @since 1.3
     */
    public void setLayout(final PropertiesConfigurationLayout layout) {
        installLayout(layout);
    }

    /**
     * {@inheritDoc} This implementation delegates to the associated layout object which does the actual saving. Note that,
     * analogous to {@link #read(Reader)}, this method does not do any synchronization.
     *
     * @since 2.0
     */
    @Override
    public void write(final Writer out) throws ConfigurationException, IOException {
        getLayout().save(this, out);
    }

}
