Adding classes for listener implementation

This commit is contained in:
Martin Stockhammer 2019-02-18 06:26:31 +01:00
parent 0366cbc7b9
commit 5cd2f362e9
11 changed files with 782 additions and 294 deletions

View File

@ -122,6 +122,12 @@
<artifactId>log4j-slf4j-impl</artifactId> <artifactId>log4j-slf4j-impl</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,257 @@
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 org.apache.archiva.redback.common.config.api.AsyncListener;
import org.apache.archiva.redback.common.config.api.ConfigRegistry;
import org.apache.archiva.redback.common.config.api.EventType;
import org.apache.archiva.redback.common.config.api.RegistryListener;
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;
import org.springframework.context.ApplicationContext;
import org.springframework.core.task.TaskExecutor;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.WeakHashMap;
/**
* This class maps apache commons configuration events into redback configuration events.
*
* @author Martin Stockhammer <martin_s@apache.org>
*/
public class CfgListener implements EventListener
{
ConfigRegistry registry;
Map<String, ListenerInfo> listeners = new LinkedHashMap<>( );
WeakHashMap<EventInfo, Object> oldValueStore = new WeakHashMap<>( );
Logger logger = LoggerFactory.getLogger( CfgListener.class );
CfgListener( ConfigRegistry registry )
{
this.registry = registry;
}
TaskExecutor defaultExecutor;
ApplicationContext applicationContext;
private final class ListenerInfo
{
final String prefix;
final RegistryListener listener;
final boolean async;
final TaskExecutor executor;
public ListenerInfo( String prefix, RegistryListener listener )
{
this.prefix = prefix;
this.listener = listener;
Class<? extends RegistryListener> clazz = listener.getClass( );
boolean async = clazz.isAnnotationPresent( AsyncListener.class );
try
{
AsyncListener classAnnotation = clazz.getAnnotation( AsyncListener.class );
AsyncListener methodAnnotation = clazz.getMethod( "handleConfigurationChangeEvent", ConfigRegistry.class, EventType.class, String.class, Object.class, Object.class ).getAnnotation( AsyncListener.class );
this.async = methodAnnotation != null || classAnnotation != null;
String executorString = methodAnnotation != null ? methodAnnotation.value( ) : ( classAnnotation != null ? classAnnotation.value( ) : null );
TaskExecutor newExec;
if ( executorString == null )
{
newExec = defaultExecutor;
}
else
{
newExec = applicationContext.getBean( executorString, TaskExecutor.class );
if ( newExec == null )
{
newExec = defaultExecutor;
}
}
this.executor = newExec;
}
catch ( NoSuchMethodException e )
{
throw new RuntimeException( "Fatal error! EventListener methods not found. Maybe you have the wrong version of EventLister in your classpath." );
}
}
}
private final class EventInfo
{
final org.apache.commons.configuration2.event.EventType type;
final String name;
final Object value;
EventInfo( org.apache.commons.configuration2.event.EventType type, String name, Object value )
{
this.type = type;
this.name = name;
this.value = value;
}
@Override
public int hashCode( )
{
return Objects.hash( type, name, value );
}
public boolean equals( EventInfo obj )
{
return Objects.equals( this.type, obj.type ) && Objects.equals( this.name, obj.name ) && Objects.equals( this.value, obj.value );
}
}
/**
* This method stores old values in the
* @param event
*/
public void onEvent( org.apache.commons.configuration2.event.ConfigurationEvent event )
{
logger.debug( "Event " + event.getClass( ).getName( ) + " Source Class: " + event.getSource( ).getClass( ).getName( ) );
logger.debug( "EventType " + event.getEventType( ) + ", EventProperty: " + event.getPropertyName( ) + ", EventValue: " + event.getPropertyValue( ) );
if ( event.isBeforeUpdate( ) )
{
logger.debug( "Event before update" );
Object oldValue = registry.getValue( event.getPropertyName( ) );
oldValueStore.put( new EventInfo( event.getEventType( ), event.getPropertyName( ), event.getPropertyValue( ) ), oldValue );
}
else
{
logger.debug( "Event after update" );
final EventType type = transformEventType( event.getEventType( ) );
final Object oldValue = oldValueStore.remove( new EventInfo( event.getEventType( ), event.getPropertyName( ), event.getPropertyValue( ) ) );
final String propertyName = event.getPropertyName();
final Object newValue = event.getPropertyValue();
listeners.entrySet( ).stream( ).filter( entry -> event.getPropertyName( ).startsWith( entry.getKey( ) ) ).forEach(
entry ->
callListener( entry.getValue(), type, propertyName, newValue, oldValue )
);
}
}
private void callListener(ListenerInfo li, EventType type, String propertyName, Object newValue, Object oldValue) {
try
{
if ( li.async )
{
li.executor.execute( ( ) -> li.listener.handleConfigurationChangeEvent( registry, type, propertyName, newValue, oldValue ) );
}
else
{
li.listener.handleConfigurationChangeEvent( registry, type, propertyName, newValue, oldValue );
}
} catch (Throwable ex) {
logger.error( "Listener exception occured: "+ex.getMessage(), ex);
// Exception is catched allow to call the other listeners.
}
}
private EventType transformEventType( org.apache.commons.configuration2.event.EventType<? extends Event> type )
{
if ( type.equals( ConfigurationEvent.ADD_PROPERTY ) )
{
return EventType.PROPERTY_ADDED;
}
else if ( type.equals( ConfigurationEvent.CLEAR_PROPERTY ) )
{
return EventType.PROPERTY_CLEARED;
}
else if ( type.equals( ConfigurationEvent.SET_PROPERTY ) )
{
return EventType.PROPERTY_SET;
}
else
{
return EventType.UNDEFINED;
}
}
@Override
public void onEvent( Event event )
{
if ( event instanceof ConfigurationEvent )
{
onEvent( (ConfigurationEvent) event );
}
else
{
logger.debug( "Event " + event.getClass( ).getName( ) + " Source Class: " + event.getSource( ).getClass( ).getName( ) );
logger.debug( "EventType " + event.getEventType( ) );
}
}
public void registerChangeListener( RegistryListener listener, String prefix )
{
listeners.put( prefix, new ListenerInfo( prefix, listener ) );
}
public boolean unregisterChangeListener( RegistryListener listener )
{
boolean found = false;
Iterator<Map.Entry<String, ListenerInfo>> it = listeners.entrySet( ).iterator( );
while ( it.hasNext( ) )
{
Map.Entry<String, ListenerInfo> e = it.next( );
if ( e.getValue( ).listener == listener )
{
it.remove( );
found = true;
}
}
return found;
}
public TaskExecutor getDefaultExecutor( )
{
return defaultExecutor;
}
public void setDefaultExecutor( TaskExecutor defaultExecutor )
{
this.defaultExecutor = defaultExecutor;
}
public ApplicationContext getApplicationContext( )
{
return applicationContext;
}
public void setApplicationContext( ApplicationContext applicationContext )
{
this.applicationContext = applicationContext;
}
}

View File

@ -28,7 +28,10 @@ import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder; import org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters; import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler; import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
import org.apache.commons.configuration2.event.ConfigurationEvent;
import org.apache.commons.configuration2.event.EventSource;
import org.apache.commons.configuration2.ex.ConfigurationException; import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.apache.commons.configuration2.interpol.ConfigurationInterpolator; import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
import org.apache.commons.configuration2.interpol.DefaultLookups; import org.apache.commons.configuration2.interpol.DefaultLookups;
import org.apache.commons.configuration2.interpol.InterpolatorSpecification; import org.apache.commons.configuration2.interpol.InterpolatorSpecification;
@ -51,6 +54,7 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
@ -65,9 +69,9 @@ import java.util.stream.StreamSupport;
* <a href="http://commons.apache.org/commons/configuration/howto_configurationbuilder.html">configuration * <a href="http://commons.apache.org/commons/configuration/howto_configurationbuilder.html">configuration
* builder</a>. * builder</a>.
*/ */
@Service("acc2-configuration") @Service( "acc2-configuration" )
public class CommonsConfigurationRegistry public class CommonsConfigurationRegistry
implements ConfigRegistry implements ConfigRegistry
{ {
private static final Pattern DOT_NAME_PATTERN = Pattern.compile( "([^.]+)(\\..*)*" ); private static final Pattern DOT_NAME_PATTERN = Pattern.compile( "([^.]+)(\\..*)*" );
@ -78,15 +82,17 @@ public class CommonsConfigurationRegistry
private ConfigurationBuilder<? extends Configuration> configurationBuilder; private ConfigurationBuilder<? extends Configuration> configurationBuilder;
boolean combined = true; private boolean combined = true;
private Map<String, ConfigurationBuilder<? extends Configuration>> builderMap = new HashMap<>( ); private final Map<String, ConfigurationBuilder<? extends Configuration>> builderMap = new HashMap<>( );
private Logger logger = LoggerFactory.getLogger( getClass( ) ); private final Logger logger = LoggerFactory.getLogger( getClass( ) );
private String propertyDelimiter = "."; private String propertyDelimiter = ".";
private boolean addSystemProperties = false; private boolean addSystemProperties = false;
final CfgListener listener = new CfgListener( this );
/** /**
* The configuration properties for the registry. This should take the format of an input to the Commons * The configuration properties for the registry. This should take the format of an input to the Commons
* Configuration * Configuration
@ -96,12 +102,13 @@ public class CommonsConfigurationRegistry
private String combinedConfigurationDefinition; private String combinedConfigurationDefinition;
public CommonsConfigurationRegistry() public CommonsConfigurationRegistry( )
{ {
// Default constructor // Default constructor
} }
public CommonsConfigurationRegistry(CombinedConfiguration configuration, ConfigurationBuilder<? extends Configuration> configurationBuilder)
public CommonsConfigurationRegistry( CombinedConfiguration configuration, CombinedConfigurationBuilder configurationBuilder )
{ {
if ( configuration == null ) if ( configuration == null )
{ {
@ -112,76 +119,120 @@ public class CommonsConfigurationRegistry
throw new NullPointerException( "configuration builder cannot be null for a combined configuration" ); throw new NullPointerException( "configuration builder cannot be null for a combined configuration" );
} }
this.combined = true; this.combined = true;
this.configuration = configuration; setConfiguration(configuration);
this.configurationBuilder = configurationBuilder; this.configurationBuilder = configurationBuilder;
} }
public CommonsConfigurationRegistry(Configuration configuration, ConfigurationBuilder<? extends Configuration> configurationBuilder) @SuppressWarnings( "WeakerAccess" )
public CommonsConfigurationRegistry( Configuration configuration, ConfigurationBuilder<? extends Configuration> configurationBuilder )
{ {
if ( configuration == null ) if ( configuration == null )
{ {
throw new NullPointerException( "configuration can not be null" ); throw new NullPointerException( "configuration can not be null" );
} }
this.configuration = configuration; setConfiguration(configuration);
this.configurationBuilder = configurationBuilder; this.configurationBuilder = configurationBuilder;
} if (configuration instanceof CombinedConfiguration) {
this.combined = true;
public String dump()
{
StringBuilder buffer = new StringBuilder( );
buffer.append( "Configuration Dump." );
for ( Iterator i = configuration.getKeys( ); i.hasNext( ); )
{
String key = ( String ) i.next( );
Object value = configuration.getProperty( key );
buffer.append( "\n\"" ).append( key ).append( "\" = \"" ).append( value ).append( "\"" );
} }
return buffer.toString( );
} }
public boolean isEmpty() public void setConfiguration( Configuration configuration )
{
this.configuration = configuration;
if (configuration instanceof EventSource ) {
EventSource evs = (EventSource) configuration;
evs.removeEventListener( ConfigurationEvent.ANY, listener );
evs.addEventListener( ConfigurationEvent.ANY, listener );
evs.addEventListener( ConfigurationEvent.SUBNODE_CHANGED, listener );
}
}
@Override
public String dump( )
{
StringBuilder buffer = new StringBuilder( "Configuration Dump:\n");
Iterable<String> it = () -> configuration.getKeys();
return buffer.append(StreamSupport.stream( it.spliterator(), false ).map( k ->
"\""+k+"\" = \""+configuration.getProperty( k ).toString() + "\"").collect(Collectors.joining( "\n" ) )).toString();
}
@Override
public boolean isEmpty( )
{ {
return configuration.isEmpty( ); return configuration.isEmpty( );
} }
public ConfigRegistry getSubset(String key) @Override
public ConfigRegistry getSubset( String key ) throws RegistryException
{ {
if (configuration instanceof BaseHierarchicalConfiguration) {
BaseHierarchicalConfiguration cfg = (BaseHierarchicalConfiguration) configuration;
if (cfg.containsKey( key ))
{
try
{
return new CommonsConfigurationRegistry( cfg.configurationAt( key, true ), null );
} catch ( ConfigurationRuntimeException ex ) {
logger.error("There are multiple entries for the given key");
throw new RegistryException( "Subset for multiple key entries is not possible.");
}
} else {
return new CommonsConfigurationRegistry( cfg.subset( key ), null );
}
}
return new CommonsConfigurationRegistry( configuration.subset( key ), configurationBuilder ); return new CommonsConfigurationRegistry( configuration.subset( key ), configurationBuilder );
} }
public List<String> getList(String key) @Override
public List<String> getList( String key )
{ {
List<String> result = configuration.getList( String.class, key ); List<String> result = configuration.getList( String.class, key );
return result == null ? new ArrayList<>( ) : result; return result == null ? new ArrayList<>( ) : result;
} }
public List<ConfigRegistry> getSubsetList(String key) @Override
public List<ConfigRegistry> getSubsetList( String key ) throws RegistryException
{ {
List<ConfigRegistry> subsets = new ArrayList<>( );
boolean done = false; if (configuration instanceof BaseHierarchicalConfiguration) {
do BaseHierarchicalConfiguration cfg = (BaseHierarchicalConfiguration)configuration;
return cfg.configurationsAt( key, true ).stream().map(c -> new CommonsConfigurationRegistry( c, null )).collect( Collectors.toList() );
} else
{ {
ConfigRegistry registry = getSubset( key + "(" + subsets.size( ) + ")" ); List<ConfigRegistry> subsets = new ArrayList<>( );
if ( !registry.isEmpty( ) ) boolean done = false;
do
{ {
subsets.add( registry ); ConfigRegistry registry = null;
} else try
{ {
done = true; registry = getSubset( key + "(" + subsets.size( ) + ")" );
}
catch ( RegistryException e )
{
throw new RegistryException( "Could not retrieve subset from key "+key+": "+e.getMessage() );
}
if ( !registry.isEmpty( ) )
{
subsets.add( registry );
}
else
{
done = true;
}
} }
while ( !done );
return subsets;
} }
while ( !done );
return subsets;
} }
@Override @Override
public ConfigRegistry getPartOfCombined(String name) public ConfigRegistry getPartOfCombined( String name )
{ {
if ( combined ) if ( combined )
{ {
CombinedConfiguration config = ( CombinedConfiguration ) configuration; CombinedConfiguration config = (CombinedConfiguration) configuration;
Configuration newCfg = config.getConfiguration( name ); Configuration newCfg = config.getConfiguration( name );
ConfigurationBuilder<? extends Configuration> cfgBuilder = null; ConfigurationBuilder<? extends Configuration> cfgBuilder = null;
try try
@ -189,10 +240,11 @@ public class CommonsConfigurationRegistry
if ( builderMap.containsKey( name ) ) if ( builderMap.containsKey( name ) )
{ {
cfgBuilder = builderMap.get( name ); cfgBuilder = builderMap.get( name );
} else }
else
{ {
cfgBuilder = configurationBuilder == null ? null : cfgBuilder = configurationBuilder == null ? null :
(( CombinedConfigurationBuilder ) configurationBuilder).getNamedBuilder( name ); ( (CombinedConfigurationBuilder) configurationBuilder ).getNamedBuilder( name );
builderMap.put( name, cfgBuilder ); builderMap.put( name, cfgBuilder );
} }
} }
@ -205,7 +257,8 @@ public class CommonsConfigurationRegistry
return null; return null;
} }
public Map<String, String> getProperties(String key) @Override
public Map<String, String> getProperties( String key )
{ {
Configuration configuration = this.configuration.subset( key ); Configuration configuration = this.configuration.subset( key );
@ -222,18 +275,20 @@ public class CommonsConfigurationRegistry
return properties; return properties;
} }
public void save() @Override
throws RegistryException public void save( )
throws RegistryException
{ {
if ( configuration instanceof FileBasedConfiguration ) if ( configuration instanceof FileBasedConfiguration )
{ {
FileBasedConfiguration fileConfiguration = ( FileBasedConfiguration ) configuration; FileBasedConfiguration fileConfiguration = (FileBasedConfiguration) configuration;
FileHandler fileHandler; FileHandler fileHandler;
if ( configurationBuilder != null && configurationBuilder instanceof FileBasedConfigurationBuilder ) if ( configurationBuilder != null && configurationBuilder instanceof FileBasedConfigurationBuilder )
{ {
FileBasedConfigurationBuilder cfgBuilder = ( FileBasedConfigurationBuilder ) configurationBuilder; FileBasedConfigurationBuilder cfgBuilder = (FileBasedConfigurationBuilder) configurationBuilder;
fileHandler = cfgBuilder.getFileHandler( ); fileHandler = cfgBuilder.getFileHandler( );
} else }
else
{ {
fileHandler = new FileHandler( fileConfiguration ); fileHandler = new FileHandler( fileConfiguration );
} }
@ -245,177 +300,198 @@ public class CommonsConfigurationRegistry
{ {
throw new RegistryException( e.getMessage( ), e ); throw new RegistryException( e.getMessage( ), e );
} }
} else }
else
{ {
throw new RegistryException( "Can only save file-based configurations" ); throw new RegistryException( "Can only save file-based configurations" );
} }
} }
@Override @Override
public void registerChangeListener(RegistryListener listener, Pattern... filter) public void registerChangeListener( RegistryListener listener, String prefix)
{ {
this.listener.registerChangeListener(listener, prefix);
}
@Override
public boolean unregisterChangeListener( RegistryListener listener )
{
return this.listener.unregisterChangeListener(listener);
}
@Override
public Collection<String> getBaseKeys( )
{
Iterable<String> iterable = ( ) -> configuration.getKeys( );
return StreamSupport.stream( iterable.spliterator( ), true )
.map( DOT_NAME_PATTERN::matcher )
.filter( Matcher::matches )
.map( k -> k.group( 1 ) ).collect( Collectors.toSet( ) );
} }
@Override @Override
public boolean unregisterChangeListener(RegistryListener listener) public Collection<String> getKeys( )
{ {
return false; Iterable<String> iterable = ( ) -> configuration.getKeys( );
return StreamSupport.stream( iterable.spliterator( ), true ).collect( Collectors.toSet( ) );
} }
@Override
public Collection<String> getKeys() public Collection<String> getKeys( String prefix )
{ {
Iterable<String> iterable = () -> configuration.getKeys( ); Iterable<String> iterable = ( ) -> configuration.getKeys( prefix );
return StreamSupport.stream( iterable.spliterator( ), false ) return StreamSupport.stream( iterable.spliterator( ), true ).collect( Collectors.toSet( ) );
.map( k -> DOT_NAME_PATTERN.matcher( k ) )
.filter( k -> k.matches( ) )
.map( k -> k.group( 1 ) ).collect( Collectors.toSet( ) );
} }
public Collection getFullKeys() @Override
{ public void remove( String key )
Iterable<String> iterable = () -> configuration.getKeys( );
return StreamSupport.stream( iterable.spliterator( ), false ).collect( Collectors.toSet( ) );
}
public void remove(String key)
{ {
configuration.clearProperty( key ); configuration.clearProperty( key );
} }
public void removeSubset(String key) @Override
public void removeSubset( String key )
{ {
// create temporary list since removing a key will modify the iterator from configuration getKeys( key ).forEach( k -> configuration.clearProperty( k ) );
List keys = new ArrayList( );
for ( Iterator i = configuration.getKeys( key ); i.hasNext( ); )
{
keys.add( i.next( ) );
}
for ( Iterator i = keys.iterator( ); i.hasNext( ); )
{
configuration.clearProperty( ( String ) i.next( ) );
}
} }
public String getString(String key) @Override
public Object getValue( String key ) {
return configuration.getProperty( key );
}
@Override
public String getString( String key )
{ {
return configuration.getString( key ); return configuration.getString( key );
} }
public String getString(String key, String defaultValue) @Override
public String getString( String key, String defaultValue )
{ {
return configuration.getString( key, defaultValue ); return configuration.getString( key, defaultValue );
} }
public void setString(String key, String value) @Override
public void setString( String key, String value )
{ {
configuration.setProperty( key, value ); configuration.setProperty( key, value );
} }
public int getInt(String key) @Override
public int getInt( String key )
{ {
return configuration.getInt( key ); return configuration.getInt( key );
} }
public int getInt(String key, int defaultValue) @Override
public int getInt( String key, int defaultValue )
{ {
return configuration.getInt( key, defaultValue ); return configuration.getInt( key, defaultValue );
} }
public void setInt(String key, int value) @Override
public void setInt( String key, int value )
{ {
configuration.setProperty( key, Integer.valueOf( value ) ); configuration.setProperty( key, value );
} }
public boolean getBoolean(String key) @Override
public boolean getBoolean( String key )
{ {
return configuration.getBoolean( key ); return configuration.getBoolean( key );
} }
public boolean getBoolean(String key, boolean defaultValue) @Override
public boolean getBoolean( String key, boolean defaultValue )
{ {
return configuration.getBoolean( key, defaultValue ); return configuration.getBoolean( key, defaultValue );
} }
public void setBoolean(String key, boolean value) @Override
public void setBoolean( String key, boolean value )
{ {
configuration.setProperty( key, Boolean.valueOf( value ) ); configuration.setProperty( key, value );
} }
public void addConfigurationFromResource(String name, String resource) @Override
throws RegistryException public void addConfigurationFromResource( String name, String resource )
throws RegistryException
{ {
addConfigurationFromResource( name, resource, null ); addConfigurationFromResource( name, resource, null );
} }
public void addConfigurationFromResource(String name, String resource, String prefix) @Override
throws RegistryException public void addConfigurationFromResource( String name, String resource, String prefix )
throws RegistryException
{ {
if ( configuration instanceof CombinedConfiguration ) if ( configuration instanceof CombinedConfiguration )
{ {
String atPrefix = StringUtils.isEmpty( prefix ) ? null : prefix; String atPrefix = StringUtils.isEmpty( prefix ) ? null : prefix;
CombinedConfiguration configuration = ( CombinedConfiguration ) this.configuration; CombinedConfiguration configuration = (CombinedConfiguration) this.configuration;
if ( resource.endsWith( ".properties" ) ) if ( resource.endsWith( ".properties" ) )
{ {
try try
{ {
logger.debug( "Loading properties configuration from classloader resource: {}", resource ); logger.debug( "Loading properties configuration from classloader resource: {}", resource );
FileBasedConfigurationBuilder<PropertiesConfiguration> builder = new FileBasedConfigurationBuilder<>( PropertiesConfiguration.class ) FileBasedConfigurationBuilder<PropertiesConfiguration> builder = new FileBasedConfigurationBuilder<>( PropertiesConfiguration.class )
.configure( new Parameters( ).properties( ) .configure( new Parameters( ).properties( )
.setLocationStrategy( new ClasspathLocationStrategy( ) ) .setLocationStrategy( new ClasspathLocationStrategy( ) )
.setFileName( resource ) ); .setFileName( resource ) );
builderMap.put( name, builder ); builderMap.put( name, builder );
configuration.addConfiguration( builder.getConfiguration( ), name, atPrefix ); configuration.addConfiguration( builder.getConfiguration( ), name, atPrefix );
} }
catch ( ConfigurationException e ) catch ( ConfigurationException e )
{ {
throw new RegistryException( throw new RegistryException(
"Unable to add configuration from resource '" + resource + "': " + e.getMessage( ), e ); "Unable to add configuration from resource '" + resource + "': " + e.getMessage( ), e );
} }
} else if ( resource.endsWith( ".xml" ) ) }
else if ( resource.endsWith( ".xml" ) )
{ {
try try
{ {
logger.debug( "Loading XML configuration from classloader resource: {}", resource ); logger.debug( "Loading XML configuration from classloader resource: {}", resource );
FileBasedConfigurationBuilder<XMLConfiguration> builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class ) FileBasedConfigurationBuilder<XMLConfiguration> builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class )
.configure( new Parameters( ).xml( ) .configure( new Parameters( ).xml( )
.setLocationStrategy( new ClasspathLocationStrategy( ) ) .setLocationStrategy( new ClasspathLocationStrategy( ) )
.setFileName( resource ) ); .setFileName( resource ) );
builderMap.put( name, builder ); builderMap.put( name, builder );
configuration.addConfiguration( builder.getConfiguration( ), name, atPrefix ); configuration.addConfiguration( builder.getConfiguration( ), name, atPrefix );
} }
catch ( ConfigurationException e ) catch ( ConfigurationException e )
{ {
throw new RegistryException( throw new RegistryException(
"Unable to add configuration from resource '" + resource + "': " + e.getMessage( ), e ); "Unable to add configuration from resource '" + resource + "': " + e.getMessage( ), e );
} }
} else }
else
{ {
throw new RegistryException( throw new RegistryException(
"Unable to add configuration from resource '" + resource + "': unrecognised type" ); "Unable to add configuration from resource '" + resource + "': unrecognised type" );
} }
} else }
else
{ {
throw new RegistryException( "The underlying configuration object is not a combined configuration " ); throw new RegistryException( "The underlying configuration object is not a combined configuration " );
} }
} }
@Override @Override
public void addConfigurationFromFile(String name, Path file) throws RegistryException public void addConfigurationFromFile( String name, Path file ) throws RegistryException
{ {
addConfigurationFromFile( name, file, "" ); addConfigurationFromFile( name, file, "" );
} }
public void addConfigurationFromFile(String name, Path file, String prefix) @Override
throws RegistryException public void addConfigurationFromFile( String name, Path file, String prefix )
throws RegistryException
{ {
if ( this.configuration instanceof CombinedConfiguration ) if ( this.configuration instanceof CombinedConfiguration )
{ {
String atPrefix = StringUtils.isEmpty( prefix ) ? null : prefix; String atPrefix = StringUtils.isEmpty( prefix ) ? null : prefix;
CombinedConfiguration configuration = ( CombinedConfiguration ) this.configuration; CombinedConfiguration configuration = (CombinedConfiguration) this.configuration;
String fileName = file.getFileName( ).toString( ); String fileName = file.getFileName( ).toString( );
if ( fileName.endsWith( ".properties" ) ) if ( fileName.endsWith( ".properties" ) )
{ {
@ -423,10 +499,10 @@ public class CommonsConfigurationRegistry
{ {
logger.debug( "Loading properties configuration from file: {}", file ); logger.debug( "Loading properties configuration from file: {}", file );
FileBasedConfigurationBuilder<PropertiesConfiguration> builder = new FileBasedConfigurationBuilder<>( PropertiesConfiguration.class ) FileBasedConfigurationBuilder<PropertiesConfiguration> builder = new FileBasedConfigurationBuilder<>( PropertiesConfiguration.class )
.configure( new Parameters( ).properties( ) .configure( new Parameters( ).properties( )
.setFileSystem( FileLocatorUtils.DEFAULT_FILE_SYSTEM ) .setFileSystem( FileLocatorUtils.DEFAULT_FILE_SYSTEM )
.setLocationStrategy( FileLocatorUtils.DEFAULT_LOCATION_STRATEGY ) .setLocationStrategy( FileLocatorUtils.DEFAULT_LOCATION_STRATEGY )
.setFile( file.toFile( ) ) ); .setFile( file.toFile( ) ) );
// builder is needed for save // builder is needed for save
builderMap.put( name, builder ); builderMap.put( name, builder );
configuration.addConfiguration( builder.getConfiguration( ), name, atPrefix ); configuration.addConfiguration( builder.getConfiguration( ), name, atPrefix );
@ -434,32 +510,35 @@ public class CommonsConfigurationRegistry
catch ( ConfigurationException e ) catch ( ConfigurationException e )
{ {
throw new RegistryException( throw new RegistryException(
"Unable to add configuration from file '" + file.getFileName( ) + "': " + e.getMessage( ), e ); "Unable to add configuration from file '" + file.getFileName( ) + "': " + e.getMessage( ), e );
} }
} else if ( fileName.endsWith( ".xml" ) ) }
else if ( fileName.endsWith( ".xml" ) )
{ {
try try
{ {
logger.debug( "Loading XML configuration from file: {}", file ); logger.debug( "Loading XML configuration from file: {}", file );
FileBasedConfigurationBuilder<XMLConfiguration> builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class ) FileBasedConfigurationBuilder<XMLConfiguration> builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class )
.configure( new Parameters( ).xml( ) .configure( new Parameters( ).xml( )
.setFileSystem( FileLocatorUtils.DEFAULT_FILE_SYSTEM ) .setFileSystem( FileLocatorUtils.DEFAULT_FILE_SYSTEM )
.setLocationStrategy( FileLocatorUtils.DEFAULT_LOCATION_STRATEGY ) .setLocationStrategy( FileLocatorUtils.DEFAULT_LOCATION_STRATEGY )
.setFile( file.toFile( ) ) ); .setFile( file.toFile( ) ) );
builderMap.put( name, builder ); builderMap.put( name, builder );
configuration.addConfiguration( builder.getConfiguration( ), name, atPrefix ); configuration.addConfiguration( builder.getConfiguration( ), name, atPrefix );
} }
catch ( ConfigurationException e ) catch ( ConfigurationException e )
{ {
throw new RegistryException( throw new RegistryException(
"Unable to add configuration from file '" + file.getFileName( ) + "': " + e.getMessage( ), e ); "Unable to add configuration from file '" + file.getFileName( ) + "': " + e.getMessage( ), e );
} }
} else }
else
{ {
throw new RegistryException( throw new RegistryException(
"Unable to add configuration from file '" + file.getFileName( ) + "': unrecognised type" ); "Unable to add configuration from file '" + file.getFileName( ) + "': unrecognised type" );
} }
} else }
else
{ {
throw new RegistryException( "The underlying configuration is not a combined configuration object." ); throw new RegistryException( "The underlying configuration is not a combined configuration object." );
} }
@ -471,22 +550,24 @@ public class CommonsConfigurationRegistry
class StringFileSystem extends FileSystem class StringFileSystem extends FileSystem
{ {
String content; final String content;
String encoding = "UTF-8"; String encoding = "UTF-8";
StringFileSystem(String content) StringFileSystem( String content )
{ {
this.content = content; this.content = content;
} }
StringFileSystem(String encoding, String content)
@SuppressWarnings( "unused" )
StringFileSystem( String encoding, String content )
{ {
this.encoding = encoding; this.encoding = encoding;
this.content = content; this.content = content;
} }
@Override @Override
public InputStream getInputStream(URL url) throws ConfigurationException public InputStream getInputStream( URL url ) throws ConfigurationException
{ {
try try
{ {
@ -500,37 +581,37 @@ public class CommonsConfigurationRegistry
} }
@Override @Override
public OutputStream getOutputStream(URL url) throws ConfigurationException public OutputStream getOutputStream( URL url )
{ {
return new ByteArrayOutputStream( 0 ); return new ByteArrayOutputStream( 0 );
} }
@Override @Override
public OutputStream getOutputStream(File file) throws ConfigurationException public OutputStream getOutputStream( File file )
{ {
return new ByteArrayOutputStream( 0 ); return new ByteArrayOutputStream( 0 );
} }
@Override @Override
public String getPath(File file, URL url, String basePath, String fileName) public String getPath( File file, URL url, String basePath, String fileName )
{ {
return basePath + "/" + fileName; return basePath + "/" + fileName;
} }
@Override @Override
public String getBasePath(String path) public String getBasePath( String path )
{ {
return path; return path;
} }
@Override @Override
public String getFileName(String path) public String getFileName( String path )
{ {
return path; return path;
} }
@Override @Override
public URL locateFromURL(String basePath, String fileName) public URL locateFromURL( String basePath, String fileName )
{ {
try try
{ {
@ -544,24 +625,17 @@ public class CommonsConfigurationRegistry
} }
@Override @Override
public URL getURL(String basePath, String fileName) throws MalformedURLException public URL getURL( String basePath, String fileName ) throws MalformedURLException
{ {
try return new URL( "file://" + getPath( null, null, basePath, fileName ) );
{
return new URL( "file://" + getPath( null, null, basePath, fileName ) );
}
catch ( MalformedURLException e )
{
// ignore
return null;
}
} }
} }
@Override
@PostConstruct @PostConstruct
public void initialize() public void initialize( )
throws RegistryException throws RegistryException
{ {
try try
{ {
@ -571,11 +645,11 @@ public class CommonsConfigurationRegistry
String interpolatedProps; String interpolatedProps;
Parameters params = new Parameters( ); Parameters params = new Parameters( );
DefaultExpressionEngineSymbols symbols = new DefaultExpressionEngineSymbols.Builder( DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS ) DefaultExpressionEngineSymbols symbols = new DefaultExpressionEngineSymbols.Builder( DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS )
.setPropertyDelimiter( propertyDelimiter ) .setPropertyDelimiter( propertyDelimiter )
.setIndexStart( "(" ) .setIndexStart( "(" )
.setIndexEnd( ")" ) .setIndexEnd( ")" )
.setEscapedDelimiter( "\\" + propertyDelimiter ) .setEscapedDelimiter( "\\" + propertyDelimiter )
.create( ); .create( );
DefaultExpressionEngine expressionEngine = new DefaultExpressionEngine( symbols ); DefaultExpressionEngine expressionEngine = new DefaultExpressionEngine( symbols );
// It allows to use system properties in the XML declaration. // It allows to use system properties in the XML declaration.
@ -587,24 +661,25 @@ public class CommonsConfigurationRegistry
// for the sources that are used for the CombinedConfiguration. // for the sources that are used for the CombinedConfiguration.
FileSystem fs = new StringFileSystem( interpolatedProps ); FileSystem fs = new StringFileSystem( interpolatedProps );
FileBasedConfigurationBuilder<XMLConfiguration> cfgBuilder = FileBasedConfigurationBuilder<XMLConfiguration> cfgBuilder =
new FileBasedConfigurationBuilder<>( new FileBasedConfigurationBuilder<>(
XMLConfiguration.class ) XMLConfiguration.class )
.configure( params.xml( ) .configure( params.xml( )
.setFileSystem( fs ) .setFileSystem( fs )
.setFileName( "config.xml" ) .setFileName( "config.xml" )
.setListDelimiterHandler( .setListDelimiterHandler(
new DefaultListDelimiterHandler( ',' ) ) new DefaultListDelimiterHandler( ',' ) )
.setExpressionEngine( expressionEngine ) .setExpressionEngine( expressionEngine )
.setThrowExceptionOnMissing( false ) ); .setThrowExceptionOnMissing( false ) );
CombinedConfigurationBuilder builder = new CombinedConfigurationBuilder( ). CombinedConfigurationBuilder builder = new CombinedConfigurationBuilder( ).
configure( params.combined( ).setDefinitionBuilder( cfgBuilder ) ); configure( params.combined( ).setDefinitionBuilder( cfgBuilder ) );
// The builder is needed later for saving of the file parts in the combined configuration. // The builder is needed later for saving of the file parts in the combined configuration.
this.configurationBuilder = builder; this.configurationBuilder = builder;
configuration = builder.getConfiguration( ); configuration = builder.getConfiguration( );
} else }
else
{ {
logger.debug( "Creating a default configuration - no configuration was provided" ); logger.debug( "Creating a default configuration - no configuration was provided" );
NodeCombiner combiner = new UnionCombiner( ); NodeCombiner combiner = new UnionCombiner( );
@ -625,43 +700,38 @@ public class CommonsConfigurationRegistry
logger.error( "Fatal error, while reading the configuration definition: " + e.getMessage( ) ); logger.error( "Fatal error, while reading the configuration definition: " + e.getMessage( ) );
logger.error( "The definition was:" ); logger.error( "The definition was:" );
logger.error( combinedConfigurationDefinition ); logger.error( combinedConfigurationDefinition );
throw new RuntimeException( e.getMessage( ), e ); throw new RegistryException( e.getMessage( ), e );
} }
} }
public void setCombinedConfigurationDefinition(String combinedConfigurationDefinition) public void setCombinedConfigurationDefinition( String combinedConfigurationDefinition )
{ {
this.combinedConfigurationDefinition = combinedConfigurationDefinition; this.combinedConfigurationDefinition = combinedConfigurationDefinition;
} }
public String getPropertyDelimiter() public String getPropertyDelimiter( )
{ {
return propertyDelimiter; return propertyDelimiter;
} }
public void setPropertyDelimiter(String propertyDelimiter) public void setPropertyDelimiter( String propertyDelimiter )
{ {
this.propertyDelimiter = propertyDelimiter; this.propertyDelimiter = propertyDelimiter;
} }
public ConfigurationBuilder<? extends Configuration> getConfigurationBuilder() public ConfigurationBuilder<? extends Configuration> getConfigurationBuilder( )
{ {
return configurationBuilder; return configurationBuilder;
} }
public void setConfigurationBuilder(ConfigurationBuilder<? extends Configuration> configurationBuilder)
{
this.configurationBuilder = configurationBuilder;
}
/** /**
* Returns true, if the system properties are added to the base configuration. Otherwise system properties * Returns true, if the system properties are added to the base configuration. Otherwise system properties
* can be interpolated by ${sys:var} syntax. * can still be interpolated by ${sys:var} syntax.
* *
* @return * @return True, if system properties are added to the configuration root
*/ */
public boolean isAddSystemProperties() public boolean isAddSystemProperties( )
{ {
return addSystemProperties; return addSystemProperties;
} }
@ -670,9 +740,9 @@ public class CommonsConfigurationRegistry
* Set to true, if the system properties should be added to the base configuration. * 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. * If set to false, system properties are no direct part of the configuration.
* *
* @param addSystemProperties * @param addSystemProperties True, or false.
*/ */
public void setAddSystemProperties(boolean addSystemProperties) public void setAddSystemProperties( boolean addSystemProperties )
{ {
this.addSystemProperties = addSystemProperties; this.addSystemProperties = addSystemProperties;
} }

View File

@ -82,7 +82,7 @@ public abstract class AbstractRegistryTest
try try
{ {
registry.getInt( "unknown" ); registry.getInt( "unknown" );
assertTrue( "no NoSuchElementException", false ); fail( "no NoSuchElementException" );
} }
catch ( NoSuchElementException e ) catch ( NoSuchElementException e )
{ {
@ -113,7 +113,7 @@ public abstract class AbstractRegistryTest
throws Exception throws Exception
{ {
ConfigRegistry registry = getRegistry(); ConfigRegistry registry = getRegistry();
assertEquals( "not true ", true, registry.getBoolean( "boolean" ) ); assertTrue( "not true ", registry.getBoolean( "boolean" ) );
} }
@Test @Test
@ -124,7 +124,7 @@ public abstract class AbstractRegistryTest
try try
{ {
registry.getBoolean( "unknown" ); registry.getBoolean( "unknown" );
assertTrue( "no NoSuchElementException", false ); fail( "no NoSuchElementException" );
} }
catch ( NoSuchElementException e ) catch ( NoSuchElementException e )
{ {

View File

@ -32,7 +32,6 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.rmi.registry.Registry;
import java.util.*; import java.util.*;
/** /**
@ -48,84 +47,108 @@ public class CommonsConfigurationRegistryTest
private static final int INT_TEST_VALUE = 8080; private static final int INT_TEST_VALUE = 8080;
public String getRoleHint() public String getRoleHint( )
{ {
return "builder"; return "builder";
} }
@Test @Test
public void requirementTest() { public void requirementTest( )
assertNotNull(System.getProperty("basedir")); {
assertTrue( System.getProperty( "basedir" ).length()>0 ); assertNotNull( System.getProperty( "basedir" ) );
assertNotNull(System.getProperty("user.dir")); assertTrue( System.getProperty( "basedir" ).length( ) > 0 );
assertTrue( System.getProperty( "user.dir" ).length()>0 ); assertNotNull( System.getProperty( "user.dir" ) );
assertTrue( System.getProperty( "user.dir" ).length( ) > 0 );
} }
@Test @Test
public void testDefaultConfiguration() public void testDefaultConfiguration( )
throws Exception throws Exception
{ {
registry = getRegistry( "default" , true); registry = getRegistry( "default", true );
assertEquals( "Check system property override", System.getProperty( "user.dir" ), assertEquals( "Check system property override", System.getProperty( "user.dir" ),
registry.getString( "user.dir" ) ); registry.getString( "user.dir" ) );
assertEquals( "Check system property", System.getProperty( "user.home" ), registry.getString( "user.home" ) ); assertEquals( "Check system property", System.getProperty( "user.home" ), registry.getString( "user.home" ) );
assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) ); assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) );
} }
@Test @Test
public void testGetKeys() throws Exception public void testGetKeys( ) throws Exception
{
registry = getRegistry( "builder" );
Collection<String> keys = registry.getBaseKeys( );
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 );
}
@Test
public void testGetFullKeys( ) throws Exception
{ {
registry = getRegistry( "builder" ); registry = getRegistry( "builder" );
Collection<String> keys = registry.getKeys( ); Collection<String> keys = registry.getKeys( );
HashSet<Object> expectedKeySet = new HashSet<>( ); HashSet<Object> expectedKeySet = new HashSet<>( );
expectedKeySet.add("test"); String[] expStrings = new String[]{
expectedKeySet.add("repository"); "test.value",
expectedKeySet.add("objects"); "test.number",
expectedKeySet.add("properties"); "test.boolean",
expectedKeySet.add("strings"); "test.interpolation",
expectedKeySet.add("user"); "repository",
expectedKeySet.add("foo"); "objects.object.foo",
expectedKeySet.add("string"); "properties.foo",
expectedKeySet.add("boolean"); "properties.bar",
expectedKeySet.add("subOne"); "strings.string",
expectedKeySet.add( "two" ); "user.dir",
"foo.bar",
"subOne.firstEntry",
"subOne.secondEntry",
"two",
"string",
"boolean"
};
Collections.addAll( expectedKeySet, expStrings );
assertEquals( expectedKeySet, keys ); assertEquals( expectedKeySet, keys );
expectedKeySet.clear();
} }
@Test @Test
public void testBuilderConfiguration() public void testBuilderConfiguration( )
throws Exception throws Exception
{ {
registry = getRegistry( "builder", true ); registry = getRegistry( "builder", true );
assertEquals( "Check system property override", "new user dir", registry.getString( "user.dir" ) ); assertEquals( "Check system property override", "new user dir", registry.getString( "user.dir" ) );
assertEquals( "Check system property default", System.getProperty( "user.home" ), assertEquals( "Check system property default", System.getProperty( "user.home" ),
registry.getString( "user.home" ) ); registry.getString( "user.home" ) );
assertEquals( "Check other properties are loaded", "foo", registry.getString( "test.value" ) ); assertEquals( "Check other properties are loaded", "foo", registry.getString( "test.value" ) );
assertEquals( "Check other properties are loaded", 1, registry.getInt( "test.number" ) ); assertEquals( "Check other properties are loaded", 1, registry.getInt( "test.number" ) );
assertTrue( "Check other properties are loaded", registry.getBoolean( "test.boolean" ) ); assertTrue( "Check other properties are loaded", registry.getBoolean( "test.boolean" ) );
} }
@Test @Test
public void testDump() public void testDump( )
throws Exception throws Exception
{ {
registry = getRegistry( "default" ); registry = getRegistry( "builder" );
String dump = registry.dump( );
String dump = registry.dump(); System.out.println(dump);
System.out.println( dump ); assertTrue( dump.startsWith( "Configuration Dump:" ) );
assertTrue( dump.startsWith( "Configuration Dump." ) ); assertTrue( dump.contains( "\"properties.foo\" = \"bar\"" ));
} }
@Test @Test
public void testDefaults() public void testDefaults( )
throws Exception throws Exception
{ {
registry = getRegistry( "builder" ); registry = getRegistry( "builder" );
@ -136,7 +159,7 @@ public class CommonsConfigurationRegistryTest
try try
{ {
registry.getInt( "foo" ); registry.getInt( "foo" );
fail(); fail( );
} }
catch ( NoSuchElementException e ) catch ( NoSuchElementException e )
{ {
@ -148,7 +171,7 @@ public class CommonsConfigurationRegistryTest
try try
{ {
registry.getBoolean( "foo" ); registry.getBoolean( "foo" );
fail(); fail( );
} }
catch ( NoSuchElementException e ) catch ( NoSuchElementException e )
{ {
@ -159,60 +182,60 @@ public class CommonsConfigurationRegistryTest
} }
@Test @Test
public void testInterpolation() public void testInterpolation( )
throws Exception throws Exception
{ {
registry = getRegistry( "builder" , true ); registry = getRegistry( "builder", true );
assertEquals( "Check system property interpolation", System.getProperty( "user.home" ) + "/.m2/repository", assertEquals( "Check system property interpolation", System.getProperty( "user.home" ) + "/.m2/repository",
registry.getString( "repository" ) ); registry.getString( "repository" ) );
assertEquals( "Check configuration value interpolation", "foo/bar", assertEquals( "Check configuration value interpolation", "foo/bar",
registry.getString( "test.interpolation" ) ); registry.getString( "test.interpolation" ) );
} }
@Test @Test
public void testAddConfigurationXmlFile() public void testAddConfigurationXmlFile( )
throws Exception throws Exception
{ {
registry = getRegistry( "default" , true); registry = getRegistry( "default", true );
registry.addConfigurationFromFile( "test.xml", Paths.get( "src/test/resources/test.xml" ) ); registry.addConfigurationFromFile( "test.xml", Paths.get( "src/test/resources/test.xml" ) );
assertEquals( "Check system property default", System.getProperty( "user.dir" ), assertEquals( "Check system property default", System.getProperty( "user.dir" ),
registry.getString( "user.dir" ) ); registry.getString( "user.dir" ) );
assertEquals( "Check other properties are loaded", "foo", registry.getString( "test.value" ) ); assertEquals( "Check other properties are loaded", "foo", registry.getString( "test.value" ) );
} }
@Test @Test
public void testAddConfigurationPropertiesFile() public void testAddConfigurationPropertiesFile( )
throws Exception throws Exception
{ {
registry = getRegistry( "default", true ); registry = getRegistry( "default", true );
registry.addConfigurationFromFile( registry.addConfigurationFromFile(
"test.properties", Paths.get("src/test/resources/test.properties" ) ); "test.properties", Paths.get( "src/test/resources/test.properties" ) );
assertEquals( "Check system property default", System.getProperty( "user.dir" ), assertEquals( "Check system property default", System.getProperty( "user.dir" ),
registry.getString( "user.dir" ) ); registry.getString( "user.dir" ) );
assertEquals( "Check other properties are loaded", "baz", registry.getString( "foo.bar" ) ); assertEquals( "Check other properties are loaded", "baz", registry.getString( "foo.bar" ) );
assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) ); assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) );
} }
@Test @Test
public void testAddConfigurationXmlResource() public void testAddConfigurationXmlResource( )
throws Exception throws Exception
{ {
registry = getRegistry( "default" , true); registry = getRegistry( "default", true );
registry.addConfigurationFromResource( "test.xml-r", "test.xml" ); registry.addConfigurationFromResource( "test.xml-r", "test.xml" );
assertEquals( "Check system property default", System.getProperty( "user.dir" ), assertEquals( "Check system property default", System.getProperty( "user.dir" ),
registry.getString( "user.dir" ) ); registry.getString( "user.dir" ) );
assertEquals( "Check other properties are loaded", "foo", registry.getString( "test.value" ) ); assertEquals( "Check other properties are loaded", "foo", registry.getString( "test.value" ) );
} }
@Test @Test
public void testAddConfigurationPropertiesResource() public void testAddConfigurationPropertiesResource( )
throws Exception throws Exception
{ {
registry = getRegistry( "default", true ); registry = getRegistry( "default", true );
@ -220,13 +243,13 @@ public class CommonsConfigurationRegistryTest
registry.addConfigurationFromResource( "test.properties-r", "test.properties" ); registry.addConfigurationFromResource( "test.properties-r", "test.properties" );
assertEquals( "Check system property default", System.getProperty( "user.dir" ), assertEquals( "Check system property default", System.getProperty( "user.dir" ),
registry.getString( "user.dir" ) ); registry.getString( "user.dir" ) );
assertEquals( "Check other properties are loaded", "baz", registry.getString( "foo.bar" ) ); assertEquals( "Check other properties are loaded", "baz", registry.getString( "foo.bar" ) );
assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) ); assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) );
} }
@Test @Test
public void testAddConfigurationUnrecognisedType() public void testAddConfigurationUnrecognisedType( )
throws Exception throws Exception
{ {
registry = getRegistry( "default" ); registry = getRegistry( "default" );
@ -234,7 +257,7 @@ public class CommonsConfigurationRegistryTest
try try
{ {
registry.addConfigurationFromResource( "test.foo", "test.foo" ); registry.addConfigurationFromResource( "test.foo", "test.foo" );
fail(); fail( );
} }
catch ( RegistryException e ) catch ( RegistryException e )
{ {
@ -245,7 +268,7 @@ public class CommonsConfigurationRegistryTest
{ {
registry.addConfigurationFromFile( "test.foo-file", registry.addConfigurationFromFile( "test.foo-file",
Paths.get( "src/test/resources/test.foo" ) ); Paths.get( "src/test/resources/test.foo" ) );
fail(); fail( );
} }
catch ( RegistryException e ) catch ( RegistryException e )
{ {
@ -254,26 +277,25 @@ public class CommonsConfigurationRegistryTest
} }
@Test @Test
public void testIsEmpty() public void testIsEmpty( )
throws Exception throws Exception
{ {
registry = getRegistry( "default", true ); registry = getRegistry( "default", true );
assertFalse( registry.isEmpty( ) );
assertFalse( registry.isEmpty() ); assertTrue( registry.getSubset( "foo" ).isEmpty( ) );
assertTrue( registry.getSubset( "foo" ).isEmpty() );
} }
@Test @Test
public void testIsEmptyWithoutSysProps() public void testIsEmptyWithoutSysProps( )
throws Exception throws Exception
{ {
registry = getRegistry( "default"); registry = getRegistry( "default" );
assertTrue( registry.isEmpty() ); assertTrue( registry.isEmpty( ) );
} }
@Test @Test
public void testGetSubset() public void testGetSubset( )
throws Exception throws Exception
{ {
registry = getRegistry( "builder" ); registry = getRegistry( "builder" );
@ -285,13 +307,13 @@ public class CommonsConfigurationRegistryTest
} }
@Test @Test
public void testGetSubsetList() public void testGetSubsetList( )
throws Exception throws Exception
{ {
registry = getRegistry( "builder" ); registry = getRegistry( "builder" );
List list = registry.getSubsetList( "objects.object" ); List list = registry.getSubsetList( "objects.object" );
assertEquals( 2, list.size() ); assertEquals( 2, list.size( ) );
ConfigRegistry r = (ConfigRegistry) list.get( 0 ); ConfigRegistry r = (ConfigRegistry) list.get( 0 );
assertTrue( "bar".equals( r.getString( "foo" ) ) || "baz".equals( r.getString( "foo" ) ) ); assertTrue( "bar".equals( r.getString( "foo" ) ) || "baz".equals( r.getString( "foo" ) ) );
r = (ConfigRegistry) list.get( 1 ); r = (ConfigRegistry) list.get( 1 );
@ -299,47 +321,47 @@ public class CommonsConfigurationRegistryTest
} }
@Test @Test
public void testGetProperties() public void testGetProperties( )
throws Exception throws Exception
{ {
registry = getRegistry( "builder" ); registry = getRegistry( "builder" );
Map<String,String> properties = registry.getProperties( "properties" ); Map<String, String> properties = registry.getProperties( "properties" );
assertEquals( 2, properties.size() ); assertEquals( 2, properties.size( ) );
assertEquals( "bar", properties.get( "foo" ) ); assertEquals( "bar", properties.get( "foo" ) );
assertEquals( "baz", properties.get( "bar" ) ); assertEquals( "baz", properties.get( "bar" ) );
} }
@Test @Test
public void testGetList() public void testGetList( )
throws Exception throws Exception
{ {
registry = getRegistry( "builder" ); registry = getRegistry( "builder" );
List list = registry.getList( "strings.string" ); List list = registry.getList( "strings.string" );
assertEquals( 3, list.size() ); assertEquals( 3, list.size( ) );
assertEquals( "s1", list.get( 0 ) ); assertEquals( "s1", list.get( 0 ) );
assertEquals( "s2", list.get( 1 ) ); assertEquals( "s2", list.get( 1 ) );
assertEquals( "s3", list.get( 2 ) ); assertEquals( "s3", list.get( 2 ) );
} }
@Test @Test
public void testGetSection() public void testGetSection( )
throws Exception throws Exception
{ {
this.registry = getRegistry( "builder" ); this.registry = getRegistry( "builder" );
ConfigRegistry registry = this.registry.getPartOfCombined( "properties" ); ConfigRegistry registry = this.registry.getPartOfCombined( "properties" );
assertNotNull(registry); assertNotNull( registry );
assertNull( registry.getString( "test.value" ) ); assertNull( registry.getString( "test.value" ) );
assertEquals( "baz", registry.getString( "foo.bar" ) ); assertEquals( "baz", registry.getString( "foo.bar" ) );
} }
@Test @Test
public void testRemoveKey() public void testRemoveKey( )
throws Exception throws Exception
{ {
registry = getRegistry( "builder" ); registry = getRegistry( "builder" );
assertNotNull(registry); assertNotNull( registry );
ConfigRegistry registry = this.registry.getPartOfCombined( "properties" ); ConfigRegistry registry = this.registry.getPartOfCombined( "properties" );
assertEquals( "baz", registry.getString( "foo.bar" ) ); assertEquals( "baz", registry.getString( "foo.bar" ) );
registry.remove( "foo.bar" ); registry.remove( "foo.bar" );
@ -347,11 +369,11 @@ public class CommonsConfigurationRegistryTest
} }
@Test @Test
public void testRemoveSubset() public void testRemoveSubset( )
throws Exception throws Exception
{ {
registry = getRegistry( "builder" ); registry = getRegistry( "builder" );
assertNotNull(registry); assertNotNull( registry );
registry.removeSubset( "strings" ); registry.removeSubset( "strings" );
assertEquals( Collections.EMPTY_LIST, registry.getList( "strings.string" ) ); assertEquals( Collections.EMPTY_LIST, registry.getList( "strings.string" ) );
@ -378,7 +400,7 @@ public class CommonsConfigurationRegistryTest
*/ */
@Test @Test
public void testGetDontForceCreateByName() public void testGetDontForceCreateByName( )
throws Exception throws Exception
{ {
registry = getRegistry( "noForceCreate" ); registry = getRegistry( "noForceCreate" );
@ -387,7 +409,7 @@ public class CommonsConfigurationRegistryTest
} }
@Test @Test
public void testSaveSection() public void testSaveSection( )
throws Exception throws Exception
{ {
Path src = Paths.get( "src/test/resources/test-save.xml" ); Path src = Paths.get( "src/test/resources/test-save.xml" );
@ -397,24 +419,24 @@ public class CommonsConfigurationRegistryTest
registry = getRegistry( "test-save" ); registry = getRegistry( "test-save" );
ConfigRegistry registry = this.registry.getPartOfCombined( "org.codehaus.plexus.registry" ); ConfigRegistry registry = this.registry.getPartOfCombined( "org.codehaus.plexus.registry" );
assertEquals( "check list elements", Arrays.asList( new String[]{ "1", "2", "3" } ), assertEquals( "check list elements", Arrays.asList( new String[]{"1", "2", "3"} ),
registry.getList( "listElements.listElement" ) ); registry.getList( "listElements.listElement" ) );
registry.remove( "listElements.listElement(1)" ); registry.remove( "listElements.listElement(1)" );
registry.save(); registry.save( );
FileBasedConfigurationBuilder<XMLConfiguration> builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class) FileBasedConfigurationBuilder<XMLConfiguration> builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class )
.configure( new Parameters().xml().setFile(dest.toFile()) ); .configure( new Parameters( ).xml( ).setFile( dest.toFile( ) ) );
XMLConfiguration configuration = builder.getConfiguration(); XMLConfiguration configuration = builder.getConfiguration( );
assertEquals( Arrays.asList( new String[]{ "1", "3" } ), configuration.getList( "listElements.listElement" ) ); assertEquals( Arrays.asList( new String[]{"1", "3"} ), configuration.getList( "listElements.listElement" ) );
// file in ${basedir}/target/conf/shared.xml // file in ${basedir}/target/conf/shared.xml
ConfigRegistry section = this.registry.getPartOfCombined( "org.apache.maven.shared.app.user" ); ConfigRegistry section = this.registry.getPartOfCombined( "org.apache.maven.shared.app.user" );
section.setString( "foo", "zloug" ); section.setString( "foo", "zloug" );
section.save(); section.save( );
builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class) builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class )
.configure( new Parameters().xml().setFile( Paths.get("target/conf/shared.xml").toFile() ) ); .configure( new Parameters( ).xml( ).setFile( Paths.get( "target/conf/shared.xml" ).toFile( ) ) );
configuration = builder.getConfiguration(); configuration = builder.getConfiguration( );
assertNotNull( configuration.getString( "foo" ) ); assertNotNull( configuration.getString( "foo" ) );
} }

View File

@ -0,0 +1,37 @@
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 org.apache.archiva.redback.common.config.api.ConfigRegistry;
import org.apache.archiva.redback.common.config.api.EventType;
import org.apache.archiva.redback.common.config.api.RegistryListener;
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
public class MockChangeListener implements RegistryListener
{
@Override
public void handleConfigurationChangeEvent( ConfigRegistry registry, EventType eventType, String propertyName, Object propertyValue, Object oldValue )
{
}
}

View File

@ -26,13 +26,17 @@
</appenders> </appenders>
<loggers> <loggers>
<logger name="org.apache.archiva.redback" level="INFO" />
<logger name="commons.beanutils" level="ERROR" />
<logger name="commons.beanutils.FluentPropertyBeanIntrospector" level="ERROR" />
<logger name="org.apache.cxf" level="info"/> <logger name="org.apache.cxf" level="info"/>
<logger name="org.springframework" level="error"/> <logger name="org.springframework" level="ERROR"/>
<logger name="org.apache.archiva.redback.components.cache" 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.archiva.redback.rest" level="ERROR"/>
<logger name="org.apache.catalina" level="off" /> <logger name="org.apache.catalina" level="off" />
<logger name="JPOX" level="ERROR"/> <logger name="JPOX" level="ERROR"/>
<root level="info"> <logger name="org.apache.archiva.redback.common.config.acc2.CfgListener" level="DEBUG" />
<root level="ERROR">
<appender-ref ref="console"/> <appender-ref ref="console"/>
</root> </root>
</loggers> </loggers>

View File

@ -0,0 +1,49 @@
package org.apache.archiva.redback.common.config.api;
/*
* 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.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
*
* A annotation that marks a event listener method as asynchronous. That means the listener event methods
* are run in a separated thread. How tasks are executed is dependent on the implementation.
*
* @author Martin Stockhammer <martin_s@apache.org>
* @since 3.0
*/
@Target(value={METHOD, TYPE})
@Retention(value=RUNTIME)
@Documented
public @interface AsyncListener
{
/**
* May be set to set the executor. The meaning of this value is implementation specific.
* @return The value.
*/
String value() default "";
}

View File

@ -23,6 +23,7 @@ import java.nio.file.Path;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
@ -48,6 +49,14 @@ public interface ConfigRegistry
*/ */
String dump( ); String dump( );
/**
* Get the original value stored in the registry. If not found, <code>null</code> is returned.
*
* @param key The key in the registry.
* @return The value.
*/
Object getValue( String key);
/** /**
* Get a string value from the registry. If not found, <code>null</code> is returned. * Get a string value from the registry. If not found, <code>null</code> is returned.
* *
@ -81,7 +90,7 @@ public interface ConfigRegistry
* @throws java.util.NoSuchElementException * @throws java.util.NoSuchElementException
* if the key is not found * if the key is not found
*/ */
int getInt( String key ); int getInt( String key ) throws NoSuchElementException;
/** /**
* Get an integer value from the registry. If not found, the default value is used. * Get an integer value from the registry. If not found, the default value is used.
@ -108,7 +117,7 @@ public interface ConfigRegistry
* @throws java.util.NoSuchElementException * @throws java.util.NoSuchElementException
* if the key is not found * if the key is not found
*/ */
boolean getBoolean( String key ); boolean getBoolean( String key ) throws NoSuchElementException;
/** /**
* Get a boolean value from the registry. If not found, the default value is used. * Get a boolean value from the registry. If not found, the default value is used.
@ -177,7 +186,7 @@ public interface ConfigRegistry
boolean isEmpty( ); boolean isEmpty( );
/** /**
* Get a list of strings at the given key in the registry. * Get a list of strings at the given key in the registry. If not found a empty list will be returned.
* *
* @param key the key to lookup * @param key the key to lookup
* @return the list of strings * @return the list of strings
@ -198,7 +207,7 @@ public interface ConfigRegistry
* @param key the key to take the subset from * @param key the key to take the subset from
* @return the registry subset * @return the registry subset
*/ */
ConfigRegistry getSubset( String key ); ConfigRegistry getSubset( String key ) throws RegistryException;
/** /**
* Get a list of subsets of the registry, for all keys descended from the given key. * Get a list of subsets of the registry, for all keys descended from the given key.
@ -206,7 +215,7 @@ public interface ConfigRegistry
* @param key the key to take the subsets from * @param key the key to take the subsets from
* @return the registry subsets * @return the registry subsets
*/ */
List<ConfigRegistry> getSubsetList( String key ); List<ConfigRegistry> getSubsetList( String key ) throws RegistryException;
/** /**
* Get a configuration source part of the registry, identified by the given name. If it doesn't exist, <code>null</code> will be * Get a configuration source part of the registry, identified by the given name. If it doesn't exist, <code>null</code> will be
@ -234,7 +243,7 @@ public interface ConfigRegistry
* *
* @param listener the listener * @param listener the listener
*/ */
void registerChangeListener( RegistryListener listener, Pattern... filter ); void registerChangeListener( RegistryListener listener, String prefix );
/** /**
* Unregister the change listener for all events. * Unregister the change listener for all events.
@ -245,17 +254,25 @@ public interface ConfigRegistry
boolean unregisterChangeListener( RegistryListener listener ); boolean unregisterChangeListener( RegistryListener listener );
/** /**
* Get all the keys in this registry. Keys are only retrieved at a depth of 1. * Get all keys on the base level in this registry. Keys are only retrieved at a depth of 1.
* *
* @return the set of keys * @return the set of keys
*/ */
Collection<String> getKeys( ); Collection<String> getBaseKeys( );
/** /**
* Get all the keys in this registry. * Get all the keys in this registry.
* @return the set of keys * @return the set of keys
*/ */
Collection<String> getFullKeys( ); Collection<String> getKeys( );
/**
* Return the keys that match the given prefix.
*
* @param prefix The prefix
* @return A collection of keys
*/
Collection<String> getKeys( String prefix);
/** /**
* Remove a keyed element from the registry. * Remove a keyed element from the registry.

View File

@ -0,0 +1,28 @@
package org.apache.archiva.redback.common.config.api;
/*
* 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.
*/
/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
public enum EventType
{
PROPERTY_SET,PROPERTY_CLEARED,PROPERTY_ADDED,UNDEFINED
}

View File

@ -24,22 +24,20 @@ package org.apache.archiva.redback.common.config.api;
*/ */
public interface RegistryListener public interface RegistryListener
{ {
/**
* Notify the object that there is about to be a configuration change.
*
* @param registry the registry that was changed
* @param propertyName the property being changed
* @param propertyValue the value the property is about to be changed to
*/
void beforeConfigurationChange( ConfigRegistry registry, String propertyName, Object propertyValue );
/** /**
* Notify the object that there has been a configuration change. * Notify the object that there has been a configuration change.
* *
* The method may be annotated by the {@link AsyncListener @AsyncListener} annotation. Which means the method will be
* executed asynchronously.
*
* @param registry the registry that was changed * @param registry the registry that was changed
* @param propertyName the property what was changed * @param propertyName the property what was changed
* @param propertyValue the value the property was changed to * @param propertyValue the value the property was changed to
* @param oldValue The value the property had before * @param oldValue The value the property had before
*/ */
void afterConfigurationChange( ConfigRegistry registry, String propertyName, Object propertyValue, Object oldValue ); void handleConfigurationChangeEvent( ConfigRegistry registry, EventType eventType, String propertyName, Object propertyValue, Object oldValue );
} }