Improving config registry and new tests

This commit is contained in:
Martin Stockhammer 2019-02-15 22:54:56 +01:00
parent 81816de77f
commit 5ba0a371c5
9 changed files with 200 additions and 242 deletions

21
pom.xml
View File

@ -670,6 +670,27 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.9.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -106,6 +106,22 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -52,6 +52,8 @@ import java.net.URL;
import java.nio.file.Path;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
/**
* Implementation of the registry component using
@ -67,6 +69,8 @@ import java.util.regex.Pattern;
public class CommonsConfigurationRegistry
implements ConfigRegistry
{
private static final Pattern DOT_NAME_PATTERN = Pattern.compile( "([^.]+)(\\..*)*" );
/**
* The combined configuration instance that houses the registry.
*/
@ -81,6 +85,7 @@ public class CommonsConfigurationRegistry
private String propertyDelimiter = ".";
private boolean addSystemProperties = false;
/**
* The configuration properties for the registry. This should take the format of an input to the Commons
@ -261,35 +266,18 @@ public class CommonsConfigurationRegistry
public Collection<String> getKeys()
{
Set<String> keys = new HashSet<String>( );
Iterable<String> iterable = () -> configuration.getKeys( );
return StreamSupport.stream( iterable.spliterator( ), false )
.map( k -> DOT_NAME_PATTERN.matcher( k ) )
.filter( k -> k.matches( ) )
.map( k -> k.group( 1 ) ).collect( Collectors.toSet( ) );
for ( Iterator<String> i = configuration.getKeys( ); i.hasNext( ); )
{
String key = i.next( );
int index = key.indexOf( '.' );
if ( index < 0 )
{
keys.add( key );
} else
{
keys.add( key.substring( 0, index ) );
}
}
return keys;
}
public Collection getFullKeys()
{
Set<String> keys = new HashSet<String>( );
for ( Iterator<String> i = configuration.getKeys( ); i.hasNext( ); )
{
keys.add( i.next( ) );
}
return keys;
Iterable<String> iterable = () -> configuration.getKeys( );
return StreamSupport.stream( iterable.spliterator( ), false ).collect( Collectors.toSet( ) );
}
public void remove(String key)
@ -491,7 +479,8 @@ public class CommonsConfigurationRegistry
this.content = content;
}
StringFileSystem(String encoding, String content) {
StringFileSystem(String encoding, String content)
{
this.encoding = encoding;
this.content = content;
}
@ -579,9 +568,7 @@ public class CommonsConfigurationRegistry
CombinedConfiguration configuration;
if ( StringUtils.isNotBlank( combinedConfigurationDefinition ) )
{
// This part is mainly for backwards compatibility.
// It allows to use system properties in the XML declaration.
String interpolatedProps;
Parameters params = new Parameters( );
DefaultExpressionEngineSymbols symbols = new DefaultExpressionEngineSymbols.Builder( DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS )
.setPropertyDelimiter( propertyDelimiter )
@ -590,8 +577,11 @@ public class CommonsConfigurationRegistry
.setEscapedDelimiter( "\\" + propertyDelimiter )
.create( );
DefaultExpressionEngine expressionEngine = new DefaultExpressionEngine( symbols );
// It allows to use system properties in the XML declaration.
ConfigurationInterpolator interpolator = ConfigurationInterpolator.fromSpecification( new InterpolatorSpecification.Builder( ).withDefaultLookup( DefaultLookups.SYSTEM_PROPERTIES.getLookup( ) ).create( ) );
String interpolatedProps = interpolator.interpolate( combinedConfigurationDefinition ).toString( );
interpolatedProps = interpolator.interpolate( combinedConfigurationDefinition ).toString( );
logger.debug( "Loading configuration into commons-configuration, xml {}", interpolatedProps );
// This is the builder configuration for the XML declaration, that contains the definition
// for the sources that are used for the CombinedConfiguration.
@ -600,7 +590,6 @@ public class CommonsConfigurationRegistry
new FileBasedConfigurationBuilder<>(
XMLConfiguration.class )
.configure( params.xml( )
.setInterpolator( interpolator )
.setFileSystem( fs )
.setFileName( "config.xml" )
.setListDelimiterHandler(
@ -624,14 +613,17 @@ public class CommonsConfigurationRegistry
}
// In the end, we add the system properties to the combined configuration
configuration.addConfiguration( new SystemConfiguration( ), "SystemProperties" );
if ( addSystemProperties )
{
configuration.addConfiguration( new SystemConfiguration( ), "SystemProperties" );
}
this.configuration = configuration;
}
catch ( ConfigurationException e )
{
logger.error("Fatal error, while reading the configuration definition: "+e.getMessage());
logger.error("The definition was:");
logger.error( "Fatal error, while reading the configuration definition: " + e.getMessage( ) );
logger.error( "The definition was:" );
logger.error( combinedConfigurationDefinition );
throw new RuntimeException( e.getMessage( ), e );
}
@ -662,4 +654,26 @@ public class CommonsConfigurationRegistry
{
this.configurationBuilder = configurationBuilder;
}
/**
* Returns true, if the system properties are added to the base configuration. Otherwise system properties
* can be interpolated by ${sys:var} syntax.
*
* @return
*/
public boolean isAddSystemProperties()
{
return addSystemProperties;
}
/**
* Set to true, if the system properties should be added to the base configuration.
* If set to false, system properties are no direct part of the configuration.
*
* @param addSystemProperties
*/
public void setAddSystemProperties(boolean addSystemProperties)
{
this.addSystemProperties = addSystemProperties;
}
}

View File

@ -52,10 +52,16 @@ public abstract class AbstractRegistryTest
return getRegistry( getRoleHint() );
}
public ConfigRegistry getRegistry( String name )
public ConfigRegistry getRegistry( String name ) throws Exception
{
return getRegistry(name, false);
}
public ConfigRegistry getRegistry( String name , boolean addSysProps )
throws Exception
{
ConfigRegistry registry = applicationContext.getBean( name, ConfigRegistry.class );
CommonsConfigurationRegistry registry = applicationContext.getBean( name, CommonsConfigurationRegistry.class );
registry.setAddSystemProperties( addSysProps );
registry.initialize();
return registry;
}

View File

@ -33,11 +33,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.rmi.registry.Registry;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.*;
/**
* Test the commons configuration registry.
@ -70,7 +66,7 @@ public class CommonsConfigurationRegistryTest
public void testDefaultConfiguration()
throws Exception
{
registry = getRegistry( "default" );
registry = getRegistry( "default" , true);
assertEquals( "Check system property override", System.getProperty( "user.dir" ),
registry.getString( "user.dir" ) );
@ -78,11 +74,36 @@ public class CommonsConfigurationRegistryTest
assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) );
}
@Test
public void testGetKeys() throws Exception
{
registry = getRegistry( "builder" );
Collection<String> keys = registry.getKeys( );
HashSet<Object> expectedKeySet = new HashSet<>( );
expectedKeySet.add("test");
expectedKeySet.add("repository");
expectedKeySet.add("objects");
expectedKeySet.add("properties");
expectedKeySet.add("strings");
expectedKeySet.add("user");
expectedKeySet.add("foo");
expectedKeySet.add("string");
expectedKeySet.add("boolean");
expectedKeySet.add("subOne");
expectedKeySet.add( "two" );
assertEquals( expectedKeySet, keys );
expectedKeySet.clear();
}
@Test
public void testBuilderConfiguration()
throws Exception
{
registry = getRegistry( "builder" );
registry = getRegistry( "builder", true );
assertEquals( "Check system property override", "new user dir", registry.getString( "user.dir" ) );
assertEquals( "Check system property default", System.getProperty( "user.home" ),
@ -99,7 +120,8 @@ public class CommonsConfigurationRegistryTest
registry = getRegistry( "default" );
String dump = registry.dump();
assertTrue( dump.startsWith( "Configuration Dump.\n\"" ) );
System.out.println( dump );
assertTrue( dump.startsWith( "Configuration Dump." ) );
}
@Test
@ -140,7 +162,7 @@ public class CommonsConfigurationRegistryTest
public void testInterpolation()
throws Exception
{
registry = getRegistry( "builder" );
registry = getRegistry( "builder" , true );
assertEquals( "Check system property interpolation", System.getProperty( "user.home" ) + "/.m2/repository",
registry.getString( "repository" ) );
@ -153,7 +175,7 @@ public class CommonsConfigurationRegistryTest
public void testAddConfigurationXmlFile()
throws Exception
{
registry = getRegistry( "default" );
registry = getRegistry( "default" , true);
registry.addConfigurationFromFile( "test.xml", Paths.get( "src/test/resources/test.xml" ) );
assertEquals( "Check system property default", System.getProperty( "user.dir" ),
@ -165,7 +187,7 @@ public class CommonsConfigurationRegistryTest
public void testAddConfigurationPropertiesFile()
throws Exception
{
registry = getRegistry( "default" );
registry = getRegistry( "default", true );
registry.addConfigurationFromFile(
"test.properties", Paths.get("src/test/resources/test.properties" ) );
@ -180,7 +202,7 @@ public class CommonsConfigurationRegistryTest
public void testAddConfigurationXmlResource()
throws Exception
{
registry = getRegistry( "default" );
registry = getRegistry( "default" , true);
registry.addConfigurationFromResource( "test.xml-r", "test.xml" );
@ -193,7 +215,7 @@ public class CommonsConfigurationRegistryTest
public void testAddConfigurationPropertiesResource()
throws Exception
{
registry = getRegistry( "default" );
registry = getRegistry( "default", true );
registry.addConfigurationFromResource( "test.properties-r", "test.properties" );
@ -235,12 +257,21 @@ public class CommonsConfigurationRegistryTest
public void testIsEmpty()
throws Exception
{
registry = getRegistry( "default" );
registry = getRegistry( "default", true );
assertFalse( registry.isEmpty() );
assertTrue( registry.getSubset( "foo" ).isEmpty() );
}
@Test
public void testIsEmptyWithoutSysProps()
throws Exception
{
registry = getRegistry( "default");
assertTrue( registry.isEmpty() );
}
@Test
public void testGetSubset()
throws Exception
@ -372,8 +403,6 @@ public class CommonsConfigurationRegistryTest
registry.remove( "listElements.listElement(1)" );
registry.save();
// @TODO: Migrate test implementation to commons config 2.4
FileBasedConfigurationBuilder<XMLConfiguration> builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class)
.configure( new Parameters().xml().setFile(dest.toFile()) );
XMLConfiguration configuration = builder.getConfiguration();

View File

@ -1,60 +0,0 @@
package org.apache.archiva.redback.common.config.acc2;
/*
* 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.
*/
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* Test component.
*/
public interface Component
{
String ROLE = Component.class.getName();
String getKey( );
Properties getProperties( );
String getConfigKey( );
Properties getConfigProperties( );
Map getMap( );
List getList( );
Map getConfigMap( );
List getConfigList( );
Properties getMergeProperties( );
int getNumber( );
int getConfigNumber( );
Nested getNested( );
Nested getConfigNested( );
List getMergeList( );
}

View File

@ -1,128 +0,0 @@
package org.apache.archiva.redback.common.config.acc2;
/*
* 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.
*/
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* Test component.
*/
public class DefaultComponent
implements Component
{
private String key;
private Properties properties;
private Map map;
private List list;
private String configKey;
private Properties configProperties;
private Map configMap;
private List configList;
private Properties mergeProperties;
private int number;
private int configNumber;
private Nested nested;
private Nested configNested;
private List mergeList;
public List getMergeList()
{
return mergeList;
}
public Nested getConfigNested()
{
return configNested;
}
public Nested getNested()
{
return nested;
}
public int getNumber()
{
return number;
}
public int getConfigNumber()
{
return configNumber;
}
public String getConfigKey()
{
return configKey;
}
public Properties getConfigProperties()
{
return configProperties;
}
public String getKey()
{
return key;
}
public Properties getProperties()
{
return properties;
}
public Map getMap()
{
return map;
}
public List getList()
{
return list;
}
public Map getConfigMap()
{
return configMap;
}
public List getConfigList()
{
return configList;
}
public Properties getMergeProperties()
{
return mergeProperties;
}
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
~ 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.
-->
<configuration > <!-- status="debug" -->
<appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="%highlight{%d{HH:mm:ss.SSS} [%L] [%t] %-5level %logger{3} - %msg%n}" />
</Console>
</appenders>
<loggers>
<logger name="org.apache.cxf" level="info"/>
<logger name="org.springframework" level="error"/>
<logger name="org.apache.archiva.redback.components.cache" level="error"/>
<logger name="org.apache.archiva.redback.rest" level="error"/>
<logger name="org.apache.catalina" level="off" />
<logger name="JPOX" level="ERROR"/>
<root level="info">
<appender-ref ref="console"/>
</root>
</loggers>
</configuration>

View File

@ -28,8 +28,14 @@ import java.util.regex.Pattern;
/**
* The configuration registry is a single source of external configuration.
*
* It can be used by components to source configuration, knowing that it can be used from within applications
* without the information being hard coded into the component.
* Each configuration entry is accessible by a unique key. The keys may be hierarchical so, that
* you can build subsets of the configuration.
*
* A configuration may be combined by multiple sources. How the multiple sources are combined, is
* part of the implementation classes.
*
* You can register listeners that are notified, if the configuration changes. The syntax for filter
* of notifications is implementation specific.
*
*/
public interface ConfigRegistry
@ -124,6 +130,7 @@ public interface ConfigRegistry
/**
* Load configuration from the given classloader resource.
*
* @param name the unique name that identifies this configuration in the combined one
* @param resource the location to load the configuration from
* @throws RegistryException if a problem occurred reading the resource to add to the registry
*/
@ -133,6 +140,7 @@ public interface ConfigRegistry
/**
* Load configuration from the given classloader resource.
*
* @param name the unique name that identifies this configuration in the combined one
* @param resource the location to load the configuration from
* @param prefix the location to add the configuration at in the registry
* @throws RegistryException if a problem occurred reading the resource to add to the registry
@ -143,6 +151,7 @@ public interface ConfigRegistry
/**
* Load configuration from the given file.
*
* @param name the unique name that identifies this configuration in the combined one
* @param file the location to load the configuration from
* @throws RegistryException if a problem occurred reading the resource to add to the registry
*/
@ -152,6 +161,7 @@ public interface ConfigRegistry
/**
* Load configuration from the given file.
*
* @param name the unique name that identifies this configuration in the combined one
* @param file the location to load the configuration from
* @param prefix the location to add the configuration at in the registry
* @throws RegistryException if a problem occurred reading the resource to add to the registry
@ -202,7 +212,8 @@ public interface ConfigRegistry
* Get a configuration source part of the registry, identified by the given name. If it doesn't exist, <code>null</code> will be
* returned.
*
* Configurations can be combined from different sources. This gives the configuration of a specific source.
* Configurations can be combined from different sources. This returns the configuration of a specific source.
* The names are the ones given by the addConfiguration* methods or defined during the initialization process.
*
* @param name The source name of the configuration source.
* @return the The config registry object that represents this source part.
@ -260,5 +271,12 @@ public interface ConfigRegistry
*/
void removeSubset( String key );
/**
* Initializes the given registry. The definition for the configuration sources is
* implementation specific. Implementations should provide methods and/or constructors
* that allows to define the configuration source.
*
* @throws RegistryException if the initialization was not successful
*/
void initialize( ) throws RegistryException;
}