DatabaseConfigPropertiesResolver.java
/*
*
* The DbUnit Database Testing Framework
* Copyright (C)2002-2026, DbUnit.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package org.dbunit.annotation.runtime;
import java.util.Properties;
import org.dbunit.annotation.DbUnitConfig;
import org.dbunit.annotation.DbUnitProperty;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.DatabaseConfigPropertiesProvider;
/**
* Resolves {@code @DbUnitConfig}'s {@link DatabaseConfig} properties - its inline
* {@code properties()} {@link DbUnitProperty} entries, or the
* {@link DatabaseConfigPropertiesProvider} its {@code propertiesProvider()} names - into the
* {@link Properties} {@link AnnotatedTestConfiguration} carries.
*
* <p>Rejects setting both {@code properties()} and {@code propertiesProvider()} (through
* {@link ProvidedAttribute}, like every other "inline value or provider class" attribute), a
* {@code @DbUnitProperty} name declared more than once, and any name {@link DatabaseConfig} does
* not recognize - which {@link DatabaseConfig#setPropertiesByString(Properties)} would otherwise
* drop silently, leaving the test running with the misspelled property never applied.
*
* @author Jeff Jensen
* @since 3.6.0
*/
final class DatabaseConfigPropertiesResolver
{
/**
* Resolves the {@link DatabaseConfig} properties.
*
* @param config The resolved {@code @DbUnitConfig}, or {@code null} when absent.
* @return The resolved properties; empty when none were declared.
* @throws IllegalStateException If both {@code properties()} and {@code propertiesProvider()}
* are set, a {@code @DbUnitProperty} name is declared twice, a named provider
* cannot be instantiated or returns {@code null}, or a name is not a known
* {@link DatabaseConfig} property.
*/
Properties resolve(final DbUnitConfig config)
{
if (config == null)
{
return new Properties();
}
final DbUnitProperty[] properties = config.properties();
final boolean providerSet =
config.propertiesProvider() != DatabaseConfigPropertiesProvider.class;
ProvidedAttribute.rejectBothSet(properties.length > 0 && providerSet, "@DbUnitConfig",
"properties()", "propertiesProvider()", null);
return providerSet ? fromProvider(config) : fromInlineProperties(properties);
}
private Properties fromProvider(final DbUnitConfig config)
{
final Properties provided = ProvidedAttribute.requireProvided(
ReflectiveInstantiation
.instantiate(config.propertiesProvider(),
"DbUnitConfig.propertiesProvider")
.getDatabaseConfigProperties(),
DatabaseConfigPropertiesProvider.class.getSimpleName(),
config.propertiesProvider(), "DbUnitConfig.propertiesProvider",
"getDatabaseConfigProperties");
final Properties copy = new Properties();
copy.putAll(provided);
for (final String name : copy.stringPropertyNames())
{
requireKnownDatabaseConfigProperty(name, "DatabaseConfigPropertiesProvider "
+ config.propertiesProvider().getName());
}
return copy;
}
private Properties fromInlineProperties(final DbUnitProperty[] properties)
{
final Properties result = new Properties();
for (final DbUnitProperty property : properties)
{
if (result.containsKey(property.name()))
{
throw new IllegalStateException("@DbUnitConfig declares more than one"
+ " @DbUnitProperty named '" + property.name() + "'; declare at most"
+ " one per name.");
}
requireKnownDatabaseConfigProperty(property.name(), "@DbUnitConfig.properties()");
result.setProperty(property.name(), property.value());
}
return result;
}
/**
* Rejects a {@link DatabaseConfig} property name - from {@code @DbUnitProperty} or a
* {@link DatabaseConfigPropertiesProvider} - that {@link DatabaseConfig} does not recognize
* in either its long {@code http://www.dbunit.org/...} or short form. A typo would otherwise
* be dropped silently by {@link DatabaseConfig#setPropertiesByString(Properties)}, which
* only logs and moves on, leaving the test running with the misspelled property never
* applied.
*
* @param name The configured property name.
* @param source A description of what configured it, for the exception message.
*/
private static void requireKnownDatabaseConfigProperty(final String name,
final String source)
{
if (DatabaseConfig.findByName(name) == null
&& DatabaseConfig.findByShortName(name) == null)
{
throw new IllegalStateException("'" + name + "' (configured via " + source
+ ") is not a known dbUnit DatabaseConfig property name. Use its long"
+ " 'http://www.dbunit.org/...' form or its short form - e.g. 'batchSize',"
+ " 'caseSensitiveTableNames'; see DatabaseConfig.");
}
}
}