diff --git a/pom.xml b/pom.xml index 61ab7fdf..68ec204a 100644 --- a/pom.xml +++ b/pom.xml @@ -307,6 +307,11 @@ redback-common-jpa ${project.version} + + org.apache.archiva.redback + redback-common-configuration-api + ${project.version} + javax.servlet servlet-api @@ -648,6 +653,18 @@ jaxb-api 2.3.0 + + + commons-beanutils + commons-beanutils + ${commons-beanutils.version} + + + commons-logging + commons-logging + + + diff --git a/redback-common/pom.xml b/redback-common/pom.xml index 11391a9e..7bc42771 100644 --- a/redback-common/pom.xml +++ b/redback-common/pom.xml @@ -35,5 +35,6 @@ redback-common-ldap redback-common-test-resources redback-common-jpa + redback-common-configuration \ No newline at end of file diff --git a/redback-common/redback-common-configuration/pom.xml b/redback-common/redback-common-configuration/pom.xml new file mode 100644 index 00000000..f1e8cf34 --- /dev/null +++ b/redback-common/redback-common-configuration/pom.xml @@ -0,0 +1,51 @@ + + + + + + + redback-common + org.apache.archiva.redback + 3.0.0-SNAPSHOT + + 4.0.0 + + redback-common-configuration + pom + + redback-common-configuration-api + redback-common-configuration-acc2 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/pom.xml b/redback-common/redback-common-configuration/redback-common-configuration-acc2/pom.xml new file mode 100644 index 00000000..0783bc95 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/pom.xml @@ -0,0 +1,107 @@ + + + + + + + redback-common-configuration + org.apache.archiva.redback + 3.0.0-SNAPSHOT + + 4.0.0 + + redback-common-configuration-acc2 + + + + org.apache.archiva.redback + redback-common-configuration-api + + + org.apache.commons + commons-configuration2 + 2.4 + + + commons-beanutils + commons-beanutils-core + + + + + + commons-beanutils + commons-beanutils + + + org.springframework + spring-context + + + org.slf4j + slf4j-api + + + + junit + junit + compile + + + + javax.annotation + jsr250-api + + + + javax.inject + javax.inject + + + + org.springframework + spring-core + compile + + + org.springframework + spring-context + compile + + + org.springframework + spring-context-support + compile + + + org.springframework + spring-beans + compile + + + org.springframework + spring-test + compile + + + + diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/main/java/org/apache/archiva/redback/common/config/acc2/CommonsConfigurationRegistry.java b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/main/java/org/apache/archiva/redback/common/config/acc2/CommonsConfigurationRegistry.java new file mode 100644 index 00000000..8fe30d96 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/main/java/org/apache/archiva/redback/common/config/acc2/CommonsConfigurationRegistry.java @@ -0,0 +1,610 @@ +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.RegistryException; +import org.apache.archiva.redback.common.config.api.RegistryListener; +import org.apache.commons.configuration2.CombinedConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.FileBasedConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.SystemConfiguration; +import org.apache.commons.configuration2.XMLConfiguration; +import org.apache.commons.configuration2.builder.BasicConfigurationBuilder; +import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder; +import org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder; +import org.apache.commons.configuration2.builder.fluent.Parameters; +import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.interpol.ConfigurationInterpolator; +import org.apache.commons.configuration2.interpol.DefaultLookups; +import org.apache.commons.configuration2.interpol.InterpolatorSpecification; +import org.apache.commons.configuration2.io.ClasspathLocationStrategy; +import org.apache.commons.configuration2.io.FileHandler; +import org.apache.commons.configuration2.io.FileSystem; +import org.apache.commons.configuration2.io.FileSystemLocationStrategy; +import org.apache.commons.configuration2.tree.DefaultExpressionEngine; +import org.apache.commons.configuration2.tree.DefaultExpressionEngineSymbols; +import org.apache.commons.configuration2.tree.NodeCombiner; +import org.apache.commons.configuration2.tree.UnionCombiner; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.regex.Pattern; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +/** + * Implementation of the registry component using + * Commons Configuration. The use of Commons Configuration + * enables a variety of sources to be used, including XML files, properties, JNDI, JDBC, etc. + *

+ * The component can be configured using the {@link #properties} configuration item, the content of which should take + * the format of an input to the Commons Configuration + * configuration + * builder. + */ +@Service( "acc2-configuration" ) +public class CommonsConfigurationRegistry + implements ConfigRegistry +{ + /** + * The combined configuration instance that houses the registry. + */ + private Configuration configuration; + + private Logger logger = LoggerFactory.getLogger( getClass() ); + + private String propertyDelimiter = "."; + + /** + * The configuration properties for the registry. This should take the format of an input to the Commons + * Configuration + * configuration + * builder. + */ + private String properties; + + + public CommonsConfigurationRegistry() + { + // default constructor + logger.debug( "empty constructor" ); + } + + public CommonsConfigurationRegistry( Configuration configuration ) + { + if ( configuration == null ) + { + throw new NullPointerException( "configuration can not be null" ); + } + + this.configuration = configuration; + } + + 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() + { + return configuration.isEmpty(); + } + + public ConfigRegistry getSubset( String key ) + { + return new CommonsConfigurationRegistry( configuration.subset( key ) ); + } + + public List getList( String key ) + { + return configuration.getList(String.class, key ); + } + + public List getSubsetList( String key ) + { + List subsets = new ArrayList<>(); + + boolean done = false; + do + { + ConfigRegistry registry = getSubset( key + "(" + subsets.size() + ")" ); + if ( !registry.isEmpty() ) + { + subsets.add( registry ); + } + else + { + done = true; + } + } + while ( !done ); + + return subsets; + } + + @Override + public ConfigRegistry getSource( String name ) + { + return null; + } + + public Map getProperties( String key ) + { + Configuration configuration = this.configuration.subset( key ); + + Map properties = new TreeMap<>(); + Iterator cfgIter = configuration.getKeys( ); + String property; + while ( cfgIter.hasNext() ) + { + property = cfgIter.next(); + List l = configuration.getList( String.class, property ); + String value = String.join(",", l); + properties.put( property, value ); + } + return properties; + } + + public void save() + throws RegistryException + { + if ( configuration instanceof FileBasedConfiguration ) + { + FileBasedConfiguration fileConfiguration = (FileBasedConfiguration) configuration; + try + { + new FileHandler( fileConfiguration ).save(); + } + catch ( ConfigurationException e ) + { + throw new RegistryException( e.getMessage(), e ); + } + } + else + { + throw new RegistryException( "Can only save file-based configurations" ); + } + } + + @Override + public void registerChangeListener( RegistryListener listener, Pattern... filter ) + { + + } + + @Override + public boolean unregisterChangeListener( RegistryListener listener ) + { + return false; + } + + + public Collection getKeys() + { + Set keys = new HashSet(); + + for ( Iterator 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 keys = new HashSet(); + + for ( Iterator i = configuration.getKeys(); i.hasNext(); ) + { + keys.add( i.next() ); + } + + return keys; + } + + public void remove( String key ) + { + configuration.clearProperty( key ); + } + + public void removeSubset( String key ) + { + // create temporary list since removing a key will modify the iterator from configuration + 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 ) + { + return configuration.getString( key ); + } + + public String getString( String key, String defaultValue ) + { + return configuration.getString( key, defaultValue ); + } + + public void setString( String key, String value ) + { + configuration.setProperty( key, value ); + } + + public int getInt( String key ) + { + return configuration.getInt( key ); + } + + public int getInt( String key, int defaultValue ) + { + return configuration.getInt( key, defaultValue ); + } + + public void setInt( String key, int value ) + { + configuration.setProperty( key, Integer.valueOf( value ) ); + } + + public boolean getBoolean( String key ) + { + return configuration.getBoolean( key ); + } + + public boolean getBoolean( String key, boolean defaultValue ) + { + return configuration.getBoolean( key, defaultValue ); + } + + public void setBoolean( String key, boolean value ) + { + configuration.setProperty( key, Boolean.valueOf( value ) ); + } + + public void addConfigurationFromResource( String name, String resource ) + throws RegistryException + { + addConfigurationFromResource( name, resource, null ); + } + + public void addConfigurationFromResource( String name, String resource, String prefix ) + throws RegistryException + { + if (configuration instanceof CombinedConfiguration) + { + String atPrefix = StringUtils.isEmpty( prefix ) ? null : prefix; + CombinedConfiguration configuration = (CombinedConfiguration) this.configuration; + if ( resource.endsWith( ".properties" ) ) + { + try + { + logger.debug( "Loading properties configuration from classloader resource: {}", resource ); + FileBasedConfigurationBuilder builder = new FileBasedConfigurationBuilder<>( PropertiesConfiguration.class ) + .configure( new Parameters().properties() + .setLocationStrategy( new ClasspathLocationStrategy() ) + .setFileName( resource ) ); + configuration.addConfiguration( builder.getConfiguration() , name, atPrefix ); + } + catch ( ConfigurationException e ) + { + throw new RegistryException( + "Unable to add configuration from resource '" + resource + "': " + e.getMessage( ), e ); + } + } + else if ( resource.endsWith( ".xml" ) ) + { + try + { + logger.debug( "Loading XML configuration from classloader resource: {}", resource ); + FileBasedConfigurationBuilder builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class ) + .configure( new Parameters().xml() + .setLocationStrategy( new ClasspathLocationStrategy() ) + .setFileName( resource ) ); + configuration.addConfiguration( builder.getConfiguration(), name, atPrefix ); + } + catch ( ConfigurationException e ) + { + throw new RegistryException( + "Unable to add configuration from resource '" + resource + "': " + e.getMessage( ), e ); + } + } + else + { + throw new RegistryException( + "Unable to add configuration from resource '" + resource + "': unrecognised type" ); + } + } else { + throw new RegistryException( "The underlying configuration object is not a combined configuration " ); + } + } + + @Override + public void addConfigurationFromFile( String name, Path file ) throws RegistryException + { + addConfigurationFromFile( name, file, "" ); + } + + public void addConfigurationFromFile( String name, Path file, String prefix ) + throws RegistryException + { + if (this.configuration instanceof CombinedConfiguration) + { + String atPrefix = StringUtils.isEmpty( prefix ) ? null : prefix; + CombinedConfiguration configuration = (CombinedConfiguration) this.configuration; + String fileName = file.getFileName().toString(); + if ( fileName.endsWith( ".properties" ) ) + { + try + { + logger.debug( "Loading properties configuration from file: {}", file ); + FileBasedConfigurationBuilder builder = new FileBasedConfigurationBuilder<>( PropertiesConfiguration.class ) + .configure( new Parameters().properties() + .setLocationStrategy( new FileSystemLocationStrategy() ) + .setFile( file.toFile() ) ); + configuration.addConfiguration( builder.getConfiguration() , name, atPrefix ); + } + catch ( ConfigurationException e ) + { + throw new RegistryException( + "Unable to add configuration from file '" + file.getFileName( ) + "': " + e.getMessage( ), e ); + } + } + else if ( fileName.endsWith( ".xml" ) ) + { + try + { + logger.debug( "Loading XML configuration from file: {}", file ); + FileBasedConfigurationBuilder builder = new FileBasedConfigurationBuilder<>( XMLConfiguration.class ) + .configure( new Parameters().xml() + .setLocationStrategy( new ClasspathLocationStrategy() ) + .setFile( file.toFile()) ); + configuration.addConfiguration( builder.getConfiguration(), name, atPrefix ); + } + catch ( ConfigurationException e ) + { + throw new RegistryException( + "Unable to add configuration from file '" + file.getFileName( ) + "': " + e.getMessage( ), e ); + } + } + else + { + throw new RegistryException( + "Unable to add configuration from file '" + file.getFileName( ) + "': unrecognised type" ); + } + } else { + throw new RegistryException( "The underlying configuration is not a combined configuration object." ); + } + } + + class StringFileSystem extends FileSystem { + + String content; + String encoding = "UTF-8"; + + StringFileSystem(String content) { + this.content = content; + } + + @Override + public InputStream getInputStream( URL url ) throws ConfigurationException + { + try + { + return new ByteArrayInputStream( content.getBytes(encoding) ); + } + catch ( UnsupportedEncodingException e ) + { + logger.error("Bad encoding for FileSystem"); + throw new ConfigurationException( "Bad encoding specified" ); + } + } + + @Override + public OutputStream getOutputStream( URL url ) throws ConfigurationException + { + return new ByteArrayOutputStream( 0 ); + } + + @Override + public OutputStream getOutputStream( File file ) throws ConfigurationException + { + return new ByteArrayOutputStream( 0 ); + } + + @Override + public String getPath( File file, URL url, String basePath, String fileName ) + { + return basePath+"/"+fileName; + } + + @Override + public String getBasePath( String path ) + { + return path; + } + + @Override + public String getFileName( String path ) + { + return path; + } + + @Override + public URL locateFromURL( String basePath, String fileName ) + { + try + { + return new URL("file://"+getPath(null, null, basePath, fileName)); + } + catch ( MalformedURLException e ) + { + // ignore + return null; + } + } + + @Override + public URL getURL( String basePath, String fileName ) throws MalformedURLException + { + try + { + return new URL("file://"+getPath(null, null, basePath, fileName)); + } + catch ( MalformedURLException e ) + { + // ignore + return null; + } + } + + } + + @PostConstruct + public void initialize() + throws RegistryException + { + try + { + CombinedConfiguration configuration; + if ( StringUtils.isNotBlank( properties ) ) + { + System.out.println("Configuration"); + System.out.println(properties); + Parameters params = new Parameters(); + DefaultExpressionEngineSymbols symbols = new DefaultExpressionEngineSymbols.Builder(DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS ) + .setPropertyDelimiter( propertyDelimiter ) + .setIndexStart( "(" ) + .setIndexEnd( ")" ) + .setEscapedDelimiter( "\\"+propertyDelimiter ) + . create( ); + DefaultExpressionEngine expressionEngine = new DefaultExpressionEngine( symbols ); + ConfigurationInterpolator interpolator = ConfigurationInterpolator.fromSpecification( new InterpolatorSpecification.Builder().withDefaultLookup( DefaultLookups.SYSTEM_PROPERTIES.getLookup() ).create() ); + System.out.println(interpolator.getDefaultLookups().stream( ).map(p -> p.toString()).collect( Collectors.joining( ","))); + String interpolatedProps = interpolator.interpolate( properties ).toString(); + logger.debug( "Loading configuration into commons-configuration, xml {}", interpolatedProps ); + FileSystem fs = new StringFileSystem( interpolatedProps ); + FileBasedConfigurationBuilder cfgBuilder = + new FileBasedConfigurationBuilder<>( + XMLConfiguration.class) + .configure(params.xml() + .setInterpolator( interpolator ) + .setFileSystem( fs ) + .setFileName( "config.xml") + .setListDelimiterHandler( + new DefaultListDelimiterHandler(',')) + .setExpressionEngine( expressionEngine ) + .setThrowExceptionOnMissing(false)); + + CombinedConfigurationBuilder builder = new CombinedConfigurationBuilder(). + configure(params.combined().setDefinitionBuilder( cfgBuilder )); + + configuration = builder.getConfiguration(); + + // interpolation as plexus did it before + + //configuration.set + } + else + { + logger.debug( "Creating a default configuration - no configuration was provided" ); + NodeCombiner combiner = new UnionCombiner(); + configuration = new CombinedConfiguration(combiner); + } + + configuration.addConfiguration( new SystemConfiguration(), "SystemProperties" ); + + this.configuration = configuration; + } + catch ( ConfigurationException e ) + { + throw new RuntimeException( e.getMessage(), e ); + } + } + + public void setProperties( String properties ) + { + this.properties = properties; + } + + public ConfigRegistry getSection( String name ) + { + CombinedConfiguration combinedConfiguration = (CombinedConfiguration) configuration; + Configuration configuration = combinedConfiguration.getConfiguration( name ); + return configuration == null ? null : new CommonsConfigurationRegistry( configuration ); + } + + public String getPropertyDelimiter() + { + return propertyDelimiter; + } + + public void setPropertyDelimiter( String propertyDelimiter ) + { + this.propertyDelimiter = propertyDelimiter; + } +} diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/main/resources/META-INF/spring-context.xml b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/main/resources/META-INF/spring-context.xml new file mode 100755 index 00000000..4a924fbe --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/main/resources/META-INF/spring-context.xml @@ -0,0 +1,29 @@ + + + + + + + + \ No newline at end of file diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/AbstractRegistryTest.java b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/AbstractRegistryTest.java new file mode 100644 index 00000000..fa6d6371 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/AbstractRegistryTest.java @@ -0,0 +1,189 @@ +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 junit.framework.TestCase; +import org.apache.archiva.redback.common.config.api.ConfigRegistry; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import javax.inject.Inject; +import java.util.NoSuchElementException; + +/** + * @author Olivier Lamy + * + * @since 8 feb. 07 + */ +@RunWith( value = SpringJUnit4ClassRunner.class ) +@ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml", "classpath*:/spring-context.xml" } ) +public abstract class AbstractRegistryTest + extends TestCase +{ + + @Inject + protected ApplicationContext applicationContext; + + public abstract String getRoleHint(); + + public ConfigRegistry getRegistry() + throws Exception + { + return getRegistry( getRoleHint() ); + } + + public ConfigRegistry getRegistry( String name ) + throws Exception + { + ConfigRegistry registry = applicationContext.getBean( name, ConfigRegistry.class ); + registry.initialize(); + return registry; + } + + @Test + public void testInt() + throws Exception + { + ConfigRegistry registry = getRegistry(); + assertEquals( "not 2 ", 2, registry.getInt( "two" ) ); + } + + @Test + public void testIntUnknown() + throws Exception + { + ConfigRegistry registry = getRegistry(); + try + { + registry.getInt( "unknown" ); + assertTrue( "no NoSuchElementException", false ); + } + catch ( NoSuchElementException e ) + { + // cool it works + } + } + + @Test + public void testString() + throws Exception + { + ConfigRegistry registry = getRegistry(); + assertEquals( "not foo ", "foo", registry.getString( "string" ) ); + } + + @Test + public void testStringUnknown() + throws Exception + { + ConfigRegistry registry = getRegistry(); + String value = registry.getString( "unknown" ); + assertNull( "unknow not null", value ); + + } + + @Test + public void testBoolean() + throws Exception + { + ConfigRegistry registry = getRegistry(); + assertEquals( "not true ", true, registry.getBoolean( "boolean" ) ); + } + + @Test + public void testBooleanUnknown() + throws Exception + { + ConfigRegistry registry = getRegistry(); + try + { + registry.getBoolean( "unknown" ); + assertTrue( "no NoSuchElementException", false ); + } + catch ( NoSuchElementException e ) + { + // cool it works + } + } + + @Test + public void testIsNotEmpty() + throws Exception + { + assertFalse( getRegistry().isEmpty() ); + } + + @Test + public void testGetSubRegistry() + throws Exception + { + assertNotNull( getRegistry().getSubset( "subOne" ) ); + } + + @Test + public void testgetSubsetValues() + throws Exception + { + ConfigRegistry sub = getRegistry().getSubset( "subOne" ); + assertNotNull( sub ); + assertEquals( "entryOne", sub.getString( "firstEntry" ) ); + assertEquals( "entryTwo", sub.getString( "secondEntry" ) ); + } + + @Test + public void testgetSubsetEmpty() + throws Exception + { + ConfigRegistry registry = getRegistry(); + assertNotNull( registry.getSubset( "none" ) ); + assertTrue( registry.getSubset( "none" ).isEmpty() ); + + } + + @Test + public void testSetBoolean() + throws Exception + { + ConfigRegistry registry = getRegistry(); + registry.setBoolean( "keyTrue", true ); + assertTrue( registry.getBoolean( "keyTrue" ) ); + } + + @Test + public void testSetInt() + throws Exception + { + ConfigRegistry registry = getRegistry(); + registry.setInt( "keyInt", 3 ); + assertEquals( 3, registry.getInt( "keyInt" ) ); + } + + @Test + public void testSetString() + throws Exception + { + ConfigRegistry registry = getRegistry(); + registry.setString( "what", "zorglub" ); + assertEquals( "zorglub", registry.getString( "what" ) ); + } +} diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/CommonsConfigurationRegistryTest.java b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/CommonsConfigurationRegistryTest.java new file mode 100644 index 00000000..a1c4e591 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/CommonsConfigurationRegistryTest.java @@ -0,0 +1,422 @@ +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.RegistryException; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +/** + * Test the commons configuration registry. + */ +public class CommonsConfigurationRegistryTest + extends AbstractRegistryTest +{ + private ConfigRegistry registry; + + private final Logger logger = LoggerFactory.getLogger( CommonsConfigurationRegistryTest.class ); + + + private static final int INT_TEST_VALUE = 8080; + + public String getRoleHint() + { + return "builder"; + } + + @Test + public void requirementTest() { + assertNotNull(System.getProperty("basedir")); + assertTrue( System.getProperty( "basedir" ).length()>0 ); + assertNotNull(System.getProperty("user.dir")); + assertTrue( System.getProperty( "user.dir" ).length()>0 ); + + } + + @Test + public void testDefaultConfiguration() + throws Exception + { + registry = getRegistry( "default" ); + + assertEquals( "Check system property override", System.getProperty( "user.dir" ), + registry.getString( "user.dir" ) ); + assertEquals( "Check system property", System.getProperty( "user.home" ), registry.getString( "user.home" ) ); + assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) ); + } + + @Test + public void testBuilderConfiguration() + throws Exception + { + registry = getRegistry( "builder" ); + + assertEquals( "Check system property override", "new user dir", registry.getString( "user.dir" ) ); + assertEquals( "Check system property default", System.getProperty( "user.home" ), + registry.getString( "user.home" ) ); + assertEquals( "Check other properties are loaded", "foo", registry.getString( "test.value" ) ); + assertEquals( "Check other properties are loaded", 1, registry.getInt( "test.number" ) ); + assertTrue( "Check other properties are loaded", registry.getBoolean( "test.boolean" ) ); + } + + @Test + public void testDump() + throws Exception + { + registry = getRegistry( "default" ); + + String dump = registry.dump(); + assertTrue( dump.startsWith( "Configuration Dump.\n\"" ) ); + } + + @Test + public void testDefaults() + throws Exception + { + registry = getRegistry( "builder" ); + + assertNull( "Check getString returns null", registry.getString( "foo" ) ); + assertEquals( "Check getString returns default", "bar", registry.getString( "foo", "bar" ) ); + + try + { + registry.getInt( "foo" ); + fail(); + } + catch ( NoSuchElementException e ) + { + // success + } + + assertEquals( "Check getInt returns default", INT_TEST_VALUE, registry.getInt( "foo", INT_TEST_VALUE ) ); + + try + { + registry.getBoolean( "foo" ); + fail(); + } + catch ( NoSuchElementException e ) + { + // success + } + + assertTrue( "Check getBoolean returns default", registry.getBoolean( "foo", true ) ); + } + + @Test + public void testInterpolation() + throws Exception + { + registry = getRegistry( "builder" ); + + assertEquals( "Check system property interpolation", System.getProperty( "user.home" ) + "/.m2/repository", + registry.getString( "repository" ) ); + + assertEquals( "Check configuration value interpolation", "foo/bar", + registry.getString( "test.interpolation" ) ); + } + + @Test + public void testAddConfigurationXmlFile() + throws Exception + { + registry = getRegistry( "default" ); + + registry.addConfigurationFromFile( "test.xml", Paths.get( "src/test/resources/test.xml" ) ); + System.out.println(registry.dump()); + assertEquals( "Check system property default", System.getProperty( "user.dir" ), + registry.getString( "user.dir" ) ); + assertEquals( "Check other properties are loaded", "foo", registry.getString( "test.value" ) ); + } + + @Test + public void testAddConfigurationPropertiesFile() + throws Exception + { + registry = getRegistry( "default" ); + + registry.addConfigurationFromFile( + "test.properties", Paths.get("src/test/resources/test.properties" ) ); + + assertEquals( "Check system property default", System.getProperty( "user.dir" ), + registry.getString( "user.dir" ) ); + assertEquals( "Check other properties are loaded", "baz", registry.getString( "foo.bar" ) ); + assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) ); + } + + @Test + public void testAddConfigurationXmlResource() + throws Exception + { + registry = getRegistry( "default" ); + + registry.addConfigurationFromResource( "test.xml-r", "test.xml" ); + + assertEquals( "Check system property default", System.getProperty( "user.dir" ), + registry.getString( "user.dir" ) ); + assertEquals( "Check other properties are loaded", "foo", registry.getString( "test.value" ) ); + } + + @Test + public void testAddConfigurationPropertiesResource() + throws Exception + { + registry = getRegistry( "default" ); + + registry.addConfigurationFromResource( "test.properties-r", "test.properties" ); + + assertEquals( "Check system property default", System.getProperty( "user.dir" ), + registry.getString( "user.dir" ) ); + assertEquals( "Check other properties are loaded", "baz", registry.getString( "foo.bar" ) ); + assertNull( "Check other properties are not loaded", registry.getString( "test.value" ) ); + } + + @Test + public void testAddConfigurationUnrecognisedType() + throws Exception + { + registry = getRegistry( "default" ); + + try + { + registry.addConfigurationFromResource( "test.foo", "test.foo" ); + fail(); + } + catch ( RegistryException e ) + { + // success + } + + try + { + registry.addConfigurationFromFile( "test.foo-file", + Paths.get( "src/test/resources/test.foo" ) ); + fail(); + } + catch ( RegistryException e ) + { + // success + } + } + + @Test + public void testIsEmpty() + throws Exception + { + registry = getRegistry( "default" ); + + assertFalse( registry.isEmpty() ); + assertTrue( registry.getSubset( "foo" ).isEmpty() ); + } + + @Test + public void testGetSubset() + throws Exception + { + registry = getRegistry( "builder" ); + + ConfigRegistry registry = this.registry.getSubset( "test" ); + assertEquals( "Check other properties are loaded", "foo", registry.getString( "value" ) ); + assertEquals( "Check other properties are loaded", 1, registry.getInt( "number" ) ); + assertTrue( "Check other properties are loaded", registry.getBoolean( "boolean" ) ); + } + + @Test + public void testGetSubsetList() + throws Exception + { + registry = getRegistry( "builder" ); + + List list = registry.getSubsetList( "objects.object" ); + assertEquals( 2, list.size() ); + ConfigRegistry r = (ConfigRegistry) list.get( 0 ); + assertTrue( "bar".equals( r.getString( "foo" ) ) || "baz".equals( r.getString( "foo" ) ) ); + r = (ConfigRegistry) list.get( 1 ); + assertTrue( "bar".equals( r.getString( "foo" ) ) || "baz".equals( r.getString( "foo" ) ) ); + } + + @Test + public void testGetProperties() + throws Exception + { + registry = getRegistry( "builder" ); + + Map properties = registry.getProperties( "properties" ); + assertEquals( 2, properties.size() ); + assertEquals( "bar", properties.get( "foo" ) ); + assertEquals( "baz", properties.get( "bar" ) ); + } + + @Test + public void testGetList() + throws Exception + { + registry = getRegistry( "builder" ); + + List list = registry.getList( "strings.string" ); + assertEquals( 3, list.size() ); + assertEquals( "s1", list.get( 0 ) ); + assertEquals( "s2", list.get( 1 ) ); + assertEquals( "s3", list.get( 2 ) ); + } + + @Test + public void testGetSection() + throws Exception + { + registry = getRegistry( "builder" ); + + ConfigRegistry registry = this.registry.getSource( "properties" ); + assertNull( registry.getString( "test.value" ) ); + assertEquals( "baz", registry.getString( "foo.bar" ) ); + } + + @Test + public void testRemoveKey() + throws Exception + { + registry = getRegistry( "builder" ); + + ConfigRegistry registry = this.registry.getSource( "properties" ); + assertEquals( "baz", registry.getString( "foo.bar" ) ); + registry.remove( "foo.bar" ); + assertNull( registry.getString( "foo.bar" ) ); + } + + @Test + public void testRemoveSubset() + throws Exception + { + registry = getRegistry( "builder" ); + + registry.removeSubset( "strings" ); + assertEquals( Collections.EMPTY_LIST, registry.getList( "strings.string" ) ); + + ConfigRegistry registry = this.registry.getSource( "properties" ); + assertEquals( "baz", registry.getString( "foo.bar" ) ); + registry.remove( "foo" ); + assertEquals( "baz", registry.getString( "foo.bar" ) ); + registry.removeSubset( "foo" ); + assertNull( registry.getString( "foo.bar" ) ); + } + +/* TODO: for 1.4 + public void testGetForcedCreateByName() + throws Exception + { + registry = (Registry) lookup( Registry.class.getName(), "forceCreate" ); + + String testFile = getTestFile( "target/foo-forced" ).getAbsolutePath(); + assertFalse( FileUtils.fileExists( testFile ) ); + + assertNotNull( registry.getSection( "foo" ) ); + } +*/ + + @Test + public void testGetDontForceCreateByName() + throws Exception + { + registry = getRegistry( "noForceCreate" ); + + assertNull( registry.getSource( "foo" ) ); + } + + @Test + public void testSaveSection() + throws Exception + { + Path src = Paths.get( "src/test/resources/test-save.xml" ); + Path dest = Paths.get( "target/test-classes/test-save.xml" ); + Files.copy( src, dest ); + + registry = getRegistry( "test-save" ); + + ConfigRegistry registry = this.registry.getSource( "org.codehaus.plexus.registry" ); + assertEquals( "check list elements", Arrays.asList( new String[]{ "1", "2", "3" } ), + registry.getList( "listElements.listElement" ) ); + + registry.remove( "listElements.listElement(1)" ); + registry.save(); + + // @TODO: Migrate test implementation to commons config 2.4 +// XMLConfiguration configuration = new XMLConfiguration( dest ); +// assertEquals( Arrays.asList( new String[]{ "1", "3" } ), configuration.getList( "listElements.listElement" ) ); +// +// // file in ${basedir}/target/conf/shared.xml +// Registry section = this.registry.getSection( "org.apache.maven.shared.app.user" ); +// section.setString( "foo", "zloug" ); +// section.save(); +// +// configuration = new XMLConfiguration( new File( "target/conf/shared.xml" ) ); +// assertNotNull( configuration.getString( "foo" ) ); + + } + + + // TODO: Migrate implementation to commons configuration 2.4 +// @Test +// public void test_listener() +// throws Exception +// { +// registry = getRegistry( "default" ); +// +// int listenerSize = CommonsConfigurationRegistry.class.cast( registry ).getChangeListenersSize(); +// +// MockChangeListener mockChangeListener = new MockChangeListener(); +// +// registry.addChangeListener( mockChangeListener ); +// +// registry.addChangeListener( new MockChangeListener() ); +// +// assertEquals( listenerSize + 2, CommonsConfigurationRegistry.class.cast( registry ).getChangeListenersSize() ); +// +// registry.removeChangeListener( mockChangeListener ); +// +// assertEquals( listenerSize + 1, CommonsConfigurationRegistry.class.cast( registry ).getChangeListenersSize() ); +// } +// +// private static class MockChangeListener +// implements RegistryListener +// { +// @Override +// public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue ) +// { +// // no op +// } +// +// @Override +// public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) +// { +// // no op +// } +// } +} diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/Component.java b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/Component.java new file mode 100644 index 00000000..916d2e66 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/Component.java @@ -0,0 +1,60 @@ +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( ); +} diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/DefaultComponent.java b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/DefaultComponent.java new file mode 100644 index 00000000..723e7513 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/DefaultComponent.java @@ -0,0 +1,128 @@ +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; + } +} diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/Nested.java b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/Nested.java new file mode 100644 index 00000000..6e54dce9 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/java/org/apache/archiva/redback/common/config/acc2/Nested.java @@ -0,0 +1,33 @@ +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. + */ + +/** + * Nested class for testing. + */ +public class Nested +{ + private String foo; + + public String getFoo() + { + return foo; + } +} diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/META-INF/spring-context.xml b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/META-INF/spring-context.xml new file mode 100755 index 00000000..8476963e --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/META-INF/spring-context.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/spring-context.xml b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/spring-context.xml new file mode 100755 index 00000000..895ea07b --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/spring-context.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + ]]> + + + + + + + + + + + ]]> + + + + + \ No newline at end of file diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test-save.xml b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test-save.xml new file mode 100644 index 00000000..76667ada --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test-save.xml @@ -0,0 +1,23 @@ + + + + + 1 + 2 + 3 + + \ No newline at end of file diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test.properties b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test.properties new file mode 100644 index 00000000..332952e2 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test.properties @@ -0,0 +1,25 @@ +# +# Copyright 2007 The Codehaus Foundation. +# +# Licensed 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. +# + +user.dir=new user dir +foo.bar=baz + +# test from plexus-registry tests +subOne.firstEntry=entryOne +subOne.secondEntry=entryTwo +two=2 +string=foo +boolean=true diff --git a/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test.xml b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test.xml new file mode 100644 index 00000000..921aed7b --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test.xml @@ -0,0 +1,42 @@ + + + + + foo + 1 + true + ${test.value}/bar + + ${user.home}/.m2/repository + + + bar + + + baz + + + + bar + baz + + + s1 + s2 + s3 + + diff --git a/redback-common/redback-common-configuration/redback-common-configuration-api/pom.xml b/redback-common/redback-common-configuration/redback-common-configuration-api/pom.xml new file mode 100644 index 00000000..28f88cca --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-api/pom.xml @@ -0,0 +1,35 @@ + + + + + + + redback-common-configuration + org.apache.archiva.redback + 3.0.0-SNAPSHOT + + 4.0.0 + + redback-common-configuration-api + + + diff --git a/redback-common/redback-common-configuration/redback-common-configuration-api/src/main/java/org/apache/archiva/redback/common/config/api/ConfigRegistry.java b/redback-common/redback-common-configuration/redback-common-configuration-api/src/main/java/org/apache/archiva/redback/common/config/api/ConfigRegistry.java new file mode 100644 index 00000000..cba0548f --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-api/src/main/java/org/apache/archiva/redback/common/config/api/ConfigRegistry.java @@ -0,0 +1,264 @@ +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.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Map; +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. + * + */ +public interface ConfigRegistry +{ + + /** + * Dump the entire registry to a string, for debugging purposes. + * + * @return the registry contents + */ + String dump( ); + + /** + * Get a string value from the registry. If not found, null is returned. + * + * @param key the key in the registry + * @return the value + */ + String getString( String key ); + + /** + * Get a string value from the registry. If not found, the default value is used. + * + * @param key the key in the registry + * @param defaultValue the default value + * @return the value + */ + String getString( String key, String defaultValue ); + + /** + * Set a string value in the registry. + * + * @param key the key in the registry + * @param value the value to set + */ + void setString( String key, String value ); + + /** + * Get an integer value from the registry. If not found, an exception is thrown. + * + * @param key the key in the registry + * @return the value + * @throws java.util.NoSuchElementException + * if the key is not found + */ + int getInt( String key ); + + /** + * Get an integer value from the registry. If not found, the default value is used. + * + * @param key the key in the registry + * @param defaultValue the default value + * @return the value + */ + int getInt( String key, int defaultValue ); + + /** + * Set an integer value in the registry. + * + * @param key the key in the registry + * @param value the value to set + */ + void setInt( String key, int value ); + + /** + * Get a boolean value from the registry. If not found, an exception is thrown. + * + * @param key the key in the registry + * @return the value + * @throws java.util.NoSuchElementException + * if the key is not found + */ + boolean getBoolean( String key ); + + /** + * Get a boolean value from the registry. If not found, the default value is used. + * + * @param key the key in the registry + * @param defaultValue the default value + * @return the value + */ + boolean getBoolean( String key, boolean defaultValue ); + + /** + * Set a boolean value in the registry. + * + * @param key the key in the registry + * @param value the value to set + */ + void setBoolean( String key, boolean value ); + + /** + * Load configuration from the given classloader resource. + * + * @param resource the location to load the configuration from + * @throws RegistryException if a problem occurred reading the resource to add to the registry + */ + void addConfigurationFromResource( String name, String resource ) + throws RegistryException; + + /** + * Load configuration from the given classloader resource. + * + * @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 + */ + void addConfigurationFromResource( String name, String resource, String prefix ) + throws RegistryException; + + /** + * Load configuration 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 + */ + void addConfigurationFromFile( String name, Path file ) + throws RegistryException; + + /** + * Load configuration 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 + * @throws RegistryException if a problem occurred reading the resource to add to the registry + */ + void addConfigurationFromFile( String name, Path file, String prefix ) + throws RegistryException; + + /** + * Determine if the registry contains any elements. + * + * @return whether the registry contains any elements + */ + boolean isEmpty( ); + + /** + * Get a list of strings at the given key in the registry. + * + * @param key the key to lookup + * @return the list of strings + */ + List getList( String key ); + + /** + * Get the properties at the given key in the registry. + * + * @param key the key to lookup + * @return the properties + */ + Map getProperties( String key ); + + /** + * Get a subset of the registry, for all keys descended from the given key. + * + * @param key the key to take the subset from + * @return the registry subset + */ + ConfigRegistry getSubset( String key ); + + /** + * Get a list of subsets of the registry, for all keys descended from the given key. + * + * @param key the key to take the subsets from + * @return the registry subsets + */ + List getSubsetList( String key ); + + /** + * Get a configuration source part of the registry, identified by the given name. If it doesn't exist, null will be + * returned. + * + * Configurations can be combined from different sources. This gives the configuration of a specific source. + * + * @param name The source name of the configuration source. + * @return the The config registry object that represents this source part. + */ + ConfigRegistry getSource( String name ); + + /** + * Save any changes to the registry since it was loaded. + * + * @throws RegistryException if there was a problem saving the registry + * @throws UnsupportedOperationException if the registry is not writable + */ + void save( ) + throws RegistryException, UnsupportedOperationException; + + /** + * Register a change listener for configuration keys that match the given patterns. + * + * @param listener the listener + */ + void registerChangeListener( RegistryListener listener, Pattern... filter ); + + /** + * Unregister the change listener for all events. + * + * @param listener + * @return true if has been removed + */ + boolean unregisterChangeListener( RegistryListener listener ); + + /** + * Get all the keys in this registry. Keys are only retrieved at a depth of 1. + * + * @return the set of keys + */ + Collection getKeys( ); + + /** + * Get all the keys in this registry. + * @return the set of keys + */ + Collection getFullKeys( ); + + /** + * Remove a keyed element from the registry. + * + * @param key the key to remove + */ + void remove( String key ); + + /** + * Remove a keyed subset of the registry. + * + * @param key the subset to remove + */ + void removeSubset( String key ); + + void initialize( ) throws RegistryException; +} diff --git a/redback-common/redback-common-configuration/redback-common-configuration-api/src/main/java/org/apache/archiva/redback/common/config/api/RegistryException.java b/redback-common/redback-common-configuration/redback-common-configuration-api/src/main/java/org/apache/archiva/redback/common/config/api/RegistryException.java new file mode 100644 index 00000000..dc747880 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-api/src/main/java/org/apache/archiva/redback/common/config/api/RegistryException.java @@ -0,0 +1,38 @@ +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. + */ + +/** + * Exception occurring in the registry component. + */ +public class RegistryException + extends Exception +{ + public RegistryException( String message ) + { + super( message ); + } + + public RegistryException( String message, Throwable cause ) + { + super( message, cause ); + } + +} diff --git a/redback-common/redback-common-configuration/redback-common-configuration-api/src/main/java/org/apache/archiva/redback/common/config/api/RegistryListener.java b/redback-common/redback-common-configuration/redback-common-configuration-api/src/main/java/org/apache/archiva/redback/common/config/api/RegistryListener.java new file mode 100644 index 00000000..a76d6dfc --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-api/src/main/java/org/apache/archiva/redback/common/config/api/RegistryListener.java @@ -0,0 +1,45 @@ +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. + */ + +/** + * Receives notifications of configuration changes in thre registry. + */ +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. + * + * @param registry the registry that was changed + * @param propertyName the property what was changed + * @param propertyValue the value the property was changed to + * @param oldValue The value the property had before + */ + void afterConfigurationChange( ConfigRegistry registry, String propertyName, Object propertyValue, Object oldValue ); +}