This is an automated email from the ASF dual-hosted git repository. martin_s pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/archiva-redback-core.git
The following commit(s) were added to refs/heads/master by this push: new a528d21 Moving configuration projects into redback and update commons config version a528d21 is described below commit a528d214318ad43eb9a699004ffa3cdd75a32b50 Author: Martin Stockhammer <marti...@apache.org> AuthorDate: Wed Feb 13 00:20:46 2019 +0100 Moving configuration projects into redback and update commons config version --- pom.xml | 17 + redback-common/pom.xml | 1 + .../{ => redback-common-configuration}/pom.xml | 38 +- .../redback-common-configuration-acc2/pom.xml | 107 ++++ .../config/acc2/CommonsConfigurationRegistry.java | 610 +++++++++++++++++++++ .../src/main/resources/META-INF/spring-context.xml | 29 + .../common/config/acc2/AbstractRegistryTest.java | 189 +++++++ .../acc2/CommonsConfigurationRegistryTest.java | 422 ++++++++++++++ .../redback/common/config/acc2/Component.java | 60 ++ .../common/config/acc2/DefaultComponent.java | 128 +++++ .../archiva/redback/common/config/acc2/Nested.java | 33 ++ .../src/test/resources/META-INF/spring-context.xml | 26 + .../src/test/resources/spring-context.xml | 101 ++++ .../src/test/resources/test-save.xml | 23 + .../src/test/resources/test.properties | 25 + .../src/test/resources/test.xml | 42 ++ .../redback-common-configuration-api}/pom.xml | 28 +- .../redback/common/config/api/ConfigRegistry.java | 264 +++++++++ .../common/config/api/RegistryException.java | 38 ++ .../common/config/api/RegistryListener.java | 45 ++ 20 files changed, 2197 insertions(+), 29 deletions(-) diff --git a/pom.xml b/pom.xml index 61ab7fd..68ec204 100644 --- a/pom.xml +++ b/pom.xml @@ -308,6 +308,11 @@ <version>${project.version}</version> </dependency> <dependency> + <groupId>org.apache.archiva.redback</groupId> + <artifactId>redback-common-configuration-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> @@ -648,6 +653,18 @@ <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> + + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + <version>${commons-beanutils.version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> </dependencies> </dependencyManagement> diff --git a/redback-common/pom.xml b/redback-common/pom.xml index 11391a9..7bc4277 100644 --- a/redback-common/pom.xml +++ b/redback-common/pom.xml @@ -35,5 +35,6 @@ <module>redback-common-ldap</module> <module>redback-common-test-resources</module> <module>redback-common-jpa</module> + <module>redback-common-configuration</module> </modules> </project> \ No newline at end of file diff --git a/redback-common/pom.xml b/redback-common/redback-common-configuration/pom.xml similarity index 63% copy from redback-common/pom.xml copy to redback-common/redback-common-configuration/pom.xml index 11391a9..f1e8cf3 100644 --- a/redback-common/pom.xml +++ b/redback-common/redback-common-configuration/pom.xml @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> + <!-- ~ Licensed to the Apache Software Foundation (ASF) under one ~ or more contributor license agreements. See the NOTICE file @@ -17,23 +18,34 @@ ~ specific language governing permissions and limitations ~ under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> + <artifactId>redback-common</artifactId> <groupId>org.apache.archiva.redback</groupId> - <artifactId>redback</artifactId> <version>3.0.0-SNAPSHOT</version> </parent> - <artifactId>redback-common</artifactId> - <name>Redback :: Commons</name> + <modelVersion>4.0.0</modelVersion> + + <artifactId>redback-common-configuration</artifactId> <packaging>pom</packaging> - <properties> - <site.staging.base>${project.parent.basedir}</site.staging.base> - </properties> <modules> - <module>redback-common-ldap</module> - <module>redback-common-test-resources</module> - <module>redback-common-jpa</module> + <module>redback-common-configuration-api</module> + <module>redback-common-configuration-acc2</module> </modules> -</project> \ No newline at end of file + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <skipTests>true</skipTests> + </configuration> + </plugin> + </plugins> + </build> + +</project> 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 0000000..0783bc9 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/pom.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, + ~ software distributed under the License is distributed on an + ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + ~ KIND, either express or implied. See the License for the + ~ specific language governing permissions and limitations + ~ under the License. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>redback-common-configuration</artifactId> + <groupId>org.apache.archiva.redback</groupId> + <version>3.0.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>redback-common-configuration-acc2</artifactId> + + <dependencies> + <dependency> + <groupId>org.apache.archiva.redback</groupId> + <artifactId>redback-common-configuration-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-configuration2</artifactId> + <version>2.4</version> + <exclusions> + <exclusion> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils-core</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>javax.annotation</groupId> + <artifactId>jsr250-api</artifactId> + </dependency> + + <dependency> + <groupId>javax.inject</groupId> + <artifactId>javax.inject</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context-support</artifactId> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>compile</scope> + </dependency> + </dependencies> + +</project> 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 0000000..8fe30d9 --- /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 + * <a href="http://commons.apache.org/commons/configuration">Commons Configuration</a>. The use of Commons Configuration + * enables a variety of sources to be used, including XML files, properties, JNDI, JDBC, etc. + * <p/> + * 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 + * <a href="http://commons.apache.org/commons/configuration/howto_configurationbuilder.html">configuration + * builder</a>. + */ +@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 + * <a href="http://commons.apache.org/configuration/howto_configurationbuilder.html">configuration + * builder</a>. + */ + 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<String> getList( String key ) + { + return configuration.getList(String.class, key ); + } + + public List<ConfigRegistry> getSubsetList( String key ) + { + List<ConfigRegistry> 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<String,String> getProperties( String key ) + { + Configuration configuration = this.configuration.subset( key ); + + Map<String,String> properties = new TreeMap<>(); + Iterator<String> cfgIter = configuration.getKeys( ); + String property; + while ( cfgIter.hasNext() ) + { + property = cfgIter.next(); + List<String> 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<String> getKeys() + { + Set<String> keys = new HashSet<String>(); + + for ( Iterator<String> i = configuration.getKeys(); i.hasNext(); ) + { + String key = i.next(); + + int index = key.indexOf( '.' ); + if ( index < 0 ) + { + keys.add( key ); + } + else + { + keys.add( key.substring( 0, index ) ); + } + } + + return keys; + } + + public Collection getFullKeys() + { + Set<String> keys = new HashSet<String>(); + + for ( Iterator<String> i = configuration.getKeys(); i.hasNext(); ) + { + keys.add( i.next() ); + } + + return keys; + } + + 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<PropertiesConfiguration> 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<XMLConfiguration> 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<PropertiesConfiguration> 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<XMLConfiguration> 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<XMLConfiguration> 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 0000000..4a924fb --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/main/resources/META-INF/spring-context.xml @@ -0,0 +1,29 @@ +<?xml version="1.0"?> + +<!-- + ~ 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. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> + + <context:component-scan base-package="org.apache.archiva.redback.common.config.acc2" /> + +</beans> \ 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 0000000..fa6d637 --- /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 0000000..a1c4e59 --- /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<String,String> 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 0000000..916d2e6 --- /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 0000000..723e751 --- /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 0000000..6e54dce --- /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 0000000..8476963 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/META-INF/spring-context.xml @@ -0,0 +1,26 @@ +<?xml version="1.0"?> + +<!-- + ~ 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. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> + +</beans> \ 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 0000000..895ea07 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/spring-context.xml @@ -0,0 +1,101 @@ +<?xml version="1.0"?> + +<!-- + ~ 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. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> + + <alias name="acc2-configuration" alias="default"/> + + <bean name="builder" class="org.apache.archiva.redback.common.config.acc2.CommonsConfigurationRegistry"> + <property name="properties"> + <value> + <![CDATA[ + <configuration> + <xml fileName="test.xml"/> + <properties fileName="test.properties" config-name="properties"/> + + </configuration> + ]]> + </value> + </property> + </bean> + + <bean name="test-save" class="org.apache.archiva.redback.common.config.acc2.CommonsConfigurationRegistry"> + <property name="properties"> + <value> + <![CDATA[ + <configuration> + <system/> + <xml fileName="${basedir}/target/test-classes/test-save.xml" + config-name="org.codehaus.plexus.registry" + config-at="org.codehaus.plexus.registry"/> + <xml fileName="${basedir}/target/conf/continuum.xml" config-optional="true" + config-at="org.apache.maven.continuum" config-forceCreate="true"/> + <xml fileName="${basedir}/target/conf/shared.xml" config-optional="true" + config-name="org.apache.maven.shared.app.user" config-at="org.apache.maven.shared.app" + config-forceCreate="true"/> + <xml fileName="${basedir}/target/conf/shared.xml" config-optional="true" + config-name="org.apache.maven.shared.app.base" config-at="org.apache.maven.shared.app"/> + <xml fileName="${basedir}/target/conf/common.xml" config-optional="true"/> + <properties fileName="${basedir}/conf/security.properties" config-optional="true" + config-at="org.codehaus.plexus.redback"/> + <xml fileName="${basedir}/target/conf/continuum.xml" config-optional="true" + config-at="org.apache.maven.continuum" config-name="org.apache.maven.continuum.user" + config-forceCreate="true"/> + <xml fileName="${basedir}/target/conf/shared.xml" config-optional="true" + config-at="org.apache.maven.shared.app" /> + <xml fileName="${basedir}/target/conf/common.xml" config-optional="true"/> + <properties fileName="${basedir}/conf/security.properties" config-optional="true" + config-at="org.codehaus.plexus.redback"/> + + </configuration> + ]]> + </value> + </property> + </bean> + + <bean name="forceCreate" class="org.apache.archiva.redback.common.config.acc2.CommonsConfigurationRegistry"> + <property name="properties"> + <value> + <![CDATA[ + <configuration> + <xml fileName="${basedir}/target/foo-forced" config-name="foo" config-forceCreate="true" config-optional="true"/> + </configuration> + ]]> + </value> + </property> + </bean> + + <bean name="noForceCreate" class="org.apache.archiva.redback.common.config.acc2.CommonsConfigurationRegistry"> + <property name="properties"> + <value> + <![CDATA[ + <configuration> + <xml fileName="${basedir}/target/foo" config-name="foo" config-optional="true"/> + </configuration> + ]]> + </value> + </property> + </bean> + +</beans> \ 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 0000000..76667ad --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test-save.xml @@ -0,0 +1,23 @@ +<!-- + ~ 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. + --> + +<registry> + <listElements> + <listElement>1</listElement> + <listElement>2</listElement> + <listElement>3</listElement> + </listElements> +</registry> \ 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 0000000..332952e --- /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 0000000..921aed7 --- /dev/null +++ b/redback-common/redback-common-configuration/redback-common-configuration-acc2/src/test/resources/test.xml @@ -0,0 +1,42 @@ +<!-- + ~ 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. + --> + +<configuration> + <test> + <value>foo</value> + <number>1</number> + <boolean>true</boolean> + <interpolation>${test.value}/bar</interpolation> + </test> + <repository>${user.home}/.m2/repository</repository> + <objects> + <object> + <foo>bar</foo> + </object> + <object> + <foo>baz</foo> + </object> + </objects> + <properties> + <foo>bar</foo> + <bar>baz</bar> + </properties> + <strings> + <string>s1</string> + <string>s2</string> + <string>s3</string> + </strings> +</configuration> diff --git a/redback-common/pom.xml b/redback-common/redback-common-configuration/redback-common-configuration-api/pom.xml similarity index 65% copy from redback-common/pom.xml copy to redback-common/redback-common-configuration/redback-common-configuration-api/pom.xml index 11391a9..28f88cc 100644 --- a/redback-common/pom.xml +++ b/redback-common/redback-common-configuration/redback-common-configuration-api/pom.xml @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> + <!-- ~ Licensed to the Apache Software Foundation (ASF) under one ~ or more contributor license agreements. See the NOTICE file @@ -17,23 +18,18 @@ ~ specific language governing permissions and limitations ~ under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> + <artifactId>redback-common-configuration</artifactId> <groupId>org.apache.archiva.redback</groupId> - <artifactId>redback</artifactId> <version>3.0.0-SNAPSHOT</version> </parent> - <artifactId>redback-common</artifactId> - <name>Redback :: Commons</name> - <packaging>pom</packaging> - <properties> - <site.staging.base>${project.parent.basedir}</site.staging.base> - </properties> - <modules> - <module>redback-common-ldap</module> - <module>redback-common-test-resources</module> - <module>redback-common-jpa</module> - </modules> -</project> \ No newline at end of file + <modelVersion>4.0.0</modelVersion> + + <artifactId>redback-common-configuration-api</artifactId> + + +</project> 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 0000000..cba0548 --- /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, <code>null</code> 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<String> getList( String key ); + + /** + * Get the properties at the given key in the registry. + * + * @param key the key to lookup + * @return the properties + */ + Map<String, String> 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<ConfigRegistry> getSubsetList( String key ); + + /** + * Get a configuration source part of the registry, identified by the given name. If it doesn't exist, <code>null</code> will be + * returned. + * + * Configurations can be combined from different sources. This gives the configuration of a specific source. + * + * @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 <code>true</code> 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<String> getKeys( ); + + /** + * Get all the keys in this registry. + * @return the set of keys + */ + Collection<String> 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 0000000..dc74788 --- /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 0000000..a76d6df --- /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 ); +}