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-components.git

commit fc1b6ff91a03e350be88806754e777bcd9eb8d2a
Author: Martin Stockhammer <[email protected]>
AuthorDate: Sat Nov 16 17:12:26 2019 +0100

    Moving spring-registry to combined components project
---
 pom.xml                                            |   1 +
 spring-registry/Jenkinsfile                        |  20 +
 spring-registry/pom.xml                            | 130 ++++++
 spring-registry/spring-registry-api/pom.xml        |  43 ++
 .../archiva/components/registry/Registry.java      | 262 ++++++++++++
 .../components/registry/RegistryException.java     |  38 ++
 .../components/registry/RegistryListener.java      |  44 ++
 spring-registry/spring-registry-commons/pom.xml    | 157 +++++++
 .../commons/CommonsConfigurationRegistry.java      | 467 +++++++++++++++++++++
 .../commons/ConfigurationListenerDelegate.java     |  82 ++++
 .../src/main/resources/META-INF/spring-context.xml |  35 ++
 .../registry/test/AbstractRegistryTest.java        | 189 +++++++++
 .../test/CommonsConfigurationRegistryTest.java     | 413 ++++++++++++++++++
 .../components/registry/test/Component.java        |  60 +++
 .../components/registry/test/DefaultComponent.java | 128 ++++++
 .../archiva/components/registry/test/Nested.java   |  33 ++
 .../org/codehaus/plexus/registry/phase.properties  |  26 ++
 .../org/codehaus/plexus/registry/test.properties   |  25 ++
 .../org/codehaus/plexus/registry/test.xml          |  42 ++
 .../src/test/resources/spring-context.xml          | 102 +++++
 .../src/test/resources/test-save.xml               |  23 +
 spring-registry/src/site/apt/index.apt             | 155 +++++++
 spring-registry/src/site/site.xml                  |  34 ++
 23 files changed, 2509 insertions(+)

diff --git a/pom.xml b/pom.xml
index 9ebe160..e2e7b7e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,6 +48,7 @@
     <module>expression-evaluator</module>
     <module>spring-apacheds</module>
     <module>graph</module>
+    <module>spring-registry</module>
   </modules> 
 
   <scm>
diff --git a/spring-registry/Jenkinsfile b/spring-registry/Jenkinsfile
new file mode 100644
index 0000000..5f264a1
--- /dev/null
+++ b/spring-registry/Jenkinsfile
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+asfStandardBuild()
diff --git a/spring-registry/pom.xml b/spring-registry/pom.xml
new file mode 100644
index 0000000..e299086
--- /dev/null
+++ b/spring-registry/pom.xml
@@ -0,0 +1,130 @@
+<!--
+  ~ 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.
+  -->
+
+<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";>
+  <parent>
+    <groupId>org.apache.archiva.components</groupId>
+    <artifactId>archiva-components</artifactId>
+    <version>3.0-SNAPSHOT</version>
+  </parent>  
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.archiva.components.registry</groupId>
+  <artifactId>spring-registry</artifactId>
+  <version>3.0-SNAPSHOT</version>
+  <name>Archiva Components :: Spring Registry</name>
+  <packaging>pom</packaging>
+
+  <properties>
+    <site.staging.base>${project.basedir}/../site</site.staging.base>
+  </properties>
+
+  <url>${webUrl}/${project.artifactId}</url>
+
+  <scm>
+    <url>${scmBrowseUrl}</url>
+  </scm>
+
+  <modules>
+    <module>spring-registry-api</module>
+    <module>spring-registry-commons</module>
+  </modules>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.apache.archiva.components.registry</groupId>
+        <artifactId>spring-registry-api</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.archiva.components.registry</groupId>
+        <artifactId>spring-registry-commons</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>commons-configuration</groupId>
+        <artifactId>commons-configuration</artifactId>
+        <version>${commons.configuration.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-text</artifactId>
+        <version>${commons.text.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>commons-collections</groupId>
+        <artifactId>commons-collections</artifactId>
+        <version>${commons.collections.3.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>commons-beanutils</groupId>
+        <artifactId>commons-beanutils</artifactId>
+        <version>${commons.beanutils.version}</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+
+  </dependencies>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-release-plugin</artifactId>
+          <configuration>
+            <preparationGoals>clean install</preparationGoals>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.8.0</version>
+        <configuration>
+          <source>${compiler.source}</source>
+          <target>${compiler.target}</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <reporting>
+    <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-jxr-plugin</artifactId>
+          <reportSets>
+            <reportSet>
+              <id>aggregate</id>
+              <inherited>false</inherited>
+              <reports>
+                <report>aggregate</report>
+              </reports>
+            </reportSet>
+          </reportSets>
+        </plugin>
+    </plugins>
+  </reporting>
+
+</project>
diff --git a/spring-registry/spring-registry-api/pom.xml 
b/spring-registry/spring-registry-api/pom.xml
new file mode 100644
index 0000000..11c7ce7
--- /dev/null
+++ b/spring-registry/spring-registry-api/pom.xml
@@ -0,0 +1,43 @@
+<?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/maven-v4_0_0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.archiva.components.registry</groupId>
+    <artifactId>spring-registry</artifactId>
+    <version>3.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.apache.archiva.components.registry</groupId>
+  <artifactId>spring-registry-api</artifactId>
+  <name>Archiva Components :: Spring Registry Api</name>
+
+  <properties>
+    <site.staging.base>${project.parent.basedir}/../site</site.staging.base>
+  </properties>
+  <url>${webUrl}/spring-registry/${project.artifactId}</url>
+
+  <scm>
+    <url>${scmBrowseUrl};f=${project.artifactId}</url>
+  </scm>
+
+</project>
diff --git 
a/spring-registry/spring-registry-api/src/main/java/org/apache/archiva/components/registry/Registry.java
 
b/spring-registry/spring-registry-api/src/main/java/org/apache/archiva/components/registry/Registry.java
new file mode 100644
index 0000000..2be4b3c
--- /dev/null
+++ 
b/spring-registry/spring-registry-api/src/main/java/org/apache/archiva/components/registry/Registry.java
@@ -0,0 +1,262 @@
+package org.apache.archiva.components.registry;
+
+/*
+ * 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.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * The Plexus registry is a single source of external configuration for Plexus 
components and applications.
+ * 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 Registry
+{
+
+    /**
+     * 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 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 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( File 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( File 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 );
+
+    /**
+     * TODO move to Map which is more generic ?
+     * Get the properties at the given key in the registry.
+     *
+     * @param key the key to lookup
+     * @return the properties
+     */
+    Properties 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
+     */
+    Registry 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 subsection of the registry, identified by the given name. If it 
doesn't exist, <code>null</code> will be
+     * returned.
+     *
+     * @param name registry section name
+     * @return the registry
+     */
+    Registry getSection( 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;
+
+    /**
+     * Add a change listener. Note that settings this on the base registry 
will only detect 'invalidation' events, not
+     * individual changes. You should retrieve the named sub-registry to 
listen for changes.
+     *
+     * @param listener the listener
+     * @todo this isn't ideal, so maybe fix combined configuration to re-fire 
it's events to it's own listeners in the c-c implementation
+     */
+    void addChangeListener( RegistryListener listener );
+
+    /**
+     * @param listener
+     * @return <code>true</code> if has been removed
+     * @since 2.3
+     */
+    boolean removeChangeListener( 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.
+     * @since 2.1
+     * @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/spring-registry/spring-registry-api/src/main/java/org/apache/archiva/components/registry/RegistryException.java
 
b/spring-registry/spring-registry-api/src/main/java/org/apache/archiva/components/registry/RegistryException.java
new file mode 100644
index 0000000..eec5f64
--- /dev/null
+++ 
b/spring-registry/spring-registry-api/src/main/java/org/apache/archiva/components/registry/RegistryException.java
@@ -0,0 +1,38 @@
+package org.apache.archiva.components.registry;
+
+/*
+ * 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/spring-registry/spring-registry-api/src/main/java/org/apache/archiva/components/registry/RegistryListener.java
 
b/spring-registry/spring-registry-api/src/main/java/org/apache/archiva/components/registry/RegistryListener.java
new file mode 100644
index 0000000..72d6b59
--- /dev/null
+++ 
b/spring-registry/spring-registry-api/src/main/java/org/apache/archiva/components/registry/RegistryListener.java
@@ -0,0 +1,44 @@
+package org.apache.archiva.components.registry;
+
+/*
+ * 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( Registry 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
+     */
+    void afterConfigurationChange( Registry registry, String propertyName, 
Object propertyValue );
+}
diff --git a/spring-registry/spring-registry-commons/pom.xml 
b/spring-registry/spring-registry-commons/pom.xml
new file mode 100644
index 0000000..fd38209
--- /dev/null
+++ b/spring-registry/spring-registry-commons/pom.xml
@@ -0,0 +1,157 @@
+<?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/maven-v4_0_0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.archiva.components.registry</groupId>
+    <artifactId>spring-registry</artifactId>
+    <version>3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>spring-registry-commons</artifactId>
+  <name>Archiva Components :: Spring Registry Commons</name>
+  <properties>
+    <site.staging.base>${project.parent.basedir}/../site</site.staging.base>
+  </properties>
+
+  <url>${webUrl}/spring-registry/${project.artifactId}</url>
+
+  <scm>
+    <url>${scmBrowseUrl};f=${project.artifactId}</url>
+  </scm>
+
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.archiva.components.registry</groupId>
+      <artifactId>spring-registry-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-configuration</groupId>
+      <artifactId>commons-configuration</artifactId>
+      <version>${commons.configuration.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>commons-beanutils</groupId>
+          <artifactId>commons-beanutils-core</artifactId>
+        </exclusion>
+        <!-- targeting JDK 1.4, xml parser/apis not needed -->
+        <exclusion>
+          <groupId>xerces</groupId>
+          <artifactId>xerces</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>xerces</groupId>
+          <artifactId>xercesImpl</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>xalan</groupId>
+          <artifactId>xalan</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>xml-apis</groupId>
+          <artifactId>xml-apis</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>servletapi</groupId>
+          <artifactId>servletapi</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-core</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-beans</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-beanutils</groupId>
+      <artifactId>commons-beanutils</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.inject</groupId>
+      <artifactId>javax.inject</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-text</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-jcl</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemPropertyVariables>
+            <basedir>${basedir}</basedir>
+          </systemPropertyVariables>
+          <forkMode>once</forkMode>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git 
a/spring-registry/spring-registry-commons/src/main/java/org/apache/archiva/components/registry/commons/CommonsConfigurationRegistry.java
 
b/spring-registry/spring-registry-commons/src/main/java/org/apache/archiva/components/registry/commons/CommonsConfigurationRegistry.java
new file mode 100644
index 0000000..e069118
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/main/java/org/apache/archiva/components/registry/commons/CommonsConfigurationRegistry.java
@@ -0,0 +1,467 @@
+package org.apache.archiva.components.registry.commons;
+
+/*
+ * 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.components.registry.Registry;
+import org.apache.archiva.components.registry.RegistryException;
+import org.apache.archiva.components.registry.RegistryListener;
+import org.apache.commons.configuration.CombinedConfiguration;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.DefaultConfigurationBuilder;
+import org.apache.commons.configuration.FileConfiguration;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration.SystemConfiguration;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.configuration.event.EventSource;
+import org.apache.commons.configuration.tree.DefaultExpressionEngine;
+import org.apache.commons.lang3.StringUtils;
+
+import org.apache.commons.text.StringSubstitutor;
+import org.apache.commons.text.lookup.StringLookupFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.io.File;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * 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( "commons-configuration" )
+public class CommonsConfigurationRegistry
+    implements Registry
+{
+    /**
+     * 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 Registry getSubset( String key )
+    {
+        return new CommonsConfigurationRegistry( configuration.subset( key ) );
+    }
+
+    public List getList( String key )
+    {
+        return configuration.getList( key );
+    }
+
+    public List<Registry> getSubsetList( String key )
+    {
+        List<Registry> subsets = new ArrayList<>( );
+
+        boolean done = false;
+        do
+        {
+            Registry registry = getSubset( key + "(" + subsets.size( ) + ")" );
+            if ( !registry.isEmpty( ) )
+            {
+                subsets.add( registry );
+            }
+            else
+            {
+                done = true;
+            }
+        }
+        while ( !done );
+
+        return subsets;
+    }
+
+    public Properties getProperties( String key )
+    {
+        Configuration configuration = this.configuration.subset( key );
+
+        Properties properties = new Properties( );
+        for ( Iterator i = configuration.getKeys( ); i.hasNext( ); )
+        {
+            String property = (String) i.next( );
+            List l = configuration.getList( property );
+            StringBuilder sb = new StringBuilder( );
+            for ( Object element : l )
+            {
+                sb.append( (String) element );
+                sb.append( "," );
+            }
+            if ( sb.length( ) > 0 )
+            {
+                sb.deleteCharAt( sb.length( ) - 1 );
+            }
+            properties.setProperty( property, sb.toString( ) );
+        }
+        return properties;
+    }
+
+    public void save( )
+        throws RegistryException
+    {
+        if ( configuration instanceof FileConfiguration )
+        {
+            FileConfiguration fileConfiguration = (FileConfiguration) 
configuration;
+            try
+            {
+                fileConfiguration.save( );
+            }
+            catch ( ConfigurationException e )
+            {
+                throw new RegistryException( e.getMessage( ), e );
+            }
+        }
+        else
+        {
+            throw new RegistryException( "Can only save file-based 
configurations" );
+        }
+    }
+
+    public void addChangeListener( RegistryListener listener )
+    {
+        EventSource eventSource = EventSource.class.cast( this.configuration );
+
+        eventSource.addConfigurationListener( new 
ConfigurationListenerDelegate( listener, this ) );
+    }
+
+    @Override
+    public boolean removeChangeListener( RegistryListener listener )
+    {
+        EventSource eventSource = EventSource.class.cast( this.configuration );
+
+        boolean removed =
+            eventSource.removeConfigurationListener( new 
ConfigurationListenerDelegate( listener, this ) );
+
+        return removed;
+    }
+
+
+    public int getChangeListenersSize( )
+    {
+        return EventSource.class.cast( this.configuration 
).getConfigurationListeners( ).size( );
+    }
+
+    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 resource )
+        throws RegistryException
+    {
+        addConfigurationFromResource( resource, null );
+    }
+
+    public void addConfigurationFromResource( String resource, String prefix )
+        throws RegistryException
+    {
+        CombinedConfiguration configuration = (CombinedConfiguration) 
this.configuration;
+        if ( resource.endsWith( ".properties" ) )
+        {
+            try
+            {
+                logger.debug( "Loading properties configuration from 
classloader resource: {}", resource );
+                configuration.addConfiguration( new PropertiesConfiguration( 
resource ), null, prefix );
+            }
+            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 );
+                configuration.addConfiguration( new XMLConfiguration( resource 
), null, prefix );
+            }
+            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" );
+        }
+    }
+
+    public void addConfigurationFromFile( File file )
+        throws RegistryException
+    {
+        addConfigurationFromFile( file, null );
+    }
+
+    public void addConfigurationFromFile( File file, String prefix )
+        throws RegistryException
+    {
+        CombinedConfiguration configuration = (CombinedConfiguration) 
this.configuration;
+        if ( file.getName( ).endsWith( ".properties" ) )
+        {
+            try
+            {
+                logger.debug( "Loading properties configuration from file: 
{}", file );
+                configuration.addConfiguration( new PropertiesConfiguration( 
file ), null, prefix );
+            }
+            catch ( ConfigurationException e )
+            {
+                throw new RegistryException(
+                    "Unable to add configuration from file '" + file.getName( 
) + "': " + e.getMessage( ), e );
+            }
+        }
+        else if ( file.getName( ).endsWith( ".xml" ) )
+        {
+            try
+            {
+                logger.debug( "Loading XML configuration from file: {}", file 
);
+                configuration.addConfiguration( new XMLConfiguration( file ), 
null, prefix );
+            }
+            catch ( ConfigurationException e )
+            {
+                throw new RegistryException(
+                    "Unable to add configuration from file '" + file.getName( 
) + "': " + e.getMessage( ), e );
+            }
+        }
+        else
+        {
+            throw new RegistryException(
+                "Unable to add configuration from file '" + file.getName( ) + 
"': unrecognised type" );
+        }
+    }
+
+    @PostConstruct
+    public void initialize( )
+        throws RegistryException
+    {
+        try
+        {
+            CombinedConfiguration configuration;
+            if ( StringUtils.isNotBlank( properties ) )
+            {
+                DefaultConfigurationBuilder builder = new 
DefaultConfigurationBuilder( );
+                DefaultExpressionEngine expressionEngine = new 
DefaultExpressionEngine( );
+                expressionEngine.setPropertyDelimiter( propertyDelimiter );
+                builder.setExpressionEngine( expressionEngine );
+
+                StringSubstitutor substitutor = new StringSubstitutor( 
StringLookupFactory.INSTANCE.systemPropertyStringLookup( ) );
+
+                String interpolatedProps = substitutor.replace( properties );
+
+                logger.debug( "Loading configuration into 
commons-configuration, xml {}", interpolatedProps );
+                builder.load( new StringReader( interpolatedProps ) );
+                configuration = builder.getConfiguration( false );
+                configuration.setExpressionEngine( expressionEngine );
+                //configuration.set
+            }
+            else
+            {
+                logger.debug( "Creating a default configuration - no 
configuration was provided" );
+                configuration = new CombinedConfiguration( );
+            }
+
+            configuration.addConfiguration( new SystemConfiguration( ) );
+
+            this.configuration = configuration;
+        }
+        catch ( ConfigurationException e )
+        {
+            throw new RuntimeException( e.getMessage( ), e );
+        }
+    }
+
+    public void setProperties( String properties )
+    {
+        this.properties = properties;
+    }
+
+    public Registry 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/spring-registry/spring-registry-commons/src/main/java/org/apache/archiva/components/registry/commons/ConfigurationListenerDelegate.java
 
b/spring-registry/spring-registry-commons/src/main/java/org/apache/archiva/components/registry/commons/ConfigurationListenerDelegate.java
new file mode 100644
index 0000000..e0847f0
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/main/java/org/apache/archiva/components/registry/commons/ConfigurationListenerDelegate.java
@@ -0,0 +1,82 @@
+package org.apache.archiva.components.registry.commons;
+
+/*
+ * 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.components.registry.Registry;
+import org.apache.archiva.components.registry.RegistryListener;
+import org.apache.commons.configuration.event.ConfigurationEvent;
+import org.apache.commons.configuration.event.ConfigurationListener;
+
+/**
+ * Commons configuration listener that delegates to the given registry 
listener.
+ */
+public class ConfigurationListenerDelegate
+    implements ConfigurationListener
+{
+    /**
+     * Delegate listener.
+     */
+    private RegistryListener listener;
+
+    /**
+     * Delegate registry.
+     */
+    private Registry registry;
+
+    public ConfigurationListenerDelegate( RegistryListener listener, Registry 
registry )
+    {
+        this.listener = listener;
+
+        this.registry = registry;
+    }
+
+    public void configurationChanged( ConfigurationEvent event )
+    {
+        if ( event.getPropertyName() != null )
+        {
+            if ( event.isBeforeUpdate() )
+            {
+                listener.beforeConfigurationChange( registry, 
event.getPropertyName(), event.getPropertyValue() );
+            }
+            else
+            {
+                listener.afterConfigurationChange( registry, 
event.getPropertyName(), event.getPropertyValue() );
+            }
+        }
+    }
+
+    // needed to be sure elements are properly removed from the listeners list
+    @Override
+    public int hashCode()
+    {
+        return this.listener.hashCode();
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( ConfigurationListenerDelegate.class.isAssignableFrom( 
obj.getClass() ) )
+        {
+            ConfigurationListenerDelegate delegate = 
ConfigurationListenerDelegate.class.cast( obj );
+            return delegate.listener == this.listener;
+        }
+        return super.equals( obj );
+    }
+}
diff --git 
a/spring-registry/spring-registry-commons/src/main/resources/META-INF/spring-context.xml
 
b/spring-registry/spring-registry-commons/src/main/resources/META-INF/spring-context.xml
new file mode 100644
index 0000000..b624dac
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/main/resources/META-INF/spring-context.xml
@@ -0,0 +1,35 @@
+<?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-3.0.xsd";
+       default-lazy-init="true">
+
+  <context:annotation-config />
+  <context:component-scan 
+    base-package="org.apache.archiva.components.registry.commons"/>
+
+ 
+</beans>
diff --git 
a/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/AbstractRegistryTest.java
 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/AbstractRegistryTest.java
new file mode 100644
index 0000000..daf07db
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/AbstractRegistryTest.java
@@ -0,0 +1,189 @@
+package org.apache.archiva.components.registry.test;
+
+/*
+ * 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.components.registry.Registry;
+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 Registry getRegistry()
+        throws Exception
+    {
+        return getRegistry( getRoleHint() );
+    }
+
+    public Registry getRegistry( String name )
+        throws Exception
+    {
+        Registry registry = applicationContext.getBean( name, Registry.class );
+        registry.initialize();
+        return registry;
+    }
+
+    @Test
+    public void testInt()
+        throws Exception
+    {
+        Registry registry = getRegistry();
+        assertEquals( "not 2 ", 2, registry.getInt( "two" ) );
+    }
+
+    @Test
+    public void testIntUnknown()
+        throws Exception
+    {
+        Registry registry = getRegistry();
+        try
+        {
+            registry.getInt( "unknown" );
+            assertTrue( "no NoSuchElementException", false );
+        }
+        catch ( NoSuchElementException e )
+        {
+            // cool it works
+        }
+    }
+
+    @Test
+    public void testString()
+        throws Exception
+    {
+        Registry registry = getRegistry();
+        assertEquals( "not foo ", "foo", registry.getString( "string" ) );
+    }
+
+    @Test
+    public void testStringUnknown()
+        throws Exception
+    {
+        Registry registry = getRegistry();
+        String value = registry.getString( "unknown" );
+        assertNull( "unknow not null", value );
+
+    }
+
+    @Test
+    public void testBoolean()
+        throws Exception
+    {
+        Registry registry = getRegistry();
+        assertEquals( "not true ", true, registry.getBoolean( "boolean" ) );
+    }
+
+    @Test
+    public void testBooleanUnknown()
+        throws Exception
+    {
+        Registry 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
+    {
+        Registry sub = getRegistry().getSubset( "subOne" );
+        assertNotNull( sub );
+        assertEquals( "entryOne", sub.getString( "firstEntry" ) );
+        assertEquals( "entryTwo", sub.getString( "secondEntry" ) );
+    }
+
+    @Test
+    public void testgetSubsetEmpty()
+        throws Exception
+    {
+        Registry registry = getRegistry();
+        assertNotNull( registry.getSubset( "none" ) );
+        assertTrue( registry.getSubset( "none" ).isEmpty() );
+
+    }
+
+    @Test
+    public void testSetBoolean()
+        throws Exception
+    {
+        Registry registry = getRegistry();
+        registry.setBoolean( "keyTrue", true );
+        assertTrue( registry.getBoolean( "keyTrue" ) );
+    }
+
+    @Test
+    public void testSetInt()
+        throws Exception
+    {
+        Registry registry = getRegistry();
+        registry.setInt( "keyInt", 3 );
+        assertEquals( 3, registry.getInt( "keyInt" ) );
+    }
+
+    @Test
+    public void testSetString()
+        throws Exception
+    {
+        Registry registry = getRegistry();
+        registry.setString( "what", "zorglub" );
+        assertEquals( "zorglub", registry.getString( "what" ) );
+    }
+}
diff --git 
a/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/CommonsConfigurationRegistryTest.java
 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/CommonsConfigurationRegistryTest.java
new file mode 100644
index 0000000..bab97f3
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/CommonsConfigurationRegistryTest.java
@@ -0,0 +1,413 @@
+package org.apache.archiva.components.registry.test;
+
+/*
+ * 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.components.registry.Registry;
+import org.apache.archiva.components.registry.RegistryException;
+import org.apache.archiva.components.registry.RegistryListener;
+import 
org.apache.archiva.components.registry.commons.CommonsConfigurationRegistry;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.FileCopyUtils;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+
+/**
+ * Test the commons configuration registry.
+ */
+public class CommonsConfigurationRegistryTest
+    extends AbstractRegistryTest
+{
+    private Registry registry;
+
+    private final Logger logger = LoggerFactory.getLogger( getClass() );
+
+
+    private static final int INT_TEST_VALUE = 8080;
+
+    public String getRoleHint()
+    {
+        return "builder";
+    }
+
+    @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( new File( 
"./src/test/resources/org/codehaus/plexus/registry/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 testAddConfigurationPropertiesFile()
+        throws Exception
+    {
+        registry = getRegistry( "default" );
+
+        registry.addConfigurationFromFile(
+            new File( 
"./src/test/resources/org/codehaus/plexus/registry/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( 
"org/codehaus/plexus/registry/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( 
"org/codehaus/plexus/registry/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( 
"org/codehaus/plexus/registry/test.foo" );
+            fail();
+        }
+        catch ( RegistryException e )
+        {
+            // success
+        }
+
+        try
+        {
+            registry.addConfigurationFromFile(
+                new File( 
"./src/test/resources/org/codehaus/plexus/registry/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" );
+
+        Registry 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() );
+        Registry r = (Registry) list.get( 0 );
+        assertTrue( "bar".equals( r.getString( "foo" ) ) || "baz".equals( 
r.getString( "foo" ) ) );
+        r = (Registry) list.get( 1 );
+        assertTrue( "bar".equals( r.getString( "foo" ) ) || "baz".equals( 
r.getString( "foo" ) ) );
+    }
+
+    @Test
+    public void testGetProperties()
+        throws Exception
+    {
+        registry = getRegistry( "builder" );
+
+        Properties properties = registry.getProperties( "properties" );
+        assertEquals( 2, properties.size() );
+        assertEquals( "bar", properties.getProperty( "foo" ) );
+        assertEquals( "baz", properties.getProperty( "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" );
+
+        Registry registry = this.registry.getSection( "properties" );
+        assertNull( registry.getString( "test.value" ) );
+        assertEquals( "baz", registry.getString( "foo.bar" ) );
+    }
+
+    @Test
+    public void testRemoveKey()
+        throws Exception
+    {
+        registry = getRegistry( "builder" );
+
+        Registry registry = this.registry.getSection( "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" ) );
+
+        Registry registry = this.registry.getSection( "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.getSection( "foo" ) );
+    }
+
+    @Test
+    public void testSaveSection()
+        throws Exception
+    {
+        File src = new File( "./src/test/resources/test-save.xml" );
+        File dest = new File( "./target/test-classes/test-save.xml" );
+        FileCopyUtils.copy( src, dest );
+
+        registry = getRegistry( "test-save" );
+
+        Registry registry = this.registry.getSection( 
"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();
+
+        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" ) );
+
+    }
+
+
+    @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/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/Component.java
 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/Component.java
new file mode 100644
index 0000000..92c424b
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/Component.java
@@ -0,0 +1,60 @@
+package org.apache.archiva.components.registry.test;
+
+/*
+ * 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/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/DefaultComponent.java
 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/DefaultComponent.java
new file mode 100644
index 0000000..9b94733
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/DefaultComponent.java
@@ -0,0 +1,128 @@
+package org.apache.archiva.components.registry.test;
+
+/*
+ * 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/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/Nested.java
 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/Nested.java
new file mode 100644
index 0000000..c29d6b6
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/test/java/org/apache/archiva/components/registry/test/Nested.java
@@ -0,0 +1,33 @@
+package org.apache.archiva.components.registry.test;
+
+/*
+ * 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/spring-registry/spring-registry-commons/src/test/resources/org/codehaus/plexus/registry/phase.properties
 
b/spring-registry/spring-registry-commons/src/test/resources/org/codehaus/plexus/registry/phase.properties
new file mode 100644
index 0000000..3b0a55e
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/test/resources/org/codehaus/plexus/registry/phase.properties
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+Component.default.number=2
+Component.default.key=value1
+Component.default.properties.org.jpox.PreserveCase=always
+Component.default.properties.key=value2
+Component.default.list=S1, S2
+Component.default.map.org.jpox.PreserveCase=always
+Component.default.map.key=value3
+Component.default.mergeProperties.key32=value32
+Component.default.mergeList=v3, v4
+Component.default.nested.foo=bar
diff --git 
a/spring-registry/spring-registry-commons/src/test/resources/org/codehaus/plexus/registry/test.properties
 
b/spring-registry/spring-registry-commons/src/test/resources/org/codehaus/plexus/registry/test.properties
new file mode 100644
index 0000000..332952e
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/test/resources/org/codehaus/plexus/registry/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/spring-registry/spring-registry-commons/src/test/resources/org/codehaus/plexus/registry/test.xml
 
b/spring-registry/spring-registry-commons/src/test/resources/org/codehaus/plexus/registry/test.xml
new file mode 100644
index 0000000..921aed7
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/test/resources/org/codehaus/plexus/registry/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/spring-registry/spring-registry-commons/src/test/resources/spring-context.xml 
b/spring-registry/spring-registry-commons/src/test/resources/spring-context.xml
new file mode 100755
index 0000000..2174eda
--- /dev/null
+++ 
b/spring-registry/spring-registry-commons/src/test/resources/spring-context.xml
@@ -0,0 +1,102 @@
+<?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";>
+
+
+  <alias name="commons-configuration" alias="default"/>
+
+  <bean name="builder" 
class="org.apache.archiva.components.registry.commons.CommonsConfigurationRegistry">
+    <property name="properties">
+      <value>
+        <![CDATA[
+          <configuration>
+            <xml fileName="org/codehaus/plexus/registry/test.xml"/>
+            <properties 
fileName="org/codehaus/plexus/registry/test.properties" 
config-name="properties"/>
+
+          </configuration>
+        ]]>
+      </value>
+    </property>
+  </bean>
+
+  <bean name="test-save" 
class="org.apache.archiva.components.registry.commons.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"/>
+          <jndi prefix="java:comp/env" config-optional="true"/>
+          <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.components.registry.commons.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.components.registry.commons.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/spring-registry/spring-registry-commons/src/test/resources/test-save.xml 
b/spring-registry/spring-registry-commons/src/test/resources/test-save.xml
new file mode 100644
index 0000000..76667ad
--- /dev/null
+++ b/spring-registry/spring-registry-commons/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/spring-registry/src/site/apt/index.apt 
b/spring-registry/src/site/apt/index.apt
new file mode 100644
index 0000000..c77349d
--- /dev/null
+++ b/spring-registry/src/site/apt/index.apt
@@ -0,0 +1,155 @@
+ -----
+ Plexus Registry Component
+ -----
+ Brett Porter
+ -----
+ 7 February 2007
+ -----
+
+~~ 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.
+
+~~ NOTE: For help with the syntax of this file, see:
+~~ http://maven.apache.org/guides/mini/guide-apt-format.html
+
+Plexus Registry
+
+    The Plexus registry is a single source of external configuration for 
Plexus components and applications.
+    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.
+
+    To facilitate a variety of providers, 
{{{http://jakarta.apache.org/commons/configuration/} Commons Configuration}}
+    is used to implement the backing storage.
+
+    This relies on a pull-based (or lookup) mechanism - the applications 
request specific pieces of configuration at
+    the time they need them, and it is retrieved from the registry.
+
+    The registry is configurable so that configuration can be placed in any 
location desired, and is shared container
+    wide. A registry using the same file as other running VMs should operate 
correctly.
+
+    <Note:> Inside the application server, this means that the scope is 
application wide as each application has it's
+    own container. It may be feasible to provide a single registry for the 
whole server, but this has not yet been
+    tested. This would only be necessary if the server was to dictate 
configuration locations that the registry was
+    not already configured to use. Of course, such additional locations could 
be added to the application registry
+    instances programmatically as well.
+
+* Example Configuration
+
+-----
+<component>
+  <role>org.codehaus.components.registry.Registry</role>
+  
<implementation>org.codehaus.plexus.registry.CommonsConfigurationRegistry</implementation>
+  <role-hint>commons-configuration</role-hint>
+  <configuration>
+    <properties>
+      <system/>
+      <jndi prefix="java:comp/env" config-optional="true"/>
+      <xml fileName="${user.home}/.m2/archiva.xml" config-optional="true" 
config-name="org.apache.maven.archiva"
+           config-at="org.apache.maven.archiva" config-forceCreate="true"/>
+      <properties fileName="${user.home}/.m2/security.properties" 
config-optional="true"
+                  config-at="org.codehaus.plexus.security"/>
+    </properties>
+  </configuration>
+</component>
+-----
+
+  The configuration inside the outer <<<\<properties\>>>> element is 
equivalent to the
+  
{{{http://jakarta.apache.org/commons/configuration/howto_configurationbuilder.html#Using_DefaultConfigurationBuilder}
 builder syntax}}
+  for Commons Configuration. This maps to similar concepts in the registry.
+
+  In this example, the precedence is to first look in the system properties, 
then JNDI, then the given XML file, and
+  finally the given properties file.
+
+  Registries can have 'sections', which are declared as partitioned areas of 
the registry. This is done using the
+  <<<config-name>>> attribute in Commons Configuration. While the sections 
behave normally as a part of the global
+  registry, they can easily be retrieved independently. This is particularly 
useful for write-back operations so the
+  file the section is stored in can be saved when the registry is modified.
+
+  Each configuration source can be configured with a given mount-point in the 
registry using the <<<config-at>>>
+  attribute. This will cause all of the properties to be stored with the given 
prefix.
+
+* Using the Registry  
+
+  The registry can be used as a simple directory, for example:
+
+-----
+int value = registry.getInt( "test.property" );
+String text = registry.getString( "text.data" );
+boolean enabled = registry.getBoolean( "system.enabled", true );
+-----
+
+  The first parameter is always a key. The registry is hierachical, so in the 
key, a <<<.>>> (period) represents a
+  nested configuration, and can be traversed to any level.
+
+  The second parameter specifies a default value. If it is not given, then 
<<<null>>> is returned for strings if the
+  key is not found in the registry, and an exception is thrown for integers 
and booleans under the same circumstances.
+
+** Subsets and Sections
+
+  There are two ways to work with a portion of the registry at a time: subsets 
and sections.
+
+  Sections were encountered earlier - and while they return a subset it may 
span a number of different base prefixes,
+  depending on whether <<<config-at>>> was specified on the section or not. 
Even so, if it is a subset of the
+  hierachy, some elements of the hierachy at the same level might not be 
returned because they come from a different
+  section.
+
+  On the other hand, subsets are reductions of the registry to keys descending 
from a given prefix.
+
+  Once a subset (or section) is obtained, it behaves the same as the registry 
as a whole, however it will have fewer
+  values, and looking up values will not have the prefix as a part of the key.
+
+  For example:
+
+-----
+String value = registry.getString( "org.codehaus.plexus.registry.value" );
+Registry subset = registry.getSubset( "org.codehaus.plexus.registry" );
+value = subset.getString( "value" ); // this will equal the earlier value 
retrieved
+-----
+
+** Lists and Maps
+
+  It is also possible to retrieve subsets of the registry as collections.
+
+    * <<<getProperties(key)>>>: Maps and properties are straightforward - the 
subset is converted into key/value pairs
+                                and returned as a map.
+
+    * <<<getSubsetList(key)>>>: For lists of complex types that will still 
contain more than one key/value pair,
+                                this method can be used to retrieve them as a 
list of subset registries.
+
+    * <<<getList(key)>>>:       For lists of simple types, this method can be 
used to get a list of value objects.
+                                
+** Using Models
+
+  To simplify the translation of configuration into reusable beans and to 
produce a self-documenting system, Modello
+  can be used to generate registry I/O classes. The appropriate goals in the 
plugin are <<<registry-reader>>> and
+  <<<registry-writer>>>.
+
+** Saving Changes
+
+  Saving changes to a registry is quite simple:
+
+-----
+registry.save();
+-----
+
+  Note that the registry must be a file-based section (saving the entire 
registry will not succeed). It will be saved
+  to the same location that it was loaded from.
+
+** Adding Change Listeners
+
+  ~~TODO
+
diff --git a/spring-registry/src/site/site.xml 
b/spring-registry/src/site/site.xml
new file mode 100644
index 0000000..654539b
--- /dev/null
+++ b/spring-registry/src/site/site.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  ~ 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 name="Spring Registry Component" >
+
+  <publishDate format="yyyy-MM-dd" position="none" />
+
+  <body>
+    <menu ref="modules" />
+    <menu ref="reports" />
+    <menu ref="ASF" />
+    <breadcrumbs>
+      <item name="Redback Components" href="../index.html" />
+      <item name="Spring Registry" href="index.html" />
+    </breadcrumbs>
+  </body>
+</project>

Reply via email to