Skip to content
Permalink
Browse files
Fixing event handling. Adding documentation.
  • Loading branch information
effrafax committed Dec 12, 2019
1 parent 258d3a6 commit cc0652463d961c71983689e00947fdf1ffe12f06
Showing 5 changed files with 161 additions and 29 deletions.
@@ -25,9 +25,24 @@
import java.util.Properties;

/**
* The Plexus registry is a single source of external configuration for Plexus components and applications.
* The 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.
*
* The configuration is stored hierarchically and each entry can be identified by a key.
* The standard notation for keys should be a dot separated string, where each dot represents a connection
* from parent to child node.
*
* The configuration can be combined from different sources. The sources are either defined during initialization
* of the concrete implementation or can be added by the <code>addConfigurationXXX()</code> methods.
*
* If you combine the configuration from different sources, you should modify the configuration from the
* sub configuration, which can be get by the {@link #getSection(String)} method. Because depending on the
* implementation the changes may not be persisted, if you change the combined tree.
*
* The standard implementation uses apache commons configuration 2 for storing the configuration.
* For implementation details see notes in <code>CommonsConfigurationRegistry</code>
*
*/
public interface Registry
{
@@ -117,7 +132,8 @@
void setBoolean( String key, boolean value );

/**
* Load configuration from the given classloader resource.
* Add a configuration source to the combined configuration. Load the file from the
* given resource string.
*
* @param resource the location to load the configuration from
* @throws RegistryException if a problem occurred reading the resource to add to the registry
@@ -126,17 +142,18 @@ void addConfigurationFromResource( String resource )
throws RegistryException;

/**
* Load configuration from the given classloader resource.
* Add a configuration source to the combined configuration and load configuration from the given classloader resource.
* The configuration source is added at the given prefix in the tree.
*
* @param resource the location to load the configuration from
* @param prefix the location to add the configuration at in the registry
* @param prefix the key prefix where the root node of the configuration is placed
* @throws RegistryException if a problem occurred reading the resource to add to the registry
*/
void addConfigurationFromResource( String resource, String prefix )
throws RegistryException;

/**
* Load configuration from the given file.
* Add a configuration source to the combined configuration and load it from the given file.
*
* @param file the location to load the configuration from
* @throws RegistryException if a problem occurred reading the resource to add to the registry
@@ -145,15 +162,27 @@ void addConfigurationFromFile( Path file )
throws RegistryException;

/**
* Load configuration from the given file.
* Add the configuration source to the combined configuration and load from the given file.
*
* @param file the location to load the configuration from
* @param prefix the location to add the configuration at in the registry
* @param prefix the key prefix where the root node of the configuration is placed
* @throws RegistryException if a problem occurred reading the resource to add to the registry
*/
void addConfigurationFromFile( Path file, String prefix )
throws RegistryException;


/**
* Add the configuration source to the combined configuration and load from the given file.
* Use the given name for referencing the configuration.
*
* @param file the location to load the configuration from
* @param prefix the key prefix where the root node of the configuration is placed
* @param name the name of the configuration
* @throws RegistryException if a problem occurred reading the resource to add to the registry
*/
void addConfigurationFromFile( Path file, String name, String prefix ) throws RegistryException;

/**
* Determine if the registry contains any elements.
*
@@ -216,6 +245,8 @@ void addConfigurationFromFile( Path file, String prefix )
/**
* Get a subsection of the registry, identified by the given name. If it doesn't exist, <code>null</code> will be
* returned.
* Subsections should be used to modify configurations. The name of the subsection depends on the implementation
* and the concrete initalization.
*
* @param name registry section name
* @return the registry
@@ -224,6 +255,9 @@ void addConfigurationFromFile( Path file, String prefix )

/**
* Save any changes to the registry since it was loaded.
* Be careful with the save method for combined configurations. It may be that changes are not written to
* disk or to a different file as expected. How and if changes from a combined configuration are written
* to disk depends on the implementation.
*
* @throws RegistryException if there was a problem saving the registry
* @throws UnsupportedOperationException if the registry is not writable
@@ -235,21 +269,21 @@ void save( )
* Add a change listener. Note that settings this on the base registry will only detect 'invalidation' events, not
* individual changes. You should retrieve the named sub-registry to listen for changes.
*
* TODO: this isn't ideal, so maybe fix combined configuration to re-fire it's events to it's own listeners in the c-c implementation
*
* @param listener the listener
*/
void addChangeListener( RegistryListener listener );

/**
* @param listener
* @return <code>true</code> if has been removed
* Remove the change listener, if it was registered before.
*
* @param listener the registered listener, that should be removed
* @return <code>true</code> if has been removed, otherwise <code>false</code>
* @since 2.3
*/
boolean removeChangeListener( RegistryListener listener );

/**
* Get all the keys in this registry. Keys are only retrieved at a depth of 1.
* Get the first level keys in this registry.
*
* @return the set of keys
*/
@@ -48,6 +48,14 @@
<artifactId>commons-configuration2</artifactId>
<version>${commons.configuration.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>

<dependency>
<groupId>javax.annotation</groupId>
@@ -75,24 +83,12 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
@@ -509,7 +509,7 @@ public void addConfigurationFromFile( Path file )
* @throws RegistryException if the configuration is not a <code>CombinedConfiguration</code>
*/
@Override
public void addConfigurationFromFile( Path file, String prefix )
public void addConfigurationFromFile( Path file, String name, String prefix )
throws RegistryException
{
CombinedConfiguration configuration = (CombinedConfiguration) this.configuration;
@@ -518,8 +518,11 @@ public void addConfigurationFromFile( Path file, String prefix )
try
{
logger.debug( "Loading properties configuration from file: {}", file );
if (configuration.getConfigurationNames( ).contains( name )) {
configuration.removeConfiguration( prefix );
}
Configurations configurations = new Configurations( );
configuration.addConfiguration( configurations.properties( file.toFile() ), prefix, prefix );
configuration.addConfiguration( configurations.properties( file.toFile() ), name, prefix );
}
catch ( ConfigurationException e )
{
@@ -532,8 +535,11 @@ else if ( file.getFileName( ).toString( ).endsWith( ".xml" ) )
try
{
logger.debug( "Loading XML configuration from file: {}", file );
if (configuration.getConfigurationNames( ).contains( name )) {
configuration.removeConfiguration( prefix );
}
Configurations configurations = new Configurations( );
configuration.addConfiguration( configurations.xml( file.toFile() ), prefix, prefix );
configuration.addConfiguration( configurations.xml( file.toFile() ), name, prefix );
}
catch ( ConfigurationException e )
{
@@ -548,6 +554,12 @@ else if ( file.getFileName( ).toString( ).endsWith( ".xml" ) )
}
}

@Override
public void addConfigurationFromFile( Path file, String prefix ) throws RegistryException
{
addConfigurationFromFile( file, prefix, prefix );
}


/**
* This method tries to read a combined configuration definition either from the string given
@@ -24,13 +24,18 @@
import org.apache.commons.configuration2.event.ConfigurationEvent;
import org.apache.commons.configuration2.event.Event;
import org.apache.commons.configuration2.event.EventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Commons configuration listener that delegates to the given registry listener.
*/
public class ConfigurationListenerDelegate
implements EventListener
{

private static final Logger log = LoggerFactory.getLogger( ConfigurationListenerDelegate.class );

/**
* Delegate listener.
*/
@@ -69,10 +74,15 @@ public boolean equals( Object obj )
@Override
public void onEvent( Event event ) {
// Do nothing
log.debug( "Event {}", event );
if (event instanceof ConfigurationEvent) {
onEvent( (ConfigurationEvent) event );
}
}

public void onEvent( ConfigurationEvent event )
{
log.debug( "Configuration event {}", event );
if ( event.isBeforeUpdate())
{
listener.beforeConfigurationChange( registry, event.getPropertyName( ), event.getPropertyValue( ) );
@@ -31,6 +31,7 @@

import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -370,22 +371,101 @@ public void testSaveSection( )

}

@Test
public void testChangeListener() throws Exception
{
registry = getRegistry( "builder" );
MockChangeListener listener = new MockChangeListener( );
registry.addChangeListener( listener );

registry.setInt( "test.key", 100 );
registry.setBoolean( "test.boolean.first", false );
registry.setBoolean( "test.boolean.second", true );
registry.setString( "test.string", "test 1020" );

assertEquals( 4, listener.getBeforeEvents( ).size( ) );
assertEquals( 4, listener.getAfterEvents( ).size( ) );

assertEquals( registry, listener.getBeforeEvents( ).get( 0 ).getRegistry( ) );
assertEquals( "test.key", listener.getBeforeEvents( ).get( 0 ).getPropertyName( ) );
assertEquals( 100, listener.getBeforeEvents( ).get( 0 ).getPropertyValue( ) );
assertEquals( 100, listener.getAfterEvents( ).get( 0 ).getPropertyValue( ) );

assertEquals( registry, listener.getBeforeEvents( ).get( 1 ).getRegistry( ) );
assertEquals( "test.boolean.first", listener.getBeforeEvents( ).get( 1 ).getPropertyName( ) );
assertEquals( false, listener.getBeforeEvents( ).get( 1 ).getPropertyValue( ) );
assertEquals( false, listener.getAfterEvents( ).get( 1 ).getPropertyValue( ) );

assertEquals( registry, listener.getBeforeEvents( ).get( 2 ).getRegistry( ) );
assertEquals( "test.boolean.second", listener.getBeforeEvents( ).get( 2 ).getPropertyName( ) );
assertEquals( true, listener.getBeforeEvents( ).get( 2 ).getPropertyValue( ) );
assertEquals( true, listener.getAfterEvents( ).get( 2 ).getPropertyValue( ) );

assertEquals( registry, listener.getBeforeEvents( ).get( 3 ).getRegistry( ) );
assertEquals( "test.string", listener.getBeforeEvents( ).get( 3 ).getPropertyName( ) );
assertEquals( "test 1020", listener.getBeforeEvents( ).get( 3 ).getPropertyValue( ) );
assertEquals( "test 1020", listener.getAfterEvents( ).get( 3 ).getPropertyValue( ) );

}


private static class ChangeEvent {
private Registry registry;
private String propertyName;
private Object propertyValue;

public ChangeEvent( Registry registry, String propertyName, Object propertyValue )
{
this.registry = registry;
this.propertyName = propertyName;
this.propertyValue = propertyValue;
}

public Object getPropertyValue( )
{
return propertyValue;
}

public Registry getRegistry( )
{
return registry;
}

public String getPropertyName( )
{
return propertyName;
}


}


private static class MockChangeListener
implements RegistryListener
{
List<ChangeEvent> beforeEvents = new ArrayList<>( );
List<ChangeEvent> afterEvents = new ArrayList<>( );

@Override
public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
{
// no op
beforeEvents.add( new ChangeEvent( registry, propertyName, propertyValue ) );
}

@Override
public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
{
// no op
afterEvents.add( new ChangeEvent( registry, propertyName, propertyValue ) );
}

public List<ChangeEvent> getAfterEvents( )
{
return afterEvents;
}

public List<ChangeEvent> getBeforeEvents( )
{
return beforeEvents;
}
}
}

0 comments on commit cc06524

Please sign in to comment.