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>
