Skip to content

Commit

Permalink
#87 : API: support SPI for net.cactusthorn.config.core.loader.Loader
Browse files Browse the repository at this point in the history
  • Loading branch information
Gmugra committed May 14, 2021
1 parent 9ce2f86 commit eb388d3
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 14 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,12 @@ FYI:
- Custom loaders always have the highest priority: last added -> first used.
- Custom loader implementation must be stateless and must have a default(no-argument) `public` constructor.

### SPI
[Service-provider loading facility](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) (introduced in JDK 1.6) can be used to *automatically* add custom loader implementation to the `ConfigFactory`. Add file *META-INF\services\net.cactusthorn.config.core.loader.Loader* in the class path.
e.g.
- [core module](https://github.com/Gmugra/net.cactusthorn.config/blob/main/core/src/main/resources/META-INF/services/net.cactusthorn.config.core.loader.Loader)
- [tests module](https://github.com/Gmugra/net.cactusthorn.config/blob/main/tests/src/main/resources/META-INF/services/net.cactusthorn.config.core.loader.Loader)

### System properties and/or environment variables in sources URIs
Syntax: {*name*}
e.g.
Expand Down
20 changes: 6 additions & 14 deletions core/src/main/java/net/cactusthorn/config/core/ConfigFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
import java.net.URI;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
Expand All @@ -40,13 +42,6 @@
import net.cactusthorn.config.core.loader.LoadStrategy;
import net.cactusthorn.config.core.loader.Loader;
import net.cactusthorn.config.core.loader.Loaders;
import net.cactusthorn.config.core.loader.standard.ClasspathJarManifestLoader;
import net.cactusthorn.config.core.loader.standard.ClasspathPropertiesLoader;
import net.cactusthorn.config.core.loader.standard.ClasspathXMLLoader;
import net.cactusthorn.config.core.loader.standard.SystemEnvLoader;
import net.cactusthorn.config.core.loader.standard.SystemPropertiesLoader;
import net.cactusthorn.config.core.loader.standard.UrlPropertiesLoader;
import net.cactusthorn.config.core.loader.standard.UrlXMLLoader;
import net.cactusthorn.config.core.util.ConfigBuilder;

public final class ConfigFactory {
Expand Down Expand Up @@ -75,13 +70,10 @@ public static final class Builder {
private LoadStrategy loadStrategy = LoadStrategy.MERGE;

private Builder() {
loaders.add(new ClasspathPropertiesLoader());
loaders.add(new SystemPropertiesLoader());
loaders.add(new SystemEnvLoader());
loaders.add(new UrlPropertiesLoader());
loaders.add(new ClasspathXMLLoader());
loaders.add(new UrlXMLLoader());
loaders.add(new ClasspathJarManifestLoader());
ServiceLoader<Loader> serviceLoader = ServiceLoader.load(Loader.class);
for (Iterator<Loader> it = serviceLoader.iterator(); it.hasNext();) {
loaders.add(it.next());
}
}

public Builder addLoader(Loader loader) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
net.cactusthorn.config.core.loader.standard.ClasspathJarManifestLoader
net.cactusthorn.config.core.loader.standard.ClasspathPropertiesLoader
net.cactusthorn.config.core.loader.standard.ClasspathXMLLoader
net.cactusthorn.config.core.loader.standard.SystemEnvLoader
net.cactusthorn.config.core.loader.standard.SystemPropertiesLoader
net.cactusthorn.config.core.loader.standard.UrlPropertiesLoader
net.cactusthorn.config.core.loader.standard.UrlXMLLoader
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2021, Alexei Khatskevich
*
* Licensed under the BSD 3-Clause license.
* You may obtain a copy of the License at
*
* https://github.com/Gmugra/net.cactusthorn.config/blob/main/LICENSE
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.cactusthorn.config.tests.loader;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

import net.cactusthorn.config.core.loader.Loader;

public class SinglePropertyLoader implements Loader {

@Override public boolean accept(URI uri) {
return uri.toString().equals("single:property");
}

@Override public Map<String, String> load(URI uri, ClassLoader classLoader) {
Map<String, String> result = new HashMap<>();
result.put("key", "value");
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
net.cactusthorn.config.tests.loader.SinglePropertyLoader
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2021, Alexei Khatskevich
*
* Licensed under the BSD 3-Clause license.
* You may obtain a copy of the License at
*
* https://github.com/Gmugra/net.cactusthorn.config/blob/main/LICENSE
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.cactusthorn.config.tests.loader;

import static org.junit.jupiter.api.Assertions.*;

import java.net.URI;
import java.util.Map;

import org.junit.jupiter.api.Test;

import net.cactusthorn.config.core.ConfigFactory;
import net.cactusthorn.config.core.loader.ConfigHolder;
import net.cactusthorn.config.core.loader.Loader;

public class SinglePropertyLoaderTest {

private static final Loader LOADER = new SinglePropertyLoader();
private static final ClassLoader CL = SinglePropertyLoaderTest.class.getClassLoader();
private static final URI SPURI = URI.create("single:property");

@Test public void accept() {
assertTrue(LOADER.accept(SPURI));
}

@Test public void notAccept() {
assertFalse(LOADER.accept(URI.create("classpath://a.properties")));
}

@Test public void load() {
Map<String, String> values = LOADER.load(SPURI, CL);
assertEquals("value", values.get("key"));
}

@Test public void loadFactory() {
ConfigHolder holder = ConfigFactory.builder().addSource("single:property").build().configHolder();
assertEquals("value", holder.getString("key"));
}
}

0 comments on commit eb388d3

Please sign in to comment.