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 2019/09/12 14:52:17 UTC
[commons-configuration] branch master updated: [CONFIGURATION-756]
Allow for custom behavior to handle errors loading included properties
files. (#34)
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 8b31196 [CONFIGURATION-756] Allow for custom behavior to handle errors loading included properties files. (#34)
8b31196 is described below
commit 8b311965eb0c04508461a3e14169f79a1c065678
Author: Gary Gregory <ga...@users.noreply.github.com>
AuthorDate: Thu Sep 12 10:52:13 2019 -0400
[CONFIGURATION-756] Allow for custom behavior to handle errors loading included properties files. (#34)
[CONFIGURATION-756] Allow for custom behavior to handle errors loading included properties files. (#34)
---
.../configuration2/ConfigurationConsumer.java | 39 +++++++
.../configuration2/PropertiesConfiguration.java | 112 +++++++++++++++++----
.../builder/PropertiesBuilderParametersImpl.java | 15 ++-
.../builder/PropertiesBuilderProperties.java | 14 +++
.../builder/fluent/Configurations.java | 44 +++++++-
.../TestPropertiesConfiguration.java | 82 ++++++++++++++-
.../TestPropertiesBuilderParametersImpl.java | 43 +++++++-
.../combined/TestCombinedConfigurationBuilder.java | 2 +-
.../builder/fluent/TestConfigurations.java | 105 ++++++++++++++++---
.../builder/fluent/TestParameters.java | 17 +++-
.../include-cyclical-reference.properties | 16 +++
.../resources/include-include-not-found.properties | 16 +++
.../resources/include-load-exception.properties | 16 +++
src/test/resources/include-not-found.properties | 16 +++
14 files changed, 489 insertions(+), 48 deletions(-)
diff --git a/src/main/java/org/apache/commons/configuration2/ConfigurationConsumer.java b/src/main/java/org/apache/commons/configuration2/ConfigurationConsumer.java
new file mode 100644
index 0000000..3e96418
--- /dev/null
+++ b/src/main/java/org/apache/commons/configuration2/ConfigurationConsumer.java
@@ -0,0 +1,39 @@
+/*
+ * 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 org.apache.commons.configuration2.ex.ConfigurationException;
+
+/**
+ * A Configuration task that may throw a ConfigurationException.
+ *
+ * @param <T> the type of the input to the operation.
+ * @since 2.6
+ */
+@FunctionalInterface
+public interface ConfigurationConsumer<T>
+{
+
+ /**
+ * Performs this operation on the given argument.
+ *
+ * @param t the input argument
+ * @throws ConfigurationException May be thrown while performing a Configuration operation.
+ */
+ void accept(T t) throws ConfigurationException;
+}
diff --git a/src/main/java/org/apache/commons/configuration2/PropertiesConfiguration.java b/src/main/java/org/apache/commons/configuration2/PropertiesConfiguration.java
index 3b86bbe..438bba8 100644
--- a/src/main/java/org/apache/commons/configuration2/PropertiesConfiguration.java
+++ b/src/main/java/org/apache/commons/configuration2/PropertiesConfiguration.java
@@ -17,6 +17,7 @@
package org.apache.commons.configuration2;
+import java.io.FileNotFoundException;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.LineNumberReader;
@@ -137,6 +138,10 @@ import org.apache.commons.text.translate.UnicodeEscaper;
* 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>
@@ -194,11 +199,31 @@ import org.apache.commons.text.translate.UnicodeEscaper;
* Properties files</a> in special.
*
* @see java.util.Properties#load
- *
*/
public class PropertiesConfiguration extends BaseConfiguration
implements FileBasedConfiguration, FileLocatorAware
{
+
+ /**
+ * 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
* http://java.sun.com/j2se/1.5.0/docs/api/java/util/Properties.html)
@@ -212,12 +237,6 @@ public class PropertiesConfiguration extends BaseConfiguration
static final String DEFAULT_SEPARATOR = " = ";
/**
- * Constant for the default {@code IOFactory}. This instance is used
- * when no specific factory was set.
- */
- private static final IOFactory DEFAULT_IO_FACTORY = new DefaultIOFactory();
-
- /**
* A string with special characters that need to be unescaped when reading
* a properties file. {@code java.util.Properties} escapes these characters
* when writing out a properties file.
@@ -257,6 +276,9 @@ public class PropertiesConfiguration extends BaseConfiguration
/** 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;
@@ -488,6 +510,17 @@ public class PropertiesConfiguration extends BaseConfiguration
}
/**
+ * 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;
+ }
+
+ /**
* Returns the {@code IOFactory} to be used for creating readers and
* writers when loading or saving this configuration.
*
@@ -496,7 +529,23 @@ public class PropertiesConfiguration extends BaseConfiguration
*/
public IOFactory getIOFactory()
{
- return (ioFactory != null) ? ioFactory : DEFAULT_IO_FACTORY;
+ return ioFactory != null ? ioFactory : DefaultIOFactory.INSTANCE;
+ }
+
+ /**
+ * 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;
}
/**
@@ -518,7 +567,7 @@ public class PropertiesConfiguration extends BaseConfiguration
{
if (ioFactory == null)
{
- throw new IllegalArgumentException("IOFactory must not be null!");
+ throw new IllegalArgumentException("IOFactory must not be null.");
}
this.ioFactory = ioFactory;
@@ -1377,6 +1426,11 @@ public class PropertiesConfiguration extends BaseConfiguration
*/
public static class DefaultIOFactory implements IOFactory
{
+ /**
+ * The singleton instance.
+ */
+ static final DefaultIOFactory INSTANCE = new DefaultIOFactory();
+
@Override
public PropertiesReader createPropertiesReader(final Reader in)
{
@@ -1827,20 +1881,35 @@ public class PropertiesConfiguration extends BaseConfiguration
if (url == null)
{
- throw new ConfigurationException("Cannot resolve include file "
- + fileName);
- }
-
- final FileHandler fh = new FileHandler(this);
- fh.setFileLocator(locator);
- final FileLocator orgLocator = locator;
- try
- {
- fh.load(url);
+ if (getIncludeListener() != null)
+ {
+ getIncludeListener().accept(new ConfigurationException(
+ "Cannot resolve include file " + fileName, new FileNotFoundException(fileName)));
+ }
}
- finally
+ else
{
- locator = orgLocator; // reset locator which is changed by load
+ final FileHandler fh = new FileHandler(this);
+ fh.setFileLocator(locator);
+ final FileLocator orgLocator = locator;
+ try
+ {
+ try
+ {
+ fh.load(url);
+ }
+ catch (ConfigurationException e)
+ {
+ if (getIncludeListener() != null)
+ {
+ getIncludeListener().accept(e);
+ }
+ }
+ }
+ finally
+ {
+ locator = orgLocator; // reset locator which is changed by load
+ }
}
}
@@ -1860,4 +1929,5 @@ public class PropertiesConfiguration extends BaseConfiguration
.basePath(basePath).fileName(fileName).create();
return FileLocatorUtils.locate(includeLocator);
}
+
}
diff --git a/src/main/java/org/apache/commons/configuration2/builder/PropertiesBuilderParametersImpl.java b/src/main/java/org/apache/commons/configuration2/builder/PropertiesBuilderParametersImpl.java
index a908ac0..39965a7 100644
--- a/src/main/java/org/apache/commons/configuration2/builder/PropertiesBuilderParametersImpl.java
+++ b/src/main/java/org/apache/commons/configuration2/builder/PropertiesBuilderParametersImpl.java
@@ -18,8 +18,10 @@ package org.apache.commons.configuration2.builder;
import java.util.Map;
+import org.apache.commons.configuration2.ConfigurationConsumer;
import org.apache.commons.configuration2.PropertiesConfiguration.IOFactory;
import org.apache.commons.configuration2.PropertiesConfigurationLayout;
+import org.apache.commons.configuration2.ex.ConfigurationException;
/**
* <p>
@@ -44,6 +46,9 @@ public class PropertiesBuilderParametersImpl extends
FileBasedBuilderParametersImpl implements
PropertiesBuilderProperties<PropertiesBuilderParametersImpl>
{
+ /** The key for the include listener property. */
+ private static final String PROP_INCLUDE_LISTENER = "includeListener";
+
/** The key for the includes allowed property. */
private static final String PROP_INCLUDES_ALLOWED = "includesAllowed";
@@ -54,6 +59,14 @@ public class PropertiesBuilderParametersImpl extends
private static final String PROP_IO_FACTORY = "IOFactory";
@Override
+ public PropertiesBuilderParametersImpl setIncludeListener(
+ final ConfigurationConsumer<ConfigurationException> includeListener)
+ {
+ storeProperty(PROP_INCLUDE_LISTENER, includeListener);
+ return this;
+ }
+
+ @Override
public PropertiesBuilderParametersImpl setIncludesAllowed(final boolean f)
{
storeProperty(PROP_INCLUDES_ALLOWED, Boolean.valueOf(f));
@@ -68,7 +81,7 @@ public class PropertiesBuilderParametersImpl extends
public void inheritFrom(final Map<String, ?> source)
{
super.inheritFrom(source);
- copyPropertiesFrom(source, PROP_INCLUDES_ALLOWED, PROP_IO_FACTORY);
+ copyPropertiesFrom(source, PROP_INCLUDES_ALLOWED, PROP_INCLUDE_LISTENER, PROP_IO_FACTORY);
}
@Override
diff --git a/src/main/java/org/apache/commons/configuration2/builder/PropertiesBuilderProperties.java b/src/main/java/org/apache/commons/configuration2/builder/PropertiesBuilderProperties.java
index 939339b..62040ed 100644
--- a/src/main/java/org/apache/commons/configuration2/builder/PropertiesBuilderProperties.java
+++ b/src/main/java/org/apache/commons/configuration2/builder/PropertiesBuilderProperties.java
@@ -16,8 +16,10 @@
*/
package org.apache.commons.configuration2.builder;
+import org.apache.commons.configuration2.ConfigurationConsumer;
import org.apache.commons.configuration2.PropertiesConfiguration.IOFactory;
import org.apache.commons.configuration2.PropertiesConfigurationLayout;
+import org.apache.commons.configuration2.ex.ConfigurationException;
/**
* <p>
@@ -39,6 +41,18 @@ import org.apache.commons.configuration2.PropertiesConfigurationLayout;
public interface PropertiesBuilderProperties<T>
{
/**
+ * Sets the current include listener, may be null.
+ *
+ * @param includeListener the current include listener, may be null.
+ * @return a reference to this object for method chaining
+ * @since 2.6
+ */
+ default T setIncludeListener(ConfigurationConsumer<ConfigurationException> includeListener)
+ {
+ return (T) this;
+ }
+
+ /**
* Sets a flag whether include files are supported by the properties
* configuration object. If set to <b>true</b>, files listed by an include
* property are loaded automatically.
diff --git a/src/main/java/org/apache/commons/configuration2/builder/fluent/Configurations.java b/src/main/java/org/apache/commons/configuration2/builder/fluent/Configurations.java
index 55f6ba5..5c07d71 100644
--- a/src/main/java/org/apache/commons/configuration2/builder/fluent/Configurations.java
+++ b/src/main/java/org/apache/commons/configuration2/builder/fluent/Configurations.java
@@ -225,6 +225,17 @@ public class Configurations
}
/**
+ * Creates a builder for a {@code PropertiesConfiguration}.
+ *
+ * @return the newly created {@code FileBasedConfigurationBuilder}
+ * @since 2.6
+ */
+ public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder()
+ {
+ return createFileBasedBuilder(PropertiesConfiguration.class);
+ }
+
+ /**
* Creates a builder for a {@code PropertiesConfiguration} and initializes
* it with the given file to be loaded.
*
@@ -239,6 +250,20 @@ public class Configurations
/**
* Creates a builder for a {@code PropertiesConfiguration} and initializes
+ * it with the given parameters to be loaded.
+ *
+ * @param parameters the parameters to be loaded
+ * @return the newly created {@code FileBasedConfigurationBuilder}
+ * @since 2.6
+ */
+ public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(
+ PropertiesBuilderParameters parameters)
+ {
+ return propertiesBuilder().configure(parameters);
+ }
+
+ /**
+ * Creates a builder for a {@code PropertiesConfiguration} and initializes
* it with the given URL to be loaded.
*
* @param url the URL to be loaded
@@ -579,6 +604,21 @@ public class Configurations
* specified type.
*
* @param configClass the configuration class
+ * @param <T> the type of the configuration to be constructed
+ * @return the newly created builder
+ * @since 2.6
+ */
+ private <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> createFileBasedBuilder(
+ final Class<T> configClass)
+ {
+ return new FileBasedConfigurationBuilder<>(configClass);
+ }
+
+ /**
+ * Creates a configured builder for a file-based configuration of the
+ * specified type.
+ *
+ * @param configClass the configuration class
* @param params the parameters object for configuring the builder
* @param <T> the type of the configuration to be constructed
* @return the newly created builder
@@ -586,8 +626,7 @@ public class Configurations
private <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> createFileBasedBuilder(
final Class<T> configClass, final FileBasedBuilderParameters params)
{
- return new FileBasedConfigurationBuilder<>(configClass)
- .configure(params);
+ return createFileBasedBuilder(configClass).configure(params);
}
/**
@@ -636,4 +675,5 @@ public class Configurations
{
return fileParams().setFileName(path);
}
+
}
diff --git a/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java b/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java
index dd63ff5..bd1e532 100644
--- a/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java
+++ b/src/test/java/org/apache/commons/configuration2/TestPropertiesConfiguration.java
@@ -17,7 +17,31 @@
package org.apache.commons.configuration2;
-import java.io.*;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
@@ -50,13 +74,11 @@ import org.apache.commons.configuration2.io.FileHandler;
import org.apache.commons.configuration2.io.FileSystem;
import org.apache.commons.lang3.mutable.MutableObject;
import org.junit.Before;
-import org.junit.Test;
+import org.junit.Ignore;
import org.junit.Rule;
+import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assert.*;
-
/**
* Test for loading and saving properties files.
*
@@ -1088,6 +1110,56 @@ public class TestPropertiesConfiguration
}
@Test
+ public void testIncludeLoadAllOnNotFound() throws Exception
+ {
+ final PropertiesConfiguration pc = new PropertiesConfiguration();
+ pc.setIncludeListener(PropertiesConfiguration.NOOP_INCLUDE_LISTENER);
+ final FileHandler handler = new FileHandler(pc);
+ handler.setBasePath(testBasePath);
+ handler.setFileName("include-not-found.properties");
+ handler.load();
+ assertEquals("valueA", pc.getString("keyA"));
+ }
+
+ @Test
+ public void testIncludeIncludeLoadAllOnNotFound() throws Exception
+ {
+ final PropertiesConfiguration pc = new PropertiesConfiguration();
+ pc.setIncludeListener(PropertiesConfiguration.NOOP_INCLUDE_LISTENER);
+ final FileHandler handler = new FileHandler(pc);
+ handler.setBasePath(testBasePath);
+ handler.setFileName("include-include-not-found.properties");
+ handler.load();
+ assertEquals("valueA", pc.getString("keyA"));
+ assertEquals("valueB", pc.getString("keyB"));
+ }
+
+ @Test
+ public void testIncludeLoadAllOnLoadException() throws Exception
+ {
+ final PropertiesConfiguration pc = new PropertiesConfiguration();
+ pc.setIncludeListener(PropertiesConfiguration.NOOP_INCLUDE_LISTENER);
+ final FileHandler handler = new FileHandler(pc);
+ handler.setBasePath(testBasePath);
+ handler.setFileName("include-load-exception.properties");
+ handler.load();
+ assertEquals("valueA", pc.getString("keyA"));
+ }
+
+ @Test
+ @Ignore("PropertiesConfiguration does NOT detect cyclical references.")
+ public void testIncludeLoadAllCycliclaReference() throws Exception
+ {
+ final PropertiesConfiguration pc = new PropertiesConfiguration();
+ pc.setIncludeListener(PropertiesConfiguration.NOOP_INCLUDE_LISTENER);
+ final FileHandler handler = new FileHandler(pc);
+ handler.setBasePath(testBasePath);
+ handler.setFileName("include-cyclical-reference.properties");
+ handler.load();
+ assertEquals("valueA", pc.getString("keyA"));
+ }
+
+ @Test
public void testLoadViaPropertyWithBasePath2() throws Exception
{
final PropertiesConfiguration pc = new PropertiesConfiguration();
diff --git a/src/test/java/org/apache/commons/configuration2/builder/TestPropertiesBuilderParametersImpl.java b/src/test/java/org/apache/commons/configuration2/builder/TestPropertiesBuilderParametersImpl.java
index 4606338..5815003 100644
--- a/src/test/java/org/apache/commons/configuration2/builder/TestPropertiesBuilderParametersImpl.java
+++ b/src/test/java/org/apache/commons/configuration2/builder/TestPropertiesBuilderParametersImpl.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertSame;
import java.util.Map;
+import org.apache.commons.configuration2.ConfigurationConsumer;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.PropertiesConfigurationLayout;
import org.apache.commons.configuration2.beanutils.BeanHelper;
@@ -70,6 +71,20 @@ public class TestPropertiesBuilderParametersImpl
}
/**
+ * Tests whether the include listener can be set.
+ */
+ @Test
+ public void testSetIncludeListener()
+ {
+ final ConfigurationConsumer<ConfigurationException> includeListener =
+ EasyMock.createMock(ConfigurationConsumer.class);
+ EasyMock.replay(includeListener);
+ assertSame("Wrong result", params, params.setIncludeListener(includeListener));
+ assertSame("IncludeListener not set", includeListener,
+ params.getParameters().get("includeListener"));
+ }
+
+ /**
* Tests whether the IO factory can be set.
*/
@Test
@@ -113,9 +128,13 @@ public class TestPropertiesBuilderParametersImpl
{
final PropertiesConfiguration.IOFactory factory =
EasyMock.createMock(PropertiesConfiguration.IOFactory.class);
- params.setIOFactory(factory).setIncludesAllowed(false)
- .setLayout(new PropertiesConfigurationLayout());
- params.setThrowExceptionOnMissing(true);
+ final ConfigurationConsumer<ConfigurationException> includeListener =
+ EasyMock.createMock(ConfigurationConsumer.class);
+ params.setIOFactory(factory)
+ .setIncludeListener(includeListener)
+ .setIncludesAllowed(false)
+ .setLayout(new PropertiesConfigurationLayout())
+ .setThrowExceptionOnMissing(true);
final PropertiesBuilderParametersImpl params2 =
new PropertiesBuilderParametersImpl();
@@ -123,6 +142,7 @@ public class TestPropertiesBuilderParametersImpl
final Map<String, Object> parameters = params2.getParameters();
assertEquals("Exception flag not set", Boolean.TRUE,
parameters.get("throwExceptionOnMissing"));
+ assertEquals("IncludeListener not set", includeListener, parameters.get("includeListener"));
assertEquals("IOFactory not set", factory, parameters.get("IOFactory"));
assertEquals("Include flag not set", Boolean.FALSE,
parameters.get("includesAllowed"));
@@ -146,4 +166,21 @@ public class TestPropertiesBuilderParametersImpl
final PropertiesConfiguration config = builder.getConfiguration();
assertEquals("Wrong IO factory", factory, config.getIOFactory());
}
+
+ /**
+ * Tests whether the IncludeListener property can be correctly set.
+ */
+ @Test
+ public void testSetIncludeListenerProperty() throws ConfigurationException
+ {
+ final ConfigurationConsumer<ConfigurationException> includeListener =
+ PropertiesConfiguration.DEFAULT_INCLUDE_LISTENER;
+ final ConfigurationBuilder<PropertiesConfiguration> builder =
+ new FileBasedConfigurationBuilder<>(
+ PropertiesConfiguration.class)
+ .configure(params.setIncludeListener(includeListener));
+
+ final PropertiesConfiguration config = builder.getConfiguration();
+ assertEquals("Wrong IncludeListener", includeListener, config.getIncludeListener());
+ }
}
diff --git a/src/test/java/org/apache/commons/configuration2/builder/combined/TestCombinedConfigurationBuilder.java b/src/test/java/org/apache/commons/configuration2/builder/combined/TestCombinedConfigurationBuilder.java
index 1017c21..0a59ea6 100644
--- a/src/test/java/org/apache/commons/configuration2/builder/combined/TestCombinedConfigurationBuilder.java
+++ b/src/test/java/org/apache/commons/configuration2/builder/combined/TestCombinedConfigurationBuilder.java
@@ -704,7 +704,7 @@ public class TestCombinedConfigurationBuilder
final CombinedConfiguration cc = builder.getConfiguration();
assertFalse("Configuration is empty", cc.isEmpty());
- // The environment may contain settings with values that
+ // The environment may contain settings with values that
// are altered by interpolation. Disable this for direct access
// to the String associated with the environment property name.
cc.setInterpolator(null);
diff --git a/src/test/java/org/apache/commons/configuration2/builder/fluent/TestConfigurations.java b/src/test/java/org/apache/commons/configuration2/builder/fluent/TestConfigurations.java
index 8ac5e71..d42c1a1 100644
--- a/src/test/java/org/apache/commons/configuration2/builder/fluent/TestConfigurations.java
+++ b/src/test/java/org/apache/commons/configuration2/builder/fluent/TestConfigurations.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertSame;
import java.io.File;
import java.net.URL;
+import java.util.Map;
import org.apache.commons.configuration2.CombinedConfiguration;
import org.apache.commons.configuration2.Configuration;
@@ -29,10 +30,12 @@ import org.apache.commons.configuration2.ConfigurationAssert;
import org.apache.commons.configuration2.INIConfiguration;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.XMLConfiguration;
+import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.plist.PropertyListConfiguration;
+import org.junit.Assert;
import org.junit.Test;
/**
@@ -57,12 +60,12 @@ public class TestConfigurations
private static final String TEST_PLIST = "test.plist";
/**
- * Generates a full path for the test file with the given name.
+ * Generates an absolute path for the test file with the given name.
*
* @param name the name of the test file
* @return the full path to this file
*/
- private static String filePath(final String name)
+ private static String absolutePath(final String name)
{
return ConfigurationAssert.getTestFile(name).getAbsolutePath();
}
@@ -126,7 +129,7 @@ public class TestConfigurations
public void testFileBasedBuilderWithPath()
{
final Configurations configs = new Configurations();
- final String filePath = filePath(TEST_PROPERTIES);
+ final String filePath = absolutePath(TEST_PROPERTIES);
final FileBasedConfigurationBuilder<PropertiesConfiguration> builder =
configs.fileBasedBuilder(PropertiesConfiguration.class,
filePath);
@@ -179,7 +182,7 @@ public class TestConfigurations
final Configurations configs = new Configurations();
final PropertyListConfiguration config =
configs.fileBased(PropertyListConfiguration.class,
- filePath(TEST_PLIST));
+ absolutePath(TEST_PLIST));
checkPList(config);
}
@@ -256,11 +259,89 @@ public class TestConfigurations
{
final Configurations configs = new Configurations();
final FileBasedConfigurationBuilder<PropertiesConfiguration> builder =
- configs.propertiesBuilder(filePath(TEST_PROPERTIES));
+ configs.propertiesBuilder(absolutePath(TEST_PROPERTIES));
checkProperties(builder.getConfiguration());
}
/**
+ * Tests whether a builder for a properties configuration can be created for
+ * a given file path when an include is not found.
+ */
+ @Test
+ public void testPropertiesBuilderFromPathIncludeNotFoundFail() throws ConfigurationException
+ {
+ final Configurations configs = new Configurations();
+ final FileBasedConfigurationBuilder<PropertiesConfiguration> builder =
+ configs.propertiesBuilder(absolutePath("include-not-found.properties"));
+ try
+ {
+ builder.getConfiguration();
+ Assert.fail("Expected ConfigurationException");
+ }
+ catch (ConfigurationException e) {
+ // ignore
+ }
+ }
+
+ /**
+ * Tests whether a builder for a properties configuration can be created for
+ * a given file path when an include is not found.
+ */
+ @Test
+ public void testPropertiesBuilderFromPathIncludeNotFoundPass() throws ConfigurationException
+ {
+ final Configurations configs = new Configurations();
+ final String absPath = absolutePath("include-not-found.properties");
+ final FileBasedConfigurationBuilder<PropertiesConfiguration> builderFail =
+ configs.propertiesBuilder(absPath);
+ // Expect failure:
+ try
+ {
+ builderFail.getConfiguration();
+ Assert.fail("Expected ConfigurationException");
+ }
+ catch (ConfigurationException e)
+ {
+ // Ignore
+ // e.printStackTrace();
+ }
+ // Expect failure:
+ try
+ {
+ configs.properties(absPath);
+ }
+ catch (ConfigurationException e) {
+ // Ignore
+ // e.printStackTrace();
+ }
+ {
+ // Expect success:
+ // @formatter:off
+ final Map<String, Object> map =
+ new Parameters().properties()
+ .setPath(absPath)
+ .setIncludeListener(PropertiesConfiguration.NOOP_INCLUDE_LISTENER)
+ .getParameters();
+ // @formatter:on
+ final BasicConfigurationBuilder<PropertiesConfiguration> builderOk = configs.propertiesBuilder(absPath)
+ .addParameters(map);
+ final PropertiesConfiguration configuration = builderOk.getConfiguration();
+ assertEquals("valueA", configuration.getString("keyA"));
+ }
+ {
+ // Expect success:
+ // @formatter:off
+ final BasicConfigurationBuilder<PropertiesConfiguration> builderOk = configs.propertiesBuilder(
+ new Parameters().properties()
+ .setPath(absPath)
+ .setIncludeListener(PropertiesConfiguration.NOOP_INCLUDE_LISTENER));
+ // @formatter:on
+ final PropertiesConfiguration configuration = builderOk.getConfiguration();
+ assertEquals("valueA", configuration.getString("keyA"));
+ }
+ }
+
+ /**
* Tests whether a properties configuration can be loaded from a file path.
*/
@Test
@@ -268,7 +349,7 @@ public class TestConfigurations
{
final Configurations configs = new Configurations();
final PropertiesConfiguration config =
- configs.properties(filePath(TEST_PROPERTIES));
+ configs.properties(absolutePath(TEST_PROPERTIES));
checkProperties(config);
}
@@ -341,7 +422,7 @@ public class TestConfigurations
{
final Configurations configs = new Configurations();
final FileBasedConfigurationBuilder<XMLConfiguration> builder =
- configs.xmlBuilder(filePath(TEST_XML));
+ configs.xmlBuilder(absolutePath(TEST_XML));
checkXML(builder.getConfiguration());
}
@@ -352,7 +433,7 @@ public class TestConfigurations
public void testXMLFromPath() throws ConfigurationException
{
final Configurations configs = new Configurations();
- final XMLConfiguration config = configs.xml(filePath(TEST_XML));
+ final XMLConfiguration config = configs.xml(absolutePath(TEST_XML));
checkXML(config);
}
@@ -425,7 +506,7 @@ public class TestConfigurations
{
final Configurations configs = new Configurations();
final FileBasedConfigurationBuilder<INIConfiguration> builder =
- configs.iniBuilder(filePath(TEST_INI));
+ configs.iniBuilder(absolutePath(TEST_INI));
checkINI(builder.getConfiguration());
}
@@ -436,7 +517,7 @@ public class TestConfigurations
public void testINIFromPath() throws ConfigurationException
{
final Configurations configs = new Configurations();
- final INIConfiguration config = configs.ini(filePath(TEST_INI));
+ final INIConfiguration config = configs.ini(absolutePath(TEST_INI));
checkINI(config);
}
@@ -512,7 +593,7 @@ public class TestConfigurations
{
final Configurations configs = new Configurations();
final CombinedConfigurationBuilder builder =
- configs.combinedBuilder(filePath(TEST_COMBINED));
+ configs.combinedBuilder(absolutePath(TEST_COMBINED));
checkCombined(builder.getConfiguration());
}
@@ -524,7 +605,7 @@ public class TestConfigurations
{
final Configurations configs = new Configurations();
final CombinedConfiguration config =
- configs.combined(filePath(TEST_COMBINED));
+ configs.combined(absolutePath(TEST_COMBINED));
checkCombined(config);
}
}
diff --git a/src/test/java/org/apache/commons/configuration2/builder/fluent/TestParameters.java b/src/test/java/org/apache/commons/configuration2/builder/fluent/TestParameters.java
index 50f52b7..03d0785 100644
--- a/src/test/java/org/apache/commons/configuration2/builder/fluent/TestParameters.java
+++ b/src/test/java/org/apache/commons/configuration2/builder/fluent/TestParameters.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import org.apache.commons.configuration2.ConfigurationConsumer;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.BasicBuilderParameters;
import org.apache.commons.configuration2.builder.BasicBuilderProperties;
@@ -35,6 +36,7 @@ import org.apache.commons.configuration2.builder.FileBasedBuilderParametersImpl;
import org.apache.commons.configuration2.builder.combined.CombinedBuilderParametersImpl;
import org.apache.commons.configuration2.builder.combined.MultiFileBuilderParametersImpl;
import org.apache.commons.configuration2.convert.ListDelimiterHandler;
+import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.tree.ExpressionEngine;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
@@ -272,11 +274,19 @@ public class TestParameters
{
final PropertiesConfiguration.IOFactory factory =
EasyMock.createMock(PropertiesConfiguration.IOFactory.class);
+ final ConfigurationConsumer<ConfigurationException> includeListener =
+ EasyMock.createMock(ConfigurationConsumer.class);
+ // @formatter:off
final Map<String, Object> map =
- new Parameters().properties().setThrowExceptionOnMissing(true)
- .setFileName("test.properties").setIOFactory(factory)
- .setListDelimiterHandler(listHandler).setIncludesAllowed(false)
+ new Parameters().properties()
+ .setThrowExceptionOnMissing(true)
+ .setFileName("test.properties")
+ .setIncludeListener(includeListener)
+ .setIOFactory(factory)
+ .setListDelimiterHandler(listHandler)
+ .setIncludesAllowed(false)
.getParameters();
+ // @formatter:on
checkBasicProperties(map);
final FileBasedBuilderParametersImpl fbp =
FileBasedBuilderParametersImpl.fromParameters(map);
@@ -284,6 +294,7 @@ public class TestParameters
.getFileName());
assertEquals("Wrong includes flag", Boolean.FALSE,
map.get("includesAllowed"));
+ assertSame("Wrong include listener", includeListener, map.get("includeListener"));
assertSame("Wrong factory", factory, map.get("IOFactory"));
}
diff --git a/src/test/resources/include-cyclical-reference.properties b/src/test/resources/include-cyclical-reference.properties
new file mode 100644
index 0000000..7a5ccf4
--- /dev/null
+++ b/src/test/resources/include-cyclical-reference.properties
@@ -0,0 +1,16 @@
+# 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.
+include = src/test/resources/include-cyclical-reference.properties
+keyA = valueA
diff --git a/src/test/resources/include-include-not-found.properties b/src/test/resources/include-include-not-found.properties
new file mode 100644
index 0000000..d0c400c
--- /dev/null
+++ b/src/test/resources/include-include-not-found.properties
@@ -0,0 +1,16 @@
+# 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.
+include = include-not-found.properties
+keyB = valueB
diff --git a/src/test/resources/include-load-exception.properties b/src/test/resources/include-load-exception.properties
new file mode 100644
index 0000000..87334cb
--- /dev/null
+++ b/src/test/resources/include-load-exception.properties
@@ -0,0 +1,16 @@
+# 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.
+include = http://this-file-does-not-and-should-not-exist.txt
+keyA = valueA
diff --git a/src/test/resources/include-not-found.properties b/src/test/resources/include-not-found.properties
new file mode 100644
index 0000000..056c086
--- /dev/null
+++ b/src/test/resources/include-not-found.properties
@@ -0,0 +1,16 @@
+# 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.
+include = this-file-does-not-and-should-not-exist.txt
+keyA = valueA