http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFactory.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFactory.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFactory.java deleted file mode 100644 index 3f8a0b1..0000000 --- a/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFactory.java +++ /dev/null @@ -1,287 +0,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. - */ -package org.apache.tamaya.core.properties; - -import java.net.URL; -import java.time.Instant; -import java.util.*; -import java.util.function.BiFunction; -import java.util.function.Predicate; -import java.util.function.Supplier; - -import org.apache.tamaya.PropertySource; - -/** - * Default implementation current the singleton backing bean for the {@link org.apache.tamaya.core.properties.PropertySourceBuilder}. - */ -public final class PropertySourceFactory { - - private static final PropertySource EMPTY_PROPERTYSOURCE = fromMap("<empty>", Collections.emptyMap()); - private static final PropertySource ENV_PROPERTYSOURCE = new EnvironmentPropertySource(); - - - /** - * Singleton constructor. - */ - private PropertySourceFactory(){} - - public static PropertySource fromArgs(String name, String... args) { - if(name==null){ - name ="<CLI> " + Arrays.toString(args); - } - // TODO read the CLI with some better library, e.g. move parsing service to ext. service SPI - Map<String, String> properties = new HashMap<>(); - for (int base = 0; base < args.length; base++) { - if (args[base].startsWith("--")) { - String argKey = args[base].substring(2); - String value = "true"; // flag only - if (base != args.length - 1) { - if (args[base + 1].startsWith("-")) { - base++; - int eqIndex = argKey.indexOf('='); - if (eqIndex > 0) { - value = argKey.substring(eqIndex + 1); - argKey = argKey.substring(0, eqIndex); - } - } else { - value = args[base + 1]; - base += 2; - } - } - properties.put(argKey, value); - } else if (args[base].startsWith("-")) { - String argKey = args[base].substring(1); - String value = "true"; // flag only - if (base != args.length - 1) { - if (args[base + 1].startsWith("-")) { - base++; - int eqIndex = argKey.indexOf('='); - if (eqIndex > 0) { - value = argKey.substring(eqIndex + 1); - argKey = argKey.substring(0, eqIndex); - } - } else { - value = args[base + 1]; - base += 2; - } - } - properties.put(argKey, value); - } - } - return fromMap(name, properties); - } - - public static PropertySource fromPaths(String name, AggregationPolicy aggregationPolicy, List<String> paths) { - if(name==null){ - name ="<Paths> " + paths.toString(); - } - return new PathBasedPropertySource(name, paths, aggregationPolicy); - } - - public static PropertySource fromURLs(String name, AggregationPolicy aggregationPolicy, List<URL> urls) { - if(name==null){ - name ="<URLs> " + urls.toString(); - } - return new URLBasedPropertySource(name, urls, aggregationPolicy); - } - - public static PropertySource fromMap(String name, Map<String, String> map) { - if(name==null){ - name ="<Map> " + map.toString(); - } - return new MapBasedPropertySource(name, map); - } - - public static PropertySource empty(String name) { - if(name==null) { - return EMPTY_PROPERTYSOURCE; - } - return fromMap(name, Collections.emptyMap()); - } - - /** - * Returns a read-only {@link org.apache.tamaya.PropertySource} reflecting the current runtime environment properties. - * - * @return a new read-only {@link org.apache.tamaya.PropertySource} instance based on the current runtime environment properties. - */ - public static PropertySource fromEnvironmentProperties() { - return ENV_PROPERTYSOURCE; - } - - /** - * Creates a new read-only {@link org.apache.tamaya.PropertySource} reflecting the current system properties. - * - * @return a new read-only {@link org.apache.tamaya.PropertySource} instance based on the current system properties. - */ - public static PropertySource fromSystemProperties() { - return new SystemPropertiesPropertySource(); - } - - public static PropertySource freezed(String name, PropertySource source) { - if(name==null){ - name ="<Freezed> source=" + source.toString()+", at="+Instant.now().toString(); - } - return FreezedPropertySource.of(name, source); - } - - /** - * Creates a new {@link org.apache.tamaya.PropertySource} containing all property maps given, hereby using the given AggregationPolicy. - * - * @param policy the AggregationPolicy to be used, not null. - * @param providers the maps to be included, not null. - * @return the aggregated instance containing all given maps. - */ - public static PropertySource aggregate(String name, AggregationPolicy policy, List<PropertySource> providers) { - if(name==null){ - name ="<Aggregate> policy=" + policy.toString()+", providers="+providers.toString(); - } - return new AggregatedPropertySource(name, null, policy, providers); - } - - /** - * Creates a new {@link org.apache.tamaya.PropertySource} that is mutable by adding a map based instance that overrides - * values fromMap the original map. - * @param provider the provider to be made mutable, not null. - * @return the mutable instance. - */ - public static PropertySource mutable(String name, PropertySource provider) { - if(name==null){ - name ="<Mutable> provider="+provider.getName(); - } - PropertySource mutableProvider = fromMap(name,new HashMap<>()); - List<PropertySource> providers = new ArrayList<>(2); - providers.add(provider); - providers.add(mutableProvider); - return new AggregatedPropertySource(name, mutableProvider, AggregationPolicy.OVERRIDE, providers); - } - - /** - * Creates a new {@link org.apache.tamaya.PropertySource} containing only properties that are shared by all given maps, - * hereby later maps in the array override properties fromMap previous instances. - * @param aggregationPolicy the policy to resolve aggregation conflicts. - * @param providers the maps to be included, not null. - * @return the intersecting instance containing all given maps. - */ - public static PropertySource intersected(String name, AggregationPolicy aggregationPolicy, List<PropertySource> providers) { - return new IntersectingPropertySource(name, aggregationPolicy, providers); - } - - /** - * Creates a new {@link org.apache.tamaya.PropertySource} containing only properties fromMap the target instance, that are not contained - * in one current the other maps passed. - * - * @param target the base map, not null. - * @param subtrahendSets the maps to be subtracted, not null. - * @return the intersecting instance containing all given maps. - */ - public static PropertySource subtracted(String name, PropertySource target, List<PropertySource> subtrahendSets) { - return new SubtractingPropertySource(name, target,subtrahendSets); - } - - - /** - * Creates a filtered {@link org.apache.tamaya.PropertySource} (a view) current a given base {@link }PropertyMap}. The filter hereby is - * applied dynamically on access, so also runtime changes current the base map are reflected appropriately. - * - * @param name the base map instance, not null. - * @param filter the filtger to be applied, not null. - * @return the new filtering instance. - */ - public static PropertySource filtered(String name, Predicate<String> filter, PropertySource source) { - if(name==null){ - name ="<Filtered> filter="+filter+", source="+source.getName(); - } - return new FilteredPropertySource(name, source, filter); - } - - /** - * Creates a new contextual {@link org.apache.tamaya.PropertySource}. Contextual maps delegate to different instances current PropertyMap depending - * on the keys returned fromMap the isolationP - * - * @param name the base name instance, not null. - * @param mapSupplier the supplier creating new provider instances - * @param isolationKeySupplier the supplier providing contextual keys based on the current environment. - */ - public static PropertySource contextual(String name, Supplier<PropertySource> mapSupplier, - Supplier<String> isolationKeySupplier) { - if(name==null){ - name ="<Contextual> mapSupplier="+mapSupplier+", isolationKeyProvider="+isolationKeySupplier; - } - return new ContextualPropertySource(name, mapSupplier, isolationKeySupplier); - } - - - /** - * Creates a filtered {@link org.apache.tamaya.PropertySource} (a view) current a given base {@link }PropertyMap}. The filter hereby is - * applied dynamically on access, so also runtime changes current the base map are reflected appropriately. - * - * @param name the base name instance, not null. - * @param source the main map instance, not null. - * @param parentMap the delegated parent map instance, not null. - * @return the new delegating instance. - */ - public static PropertySource delegating(String name, PropertySource source, Map<String, String> parentMap) { - if(name==null){ - name ="<Delegating> source="+source+", delegates="+parentMap; - } - return new DelegatingPropertySource(name, source, parentMap); - } - - /** - * Creates a {@link org.apache.tamaya.PropertySource} where all keys current a current map, - * existing in another map are replaced - * with the ones fromMap the other {@link org.apache.tamaya.PropertySource}. The filter hereby is - * applied dynamically on access, so also runtime changes current the base map are reflected appropriately. - * Keys not existing in the {@code mainMap}, but present in {@code replacementMao} will be hidden. - * - * @param name the base name instance, not null. - * @param source the main source instance, which keys, present in {@code replacementMap} will be replaced - * with the ones - * in {@code replacementMap}, not null. - * @param replacementMap the map instance, that will replace all corresponding entries in {@code mainMap}, not null. - * @return the new delegating instance. - */ - public static PropertySource replacing(String name, PropertySource source, Map<String, String> replacementMap) { - if(name==null){ - name ="<Replacement> source="+source+", replacements="+replacementMap; - } - return new ReplacingPropertySource(name, source, replacementMap); - } - - /** - * Creates a new {@link org.apache.tamaya.PropertySource} given an existing one, and an alternate - * meta-info. - * @param name the new meta-information, not null. - * @param baseProvider the property source, not null. - * @return the new property source.never null. - */ - public static PropertySource build(String name, PropertySource baseProvider) { - return new BuildablePropertySource(name, baseProvider); - } - - /** - * Creates a new filtered {@link org.apache.tamaya.PropertySource} using the given filter. - * @param name the base name instance, not null. - * @param valueFilter the value filter function, null result will remove the given entries. - * @param current the source to be filtered - */ - public static PropertySource filterValues(String name, BiFunction<String, String, String> valueFilter, PropertySource current) { - return new ValueFilteredPropertySource(name, valueFilter, current); - } -}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java index 5fcf895..c081c94 100644 --- a/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/PropertySourceFunctions.java @@ -62,4 +62,57 @@ public final class PropertySourceFunctions { return (c) -> new MappedPropertySource(c, keyMapper); } + + + /** + * Intersetcs the current properties with the given {@link org.apache.tamaya.PropertySource} instance. + * + * @param providers the maps to be intersected, not null. + * @return the builder for chaining. + */ + public UnaryOperator<PropertySource> intersect(PropertySource... providers) { + if (providers.length == 0) { + return this; + } + String name = this.currentName; + if (currentName == null) { + name = "<intersection> -> " + Arrays.toString(providers); + } + return addPropertySources(PropertySourceFactory.intersected(name, aggregationPolicy, Arrays.asList(providers))); + } + + + /** + * Filters the current properties based on the given predicate.. + * + * @param filter the filter to be applied, not null. + * @return the new filtering instance. + */ + public UnaryOperator<PropertySource> filter(Predicate<String> filter) { + String name = this.currentName; + if (currentName == null) { + name = "<filtered> -> " + filter; + } + current = PropertySourceFactory.filtered(name, filter, current); + this.currentName = null; + return this; + } + + + /** + * Replaces all keys in the current provider by the given map. + * + * @param replacementMap the map instance, that will replace all corresponding entries in {@code mainMap}, not null. + * @return the new delegating instance. + */ + public PropertySourceBuilder replace(Map<String, String> replacementMap) { + String name = this.currentName; + if (currentName == null) { + name = "<replacement> -> current=" + current.getName() + " with =" + replacementMap; + } + current = PropertySourceFactory.replacing(name, current, replacementMap); + this.currentName = null; + return this; + } + } http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/ReplacingPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/ReplacingPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/ReplacingPropertySource.java deleted file mode 100644 index 85100e3..0000000 --- a/dormant/core/src/main/java/org/apache/tamaya/core/properties/ReplacingPropertySource.java +++ /dev/null @@ -1,75 +0,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. - */ -package org.apache.tamaya.core.properties; - -import org.apache.tamaya.PropertySource; - -import java.util.*; - -/** - * Implementation for a {@link org.apache.tamaya.PropertySource} that is an aggregate current - * multiple child instances, where all existing key/values in a replacementMap will - * replace values in a main map, if present there. - */ -class ReplacingPropertySource implements PropertySource { - - private PropertySource mainMap; - private Map<String,String> replacingMap; - private String name; - - /** - * Creates a mew instance, with aggregation polilcy - * {@code AggregationPolicy.OVERRIDE}. - * - * @param mainMap The main ConfigMap. - * @param replacingMap The replacing ConfigMap. - */ - public ReplacingPropertySource(String name, PropertySource mainMap, Map<String, String> replacingMap){ - this.replacingMap = Objects.requireNonNull(replacingMap); - this.mainMap = Objects.requireNonNull(mainMap); - this.name = Objects.requireNonNull(name); - } - - @Override - public Map<String,String> getProperties(){ - Map<String,String> result = new HashMap<>(replacingMap); - mainMap.getProperties().entrySet().stream().filter(en -> !replacingMap.containsKey(en.getKey())).forEach(en -> - result.put(en.getKey(), en.getValue())); - return result; - } - - @Override - public String getName(){ - return this.name; - } - - @Override - public Optional<String> get(String key){ - String val = replacingMap.get(key); - if(val == null){ - return mainMap.get(key); - } - return Optional.ofNullable(val); - } - - @Override - public String toString(){ - return super.toString() + "(mainMap=" + mainMap + ", replacingMap=" + replacingMap + ")"; - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/SubtractingPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/SubtractingPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/SubtractingPropertySource.java deleted file mode 100644 index f78ceb9..0000000 --- a/dormant/core/src/main/java/org/apache/tamaya/core/properties/SubtractingPropertySource.java +++ /dev/null @@ -1,56 +0,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. - */ -package org.apache.tamaya.core.properties; - -import org.apache.tamaya.PropertySource; - -import java.util.*; -import java.util.stream.Collectors; - -class SubtractingPropertySource extends AbstractPropertySource { - - private static final long serialVersionUID = 4301042530074932562L; - private PropertySource unit; - private List<PropertySource> subtrahends; - - public SubtractingPropertySource(String name, PropertySource configuration, List<PropertySource> subtrahends){ - super(name); - Objects.requireNonNull(configuration); - this.unit = configuration; - this.subtrahends = new ArrayList<>(subtrahends); - } - - private boolean filter(Map.Entry<String,String> entry){ - for(PropertySource prov: subtrahends){ - if(prov.get(entry.getKey()).isPresent()){ - return false; - } - } - return true; - } - - @Override - public Map<String,String> getProperties(){ - return this.unit.getProperties().entrySet().stream().filter(this::filter).collect(Collectors.toMap( - Map.Entry::getKey, - Map.Entry::getValue - )); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/SystemPropertiesPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/SystemPropertiesPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/SystemPropertiesPropertySource.java index f66c4f8..1964b16 100644 --- a/dormant/core/src/main/java/org/apache/tamaya/core/properties/SystemPropertiesPropertySource.java +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/SystemPropertiesPropertySource.java @@ -21,36 +21,35 @@ package org.apache.tamaya.core.properties; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Properties; -class SystemPropertiesPropertySource extends AbstractPropertySource { +public class SystemPropertiesPropertySource implements PropertySource { private static final long serialVersionUID = -5935940312707001199L; + private int ordinal; + + private String name; + /** * Constructor. */ - protected SystemPropertiesPropertySource() { - super("<System.getProperties()>"); + public SystemPropertiesPropertySource(int ordinal, String name) { + this.ordinal = ordinal; + this.name = Objects.requireNonNull(name); + } @Override public Map<String,String> getProperties(){ - Properties sysProps = System.getProperties(); -// if(sysProps instanceof ConfiguredSystemProperties){ -// sysProps = ((ConfiguredSystemProperties)sysProps).getInitialProperties(); -// } - Map<String,String> props = new HashMap<>(); - for (Map.Entry<Object,Object> en : sysProps.entrySet()) { - props.put(en.getKey().toString(), en.getValue().toString()); - } - return Collections.unmodifiableMap(props); + return Collections.unmodifiableMap(System.getProperties()); } @Override public String toString(){ - return "SystemPropertiesPropertyProvider[" + System.getProperties().size() + " system properties]"; + return "PropertySource[System Properties]"; } } http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/URLBasedPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/URLBasedPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/URLBasedPropertySource.java deleted file mode 100644 index f690ef9..0000000 --- a/dormant/core/src/main/java/org/apache/tamaya/core/properties/URLBasedPropertySource.java +++ /dev/null @@ -1,81 +0,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. - */ -package org.apache.tamaya.core.properties; - -import org.apache.tamaya.ConfigException; -import org.apache.tamaya.core.internal.resources.io.UrlResource; -import org.apache.tamaya.core.resource.Resource; - -import java.net.URL; -import java.util.*; - -/** - * Created by Anatole on 16.10.2014. - */ -final class URLBasedPropertySource extends AbstractPropertySource { - - private static final long serialVersionUID = 648272283683183532L; - private List<URL> resources = new ArrayList<>(); - private Map<String,String> properties = new HashMap<>(); - private AggregationPolicy aggregationPolicy; - - public URLBasedPropertySource(String name, List<URL> resources, AggregationPolicy aggregationPolicy) { - super(name); - this.resources.addAll(Objects.requireNonNull(resources)); - this.aggregationPolicy = Objects.requireNonNull(aggregationPolicy); - init(); - } - - private void init(){ - List<String> sources = new ArrayList<>(); - for(URL url : resources){ - Resource res = new UrlResource(url); - ConfigurationFormat format = ConfigurationFormat.from(res); - if(format != null){ - try{ - Map<String, String> read = format.readConfiguration(res); - sources.add(res.toString()); - read.forEach((k, v) -> { - String newValue = aggregationPolicy.aggregate(k, properties.get(k), v); - if(newValue==null) { - properties.remove(k); - } - else { - properties.put(k, newValue); - } - }); - } - catch(ConfigException e){ - throw e; - } - catch(Exception e){ - e.printStackTrace(); - } - } - } -// MetaInfoBuilder metaInfoBuilder = MetaInfoBuilder.of(getMetaInfo()); -// metaInfo = metaInfoBuilder -// .setSources(sources.toString()).build(); - } - - @Override - public Map<String, String> getProperties() { - return properties; - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/ValueFilteredPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/ValueFilteredPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/ValueFilteredPropertySource.java deleted file mode 100644 index db17d21..0000000 --- a/dormant/core/src/main/java/org/apache/tamaya/core/properties/ValueFilteredPropertySource.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.apache.tamaya.core.properties; - -import org.apache.tamaya.PropertySource; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Optional; -import java.util.function.BiFunction; - -/** - * Property source which filters any key/values dynamically. - */ -class ValueFilteredPropertySource implements PropertySource{ - - private String name; - private BiFunction<String, String, String> valueFilter; - private PropertySource source; - - public ValueFilteredPropertySource(String name, BiFunction<String, String, String> valueFilter, PropertySource current) { - this.name = Optional.ofNullable(name).orElse("<valueFiltered> -> name="+current.getName()+", valueFilter="+valueFilter.toString()); - } - - @Override - public String getName() { - return name; - } - - @Override - public Optional<String> get(String key) { - String value = this.source.get(key).orElse(null); - value = valueFilter.apply(key, value); - return Optional.ofNullable(value); - } - - @Override - public Map<String, String> getProperties() { - Map<String, String> map = new HashMap<>(source.getProperties()); - map.replaceAll(valueFilter); - return map; - } - - @Override - public String toString() { - return "ValueFilteredPropertySource{" + - "source=" + source.getName() + - ", name='" + name + '\'' + - ", valueFilter=" + valueFilter + - '}'; - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/PropertySourceFactory.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/PropertySourceFactory.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/PropertySourceFactory.java new file mode 100644 index 0000000..b7d985c --- /dev/null +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/PropertySourceFactory.java @@ -0,0 +1,279 @@ +/* + * 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. + */ +package org.apache.tamaya.core.properties; + +import java.net.URL; +import java.time.Instant; +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import org.apache.tamaya.PropertySource; + +/** + * Default implementation current the singleton backing bean for the {@link org.apache.tamaya.core.properties.PropertySourceBuilder}. + */ +public final class PropertySourceFactory { + + private static final PropertySource ENV_PROPERTYSOURCE = new EnvironmentPropertySource(); + + + /** + * Singleton constructor. + */ + private PropertySourceFactory(){} + + public static PropertySource fromArgs(int ordinal, String name, String... args) { + if(name==null){ + name ="<CLI> " + Arrays.toString(args); + } + //X TODO read the CLI with some better library, e.g. move parsing service to ext. service SPI + Map<String, String> properties = new HashMap<>(); + for (int base = 0; base < args.length; base++) { + if (args[base].startsWith("--")) { + String argKey = args[base].substring(2); + String value = "true"; // flag only + if (base != args.length - 1) { + if (args[base + 1].startsWith("-")) { + base++; + int eqIndex = argKey.indexOf('='); + if (eqIndex > 0) { + value = argKey.substring(eqIndex + 1); + argKey = argKey.substring(0, eqIndex); + } + } else { + value = args[base + 1]; + base += 2; + } + } + properties.put(argKey, value); + } else if (args[base].startsWith("-")) { + String argKey = args[base].substring(1); + String value = "true"; // flag only + if (base != args.length - 1) { + if (args[base + 1].startsWith("-")) { + base++; + int eqIndex = argKey.indexOf('='); + if (eqIndex > 0) { + value = argKey.substring(eqIndex + 1); + argKey = argKey.substring(0, eqIndex); + } + } else { + value = args[base + 1]; + base += 2; + } + } + properties.put(argKey, value); + } + } + return fromMap(ordinal, name, properties); + } + + public static Collection<PropertySource> fromPaths(int ordinal, String name, List<String> paths) { + if(name==null){ + name ="<Paths> " + paths.toString(); + } + return new PathBasedPropertySource(ordinal, name, paths); + } + + public static Collection<PropertySource> fromURLs(int ordinal, String name, List<URL> urls) { + if(name==null){ + name ="<URLs> " + urls.toString(); + } + return new URLBasedPropertySource(ordinal, name, urls); + } + + public static PropertySource fromMap(int ordinal, String name, Map<String, String> map) { + if(name==null){ + name ="<Map> " + map.toString(); + } + return new MapBasedPropertySource(name, map); + } + + /** + * Returns a read-only {@link org.apache.tamaya.PropertySource} reflecting the current runtime environment properties. + * + * @return a new read-only {@link org.apache.tamaya.PropertySource} instance based on the current runtime environment properties. + */ + public static PropertySource fromEnvironmentProperties() { + return ENV_PROPERTYSOURCE; + } + + /** + * Creates a new read-only {@link org.apache.tamaya.PropertySource} reflecting the current system properties. + * + * @return a new read-only {@link org.apache.tamaya.PropertySource} instance based on the current system properties. + */ + public static PropertySource fromSystemProperties() { + return new SystemPropertiesPropertySource(); + } + + public static PropertySource freezed(String name, PropertySource source) { + if(name==null){ + name ="<Freezed> source=" + source.toString()+", at="+Instant.now().toString(); + } + return FreezedPropertySource.of(name, source); + } + + /** + * Creates a new {@link org.apache.tamaya.PropertySource} containing all property maps given, hereby using the given AggregationPolicy. + * + * @param policy the AggregationPolicy to be used, not null. + * @param providers the maps to be included, not null. + * @return the aggregated instance containing all given maps. + */ + public static PropertySource aggregate(String name, AggregationPolicy policy, List<PropertySource> providers) { + if(name==null){ + name ="<Aggregate> policy=" + policy.toString()+", providers="+providers.toString(); + } + return new AggregatedPropertySource(name, null, policy, providers); + } + + /** + * Creates a new {@link org.apache.tamaya.PropertySource} that is mutable by adding a map based instance that overrides + * values fromMap the original map. + * @param provider the provider to be made mutable, not null. + * @return the mutable instance. + */ + public static PropertySource mutable(String name, PropertySource provider) { + if(name==null){ + name ="<Mutable> provider="+provider.getName(); + } + PropertySource mutableProvider = fromMap(name,new HashMap<>()); + List<PropertySource> providers = new ArrayList<>(2); + providers.add(provider); + providers.add(mutableProvider); + return new AggregatedPropertySource(name, mutableProvider, AggregationPolicy.OVERRIDE, providers); + } + + /** + * Creates a new {@link org.apache.tamaya.PropertySource} containing only properties that are shared by all given maps, + * hereby later maps in the array override properties fromMap previous instances. + * @param aggregationPolicy the policy to resolve aggregation conflicts. + * @param providers the maps to be included, not null. + * @return the intersecting instance containing all given maps. + */ + public static PropertySource intersected(String name, AggregationPolicy aggregationPolicy, List<PropertySource> providers) { + return new IntersectingPropertySource(name, aggregationPolicy, providers); + } + + /** + * Creates a new {@link org.apache.tamaya.PropertySource} containing only properties fromMap the target instance, that are not contained + * in one current the other maps passed. + * + * @param target the base map, not null. + * @param subtrahendSets the maps to be subtracted, not null. + * @return the intersecting instance containing all given maps. + */ + public static PropertySource subtracted(String name, PropertySource target, List<PropertySource> subtrahendSets) { + return new SubtractingPropertySource(name, target,subtrahendSets); + } + + + /** + * Creates a filtered {@link org.apache.tamaya.PropertySource} (a view) current a given base {@link }PropertyMap}. The filter hereby is + * applied dynamically on access, so also runtime changes current the base map are reflected appropriately. + * + * @param name the base map instance, not null. + * @param filter the filtger to be applied, not null. + * @return the new filtering instance. + */ + public static PropertySource filtered(String name, Predicate<String> filter, PropertySource source) { + if(name==null){ + name ="<Filtered> filter="+filter+", source="+source.getName(); + } + return new FilteredPropertySource(name, source, filter); + } + + /** + * Creates a new contextual {@link org.apache.tamaya.PropertySource}. Contextual maps delegate to different instances current PropertyMap depending + * on the keys returned fromMap the isolationP + * + * @param name the base name instance, not null. + * @param mapSupplier the supplier creating new provider instances + * @param isolationKeySupplier the supplier providing contextual keys based on the current environment. + */ + public static PropertySource contextual(String name, Supplier<PropertySource> mapSupplier, + Supplier<String> isolationKeySupplier) { + if(name==null){ + name ="<Contextual> mapSupplier="+mapSupplier+", isolationKeyProvider="+isolationKeySupplier; + } + return new ContextualPropertySource(name, mapSupplier, isolationKeySupplier); + } + + + /** + * Creates a filtered {@link org.apache.tamaya.PropertySource} (a view) current a given base {@link }PropertyMap}. The filter hereby is + * applied dynamically on access, so also runtime changes current the base map are reflected appropriately. + * + * @param name the base name instance, not null. + * @param source the main map instance, not null. + * @param parentMap the delegated parent map instance, not null. + * @return the new delegating instance. + */ + public static PropertySource delegating(String name, PropertySource source, Map<String, String> parentMap) { + if(name==null){ + name ="<Delegating> source="+source+", delegates="+parentMap; + } + return new DelegatingPropertySource(name, source, parentMap); + } + + /** + * Creates a {@link org.apache.tamaya.PropertySource} where all keys current a current map, + * existing in another map are replaced + * with the ones fromMap the other {@link org.apache.tamaya.PropertySource}. The filter hereby is + * applied dynamically on access, so also runtime changes current the base map are reflected appropriately. + * Keys not existing in the {@code mainMap}, but present in {@code replacementMao} will be hidden. + * + * @param name the base name instance, not null. + * @param source the main source instance, which keys, present in {@code replacementMap} will be replaced + * with the ones + * in {@code replacementMap}, not null. + * @param replacementMap the map instance, that will replace all corresponding entries in {@code mainMap}, not null. + * @return the new delegating instance. + */ + public static PropertySource replacing(String name, PropertySource source, Map<String, String> replacementMap) { + if(name==null){ + name ="<Replacement> source="+source+", replacements="+replacementMap; + } + return new ReplacingPropertySource(name, source, replacementMap); + } + + /** + * Creates a new {@link org.apache.tamaya.PropertySource} given an existing one, and an alternate + * meta-info. + * @param name the new meta-information, not null. + * @param baseProvider the property source, not null. + * @return the new property source.never null. + */ + public static PropertySource build(String name, PropertySource baseProvider) { + return new BuildablePropertySource(name, baseProvider); + } + + /** + * Creates a new filtered {@link org.apache.tamaya.PropertySource} using the given filter. + * @param name the base name instance, not null. + * @param valueFilter the value filter function, null result will remove the given entries. + * @param current the source to be filtered + */ + public static PropertySource filterValues(String name, BiFunction<String, String, String> valueFilter, PropertySource current) { + return new ValueFilteredPropertySource(name, valueFilter, current); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/PropertySourcesBuilder.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/PropertySourcesBuilder.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/PropertySourcesBuilder.java new file mode 100644 index 0000000..712e3f6 --- /dev/null +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/PropertySourcesBuilder.java @@ -0,0 +1,367 @@ +/* +* 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. +*/ +package org.apache.tamaya.core.properties.factories; + +import java.lang.IllegalArgumentException; +import java.net.URL; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.apache.tamaya.core.properties.AggregationPolicy; +import org.apache.tamaya.core.properties.PropertySourceFactory; +import org.apache.tamaya.spi.PropertySource; + +/** + * Builder for assembling non trivial property providers. + */ +public final class PropertySourcesBuilder { + + /** + * Name used for the final result. + */ + private Map<String, PropertySource> propertySources = new HashMap<>(); + + /** + * The current aggregation policy used, when aggregating providers. + */ + private AggregationPolicy aggregationPolicy = AggregationPolicy.OVERRIDE; + + /** + * The current ordinal used for creating property source instances. + */ + private int currentOrdinal; + /** The increment added to {@code currentOrdinal}, when new property sources are added and no + * explcit ordinal is used. */ + private int ordinalIncrement; + + /** The name to be used for the next PropertySource constructed, or null, for creating a defau,t name. */ + private String currentName; + + /** + * Private singleton constructor. + */ + private PropertySourcesBuilder(int ordinal, int ordinalIncrement) { + this.ordinalIncrement = ordinalIncrement; + this.currentOrdinal = ordinal; + } + + /** + * Creates a new builder instance. + * + * @param ordinal The initial starting ordinal to be used when new property sources are created and added. + * @param ordinalIncrement the ordinal increment to be added when no new property sources are created and added. + * @return a new builder instance, never null. + */ + public static PropertySourcesBuilder of(int ordinal, int ordinalIncrement) { + return new PropertySourcesBuilder(ordinal, ordinalIncrement); + } + + /** + * Creates a new builder instance. + * + * @param ordinal The initial starting ordinal to be used when new property sources are created and added. + * The default ordinal increment used is 10. + * @return a new builder instance, never null. + */ + public static PropertySourcesBuilder of(int ordinal) { + return new PropertySourceBuilder(ordinal, 10); + } + + + /** + * Creates a new builder instance, starting with ordinal of 1 and an ordinal increment of 10. + * + * @param name the provider name, not null. + * @return a new builder instance, never null. + */ + public static PropertySourcesBuilder of() { + return new PropertySourceBuilder(1, 10); + } + + /** + * Sets the current ordinal used, when additional property sets are added. The ordinal will normally implicitly + * incresed for each property set by {@code ordinalIncrement}. If the ordinal is passed explcitly to a method + * all created sources will have the same ordinal. + * + * @param ordinal the ordinal to be used. + * @return the builder for chaining. + */ + public PropertySourcesBuilder withOrdinal(int ordinal) { + this.currentOrdinal = ordinal; + return this; + } + + /** + * Sets the current name used, when the next property sets is added. If set to null a default name will be + * constructed. + * + * @param name the name to be used for the next property set created, or null. + * @return the builder for chaining. + */ + public PropertySourcesBuilder withName(String name) { + this.currentName = name; + return this; + } + + /** + * Aggregates the given {@code sources} (at least 2) into a new + * {@link PropertySource} and adds it with the given current ordinal and name. + * + * @param aggregationPolicy the aggregation policy, not null. + * @param sources the property sources to be aggregated. + * @return the builder for chaining. + */ + public PropertySourcesBuilder addAggregation(AggregationPolicy aggregationPolicy, PropertySource... sources) { + this.aggregationPolicy = Objects.requireNonNull(aggregationPolicy); + String name = this.currentName; + if(name==null){ + name = "Aggregate["+ Arrays.stream(sources).map(s -> s.getName()).collect( + () -> "", + (s,o) -> s + ',' + o, + (s1, s2) -> s1 + ',' + s2) +"]" + } + ProperttySource source = new new AggregatedPropertySource(currentOrdinal, name, aggregationPolicy, sources); + this.propertySources.put(source.getName(), source); + this.currentOrdinal += ordinalIncrement; + return this; + } + + /** + * Adds the given providers with the current active {@link AggregationPolicy}. By + * default {@link AggregationPolicy#OVERRIDE} is used. + * + * @param propertySources the property sources to be added, not null. + * @return the builder for chaining. + * @see #withAggregationPolicy(AggregationPolicy) + */ + public PropertySourcesBuilder addPropertySources(PropertySource... propertySources) { + if (propertySources.length == 0) { + return this; + } + return addPropertySources(Arrays.asList(propertySources)); + } + + /** + * Adds the given providers with the current active {@link AggregationPolicy}. By + * default {@link AggregationPolicy#OVERRIDE} is used. + * + * @param providers providers to be added, not null. + * @return the builder for chaining. + * @see #withAggregationPolicy(AggregationPolicy) + */ + public PropertySourcesBuilder addPropertySources(List<PropertySource> providers) { + if (providers.isEmpty()) { + return this; + } + for (PropertySource src : providers) { + PropertySource current = this.propertySources.get(src.getName()); + if (src != null) { + throw new IllegalArgumentException("PropertySource with that name is already existing: " + src.getName()) + } + } + for (PropertySource src : providers) { + this.propertySources.put(sec.getName(), src); + } + return this; + } + + /** + * Creates a new {@link PropertySource} using the given command line arguments and adds it + * using the current aggregation policy in place. + * + * @param args the command line arguments, not null. + * @return the builder for chaining. + */ + public PropertySourcesBuilder addArgs(String... args) { + if (args.length == 0) { + return this; + } + String name = this.currentName; + if (currentName == null) { + name = "CLI-Args"; + } + PropertySource argProvider = PropertySourceFactory.fromArgs(currentOrdinal, name, args); + currentOrdinal+=ordinalIncrement; + return addPropertySources(argProvider); + } + + /** + * Creates a new read-only {@link PropertySource} by reading the according path resources. The effective resources read + * hereby are determined by the {@code PathResolverService} configured into the {@code Bootstrap} SPI. + * Properties read are aggregated using the current aggregation policy active. + * + * @param paths the paths to be resolved by the {@code PathResolverService} , not null. + * @return the builder for chaining. + */ + public PropertySourcesBuilder addPaths(String... paths) { + if (paths.length == 0) { + return this; + } + return addPaths(Arrays.asList(paths)); + } + + + /** + * Creates a new read-only {@link PropertySource} by reading the according path resources. The effective resources read + * hereby are determined by the {@code PathResolverService} configured into the {@code Bootstrap} SPI. + * Properties read are aggregated using the current aggregation policy active. + * + * @param paths the paths to be resolved by the {@code PathResolverService} , not null. + * @return the builder for chaining. + */ + public PropertySourcesBuilder addPaths(List<String> paths) { + if (paths.isEmpty()) { + return this; + } + String name = this.currentName; + if (currentName == null) { + name = "paths=" + paths.toString(); + } + addPropertySources(PropertySourceFactory.fromPaths(currentOrdinal, name, paths)); + } + + /** + * Creates a new read-only {@link PropertySource} by reading the according URL resources. + * Properties read are aggregated using the current aggregation policy active. + * + * @param urls the urls to be read, not null. + * @return the builder for chaining. + */ + public PropertySourcesBuilder addURLs(URL... urls) { + if (urls.length == 0) { + return this; + } + return addURLs(Arrays.asList(urls)); + } + + /** + * Creates a new read-only {@link PropertySource} by reading the according URL resources. + * Properties read are aggregated using the current aggregation policy active. + * + * @param urls the urls to be read, not null. + * @return the builder for chaining. + */ + public PropertySourcesBuilder addURLs(List<URL> urls) { + if (urls.isEmpty()) { + return this; + } + String name = this.currentName; + if (currentName == null) { + name = "URL: =" + urls; + } + return addPropertySources(PropertySourceFactory.fromURLs(name, this.aggregationPolicy, urls)); + } + + + /** + * Creates a new read-only {@link PropertySource} based on the given map. + * Properties read are aggregated using the current aggregation policy active. + * + * @param map the map to be added, not null. + * @return the builder for chaining. + */ + public PropertySourcesBuilder addMap(Map<String, String> map) { + if (map.isEmpty()) { + return this; + } + String name = this.currentName; + if (currentName == null) { + name = "Map; + } + return addPropertySources(PropertySourceFactory.fromMap(currentOrdinal, name, map)); + } + + + /** + * Add the current environment properties. Aggregation is based on the current {@link AggregationPolicy} acvtive. + * + * @return the builder for chaining. + */ + public PropertySourcesBuilder addEnvironmentProperties() { + String name = this.currentName; + if (currentName == null) { + name = "Environment-Properties"; + } + return addPropertySources(PropertySourceFactory.fromEnvironmentProperties()); + } + + /** + * Add the current system properties. Aggregation is based on the current {@link AggregationPolicy} acvtive. + * + * @return the builder for chaining. + */ + public PropertySourcesBuilder addSystemProperties() { + String name = this.currentName; + if (currentName == null) { + name = "System-Properties"; + } + return addPropertySources(PropertySourceFactory.fromSystemProperties()); + } + + +// +// /** +// * Filters the current {@link org.apache.tamaya.PropertySource} with the given valueFilter. +// * +// * @param valueFilter the value filter, not null. +// * @return the (dynamically) filtered source instance, never null. +// */ +// public PropertySourceBuilder filterValues(BiFunction<String, String, String> valueFilter) { +// String name = this.currentName; +// if (currentName == null) { +// name = "<filteredValues> -> " + valueFilter; +// } +// this.current = PropertySourceFactory.filterValues(name, valueFilter, this.current); +// return this; +// } + + + /** + * Subtracts with the given {@link org.apache.tamaya.PropertySource} instance from the current properties. + * + * @param providers the maps to be subtracted, not null. + * @return the builder for chaining. + */ + public PropertySourcesBuilder subtract(PropertySource... providers) { + if (providers.length == 0) { + return this; + } + String name = this.currentName; + if (currentName == null) { + name = "<subtraction> -> " + Arrays.toString(providers); + } + current = PropertySourceFactory.subtracted(name, current, Arrays.asList(providers)); + return this; + } + + + /** + * Build a new property provider based on the input. + * + * @return a new property provider, or null. + */ + public Collection<PropertySource> build() { + return this.propertySources.values(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/ResourcePropertySourceProvider.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/ResourcePropertySourceProvider.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/ResourcePropertySourceProvider.java new file mode 100644 index 0000000..6dae705 --- /dev/null +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/factories/ResourcePropertySourceProvider.java @@ -0,0 +1,70 @@ +/* + * 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. + */ +package org.apache.tamaya.core.properties; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.Override; +import java.lang.String; +import java.net.URL; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class ResourcePropertySourceProvider implements PropertySourceProvider { + + private static final Logger LOG = Logger.getLogger(ResourcePropertySourceProvider.class.getName()); + + private int baseOrdinal; + + private Collection<PropertySource> propertySources; + + private Resource resource; + + public ResourcePropertySourceProvider(int baseOrdinal, String baseName, Resource resource) { + this.resource = Objects.requireNonNull(resource); + this.baseOrdinal = baseOrdinal; + List<ConfigFormat> formats = ConfigFormat.getFormats(resource); + for(ConfigFormat format: formats){ + try{ + propertySources = format.readConfiguration(baseOrdinal, baseName, resource); + } + catch(Exception e){ + LOG.info(() -> "Format was not matching: " + format.getFormatName() + " for resource: " + resource.getName()); + } + } + } + + public Resource getResource(){ + return this.resource; + } + + + @Override + public String toString() { + return "ResourcePropertySourceProvider{" + + "resource=" + resource + + ", propertySources=" + propertySources + + '}'; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/AggregatedPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/AggregatedPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/AggregatedPropertySource.java new file mode 100644 index 0000000..e62a9a6 --- /dev/null +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/AggregatedPropertySource.java @@ -0,0 +1,97 @@ +/* + * 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. + */ +package org.apache.tamaya.core.properties.filtered; + +import org.apache.tamaya.core.properties.AggregationPolicy; +import org.apache.tamaya.spi.PropertySource; + +import java.util.*; + +/** + * Implementation for a {@link org.apache.tamaya.spi.PropertySource} that is an aggregate current + * multiple child instances. + */ +public class AggregatedPropertySource implements PropertySource { + + private PropertySource baseSource; + private PropertySource aggregatedSource; + private String name; + private int ordinal; + private AggregationPolicy aggregationPolicy; + + /** + * Creates a mew instance, with aggregation polilcy + * {@code AggregationPolicy.OVERRIDE}. + * + * @param ordinal the ordinal + * @param name The name to be used, not null. + * @param aggregationPolicy the {@link org.apache.tamaya.core.properties.AggregationPolicy} to be applied + * @param baseSource the base property source, not null + * @param aggregatedSource the aggregatesd property source, not null + */ + public AggregatedPropertySource(int ordinal, String name, AggregationPolicy aggregationPolicy, + PropertySource baseSource, PropertySource aggregatedSource) { + this.aggregationPolicy = Objects.requireNonNull(aggregationPolicy); + this.name = Objects.requireNonNull(name); + this.ordinal = ordinal; + this.baseSource = Objects.requireNonNull(baseSource); + this.aggregatedSource = Objects.requireNonNull(aggregatedSource); + } + + @Override + public int getOrdinal() { + return this.ordinal; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public Map<String, String> getProperties() { + Map<String, String> result = new HashMap<>(); + Set<String> keySet = new HashSet<>(this.baseSource.getProperties().keySet()); + keySet.addAll(this.aggregatedSource.getProperties().keySet()); + for (String key : keySet) { + String value = this.aggregationPolicy.aggregate( + key, + baseSource.get(key).orElse(null), + aggregatedSource.get(key).orElse(null)); + if (value != null) { + result.put(key, value); + } + } + return result; + } + + @Override + public Optional<String> get(String key) { + String value1 = this.baseSource.get(key).orElse(null); + String value2 = this.aggregatedSource.get(key).orElse(null); + return Optional.ofNullable(aggregationPolicy.aggregate(key, value1, value2)); + } + + @Override + public String toString() { + return "Aggregate(baseSource=" + baseSource + + ", aggregatedSource=" + aggregatedSource.getName() + + ", aggregationPolicy=" + aggregationPolicy + ")"; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/FilteredPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/FilteredPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/FilteredPropertySource.java new file mode 100644 index 0000000..ecf2950 --- /dev/null +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/FilteredPropertySource.java @@ -0,0 +1,68 @@ +/* + * 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. + */ +package org.apache.tamaya.core.properties; + +import org.apache.tamaya.PropertySource; + +import java.lang.Override; +import java.lang.String; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Predicate; + +class FilteredPropertySource implements PropertySource { + + private PropertySource baseSource; + private Predicate<String> filter; + + public FilteredPropertySource(PropertySource baseSource, Predicate<String> filter){ + this.baseSource = Objects.requireNonNull(baseSource); + this.filter = Objects.requireNonNull(filter); + } + + @Override + public int ordinal(){ + return baseSource.ordinal(); + } + + @Override + public String getName(){ + return baseSource + "(filtered)"; + } + + @Override + public Map<String,String> getProperties(){ + final Map<String,String> result = new HashMap<>(); + this.unit.getProperties().entrySet().forEach(e -> { + if(filter.test(e.getKey())){ + result.put(e.getKey(), e.getValue()); + } + }); + return result; + } + + @Override + public String toString() { + return "FilteredPropertySource{" + + "baseSource=" + baseSource + + ", filter=" + filter + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/IntersectingPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/IntersectingPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/IntersectingPropertySource.java new file mode 100644 index 0000000..e441985 --- /dev/null +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/IntersectingPropertySource.java @@ -0,0 +1,55 @@ +/* + * 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. + */ +package org.apache.tamaya.core.properties.filtered; + +import org.apache.tamaya.*; +import org.apache.tamaya.core.properties.filtered.AggregatedPropertySource; +import org.apache.tamaya.spi.PropertySource; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Provider implementation that combines multiple other config by intersecting + * the key/values common to one source. + */ +class IntersectingPropertySource extends AggregatedPropertySource { + + + /** + * Creates a mew instance, with aggregation polilcy + * {@code AggregationPolicy.OVERRIDE}. + * + * @param ordinal the ordinal + * @param name The name to be used, not null. + * @param baseSource the base property source, not null + * @param aggregatedSource the aggregatesd property source, not null + */ + public IntersectingPropertySource(int ordinal, String name, + PropertySource baseSource, PropertySource aggregatedSource) { + super(ordinal, name, (k,v1,v2) -> { + if(v1!=null && v2!=null && v1.equals(v2)){ + return v1; + } + return null; + }, baseSource, aggregatedSource); + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/MappedPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/MappedPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/MappedPropertySource.java new file mode 100644 index 0000000..0db716d --- /dev/null +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/MappedPropertySource.java @@ -0,0 +1,67 @@ +package org.apache.tamaya.core.properties.filtered; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.UnaryOperator; + +import org.apache.tamaya.PropertySource; +import org.apache.tamaya.spi.PropertySource; + +/** + * PropertySource implementation that maps certain parts (defined by an {@code UnaryOperator<String>}) to alternate areas. + */ +class MappedPropertySource implements PropertySource { + + private static final long serialVersionUID = 8690637705511432083L; + + /** The mapping operator. */ + private UnaryOperator<String> keyMapper; + /** The base configuration. */ + private PropertySource propertySource; + + /** + * Creates a new instance. + * @param config the base configuration, not null + * @param keyMapper The mapping operator, not null + */ + public MappedPropertySource(PropertySource config, UnaryOperator<String> keyMapper) { + this.propertySource = Objects.requireNonNull(config); + this.keyMapper = Objects.requireNonNull(keyMapper); + } + + @Override + public int getOrdinal(){ + return this.propertySource.getOrdinal(); + } + + @Override + public String getName(){ + return this.propertySource.getName()+"[mapped]"; + } + + @Override + public Map<String, String> getProperties() { + Map<String, String> result = new HashMap<>(); + Map<String, String> map = this.propertySource.getProperties(); + map.forEach((k,v) -> { + String targetKey = keyMapper.apply(k); + if(targetKey!=null){ + result.put(targetKey, v); + } + }); + return result; + } + + @Override + public Optional<String> get(String key){ + return Optional.of(getProperties().get(key)); + } + + @Override + public boolean isEmpty() { + return this.propertySource.isEmpty(); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/ValueFilteredPropertySource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/ValueFilteredPropertySource.java b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/ValueFilteredPropertySource.java new file mode 100644 index 0000000..8eb0f60 --- /dev/null +++ b/dormant/core/src/main/java/org/apache/tamaya/core/properties/filtered/ValueFilteredPropertySource.java @@ -0,0 +1,55 @@ +package org.apache.tamaya.core.properties.filtered; + +import org.apache.tamaya.spi.PropertySource; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.BiFunction; + +/** + * Property source which filters any key/values dynamically. + */ +class ValueFilteredPropertySource implements PropertySource{ + + private String name; + private BiFunction<String, String, String> valueFilter; + private PropertySource source; + + public ValueFilteredPropertySource(String name, BiFunction<String, String, String> valueFilter, PropertySource current) { + this.name = Optional.ofNullable(name).orElse("<valueFiltered> -> name="+current.getName()+", valueFilter="+valueFilter.toString()); + } + + @Override + public int getOrdinal() { + return source.getOrdinal(); + } + + @Override + public String getName() { + return name; + } + + @Override + public Optional<String> get(String key) { + String value = this.source.get(key).orElse(null); + value = valueFilter.apply(key, value); + return Optional.ofNullable(value); + } + + @Override + public Map<String, String> getProperties() { + Map<String, String> map = new HashMap<>(source.getProperties()); + map.replaceAll(valueFilter); + return map; + } + + @Override + public String toString() { + return "ValueFilteredPropertySource{" + + "source=" + source.getName() + + ", name='" + name + '\'' + + ", valueFilter=" + valueFilter + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/resource/InputStreamSource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/resource/InputStreamSource.java b/dormant/core/src/main/java/org/apache/tamaya/core/resource/InputStreamSource.java deleted file mode 100644 index 102337d..0000000 --- a/dormant/core/src/main/java/org/apache/tamaya/core/resource/InputStreamSource.java +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Copyright 2002-2012 the original author or authors. -* -* 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. -*/ - -package org.apache.tamaya.core.resource; - -import java.io.IOException; -import java.io.InputStream; - -/** -* Simple interface for objects that are sources for an {@link InputStream}. -* -* <p>This is the base interface for Spring's more extensive {@link Resource} interface. -* -* <p>For single-use streams, {@link org.apache.tamaya.core.internal.resources.io.InputStreamResource} can be used for any -* given {@code InputStream}. Spring's {@code ByteArrayResource} or any -* file-based {@code Resource} implementation can be used as a concrete -* instance, allowing one to read the underlying content stream multiple times. -* This makes this interface useful as an abstract content source for mail -* attachments, for example. -* -* @author Juergen Hoeller -* @since 20.01.2004 -* @see java.io.InputStream -* @see Resource -* @see org.apache.tamaya.core.internal.resources.io.InputStreamResource -*/ -@FunctionalInterface -public interface InputStreamSource { - - /** - * Return an {@link InputStream}. - * <p>It is expected that each call creates a <i>fresh</i> stream. - * <p>This requirement is particularly important when you consider an API such - * as JavaMail, which needs to be able to read the stream multiple times when - * creating mail attachments. For such a use case, it is <i>required</i> - * that each {@code getInputStreamSupplier()} call returns a fresh stream. - * @return the input stream for the underlying resource (must not be {@code null}) - * @throws IOException if the stream could not be opened - */ - InputStream getInputStream() throws IOException; - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/resource/Resource.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/resource/Resource.java b/dormant/core/src/main/java/org/apache/tamaya/core/resource/Resource.java deleted file mode 100644 index ca76974..0000000 --- a/dormant/core/src/main/java/org/apache/tamaya/core/resource/Resource.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * 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. - */ -package org.apache.tamaya.core.resource; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URL; - -/** - * Interface for a resource descriptor that abstracts from the actual - * type current underlying resource, such as a file or class path resource. - * - * <p>An InputStream can be opened for every resource if it exists in - * physical form, but a URL or File handle can just be returned for - * certain resources. The actual behavior is implementation-specific. - * - * @author Juergen Hoeller - * @since 28.12.2003 - * @see #getInputStream() - * @see #getURL() - * @see #getURI() - * @see #getFile() - */ -public interface Resource extends InputStreamSource { - - /** - * Return whether this resource actually exists in physical form. - * <p>This method performs a definitive existence check, whereas the - * existence current a {@code Resource} handle only guarantees a - * valid descriptor handle. - */ - boolean exists(); - - /** - * Return whether the contents current this resource can be read, - * e.g. via {@link #getInputStream()} or {@link #getFile()}. - * <p>Will be {@code true} for typical resource descriptors; - * note that actual content reading may still fail when attempted. - * However, a keys current {@code false} is a definitive indication - * that the resource content cannot be read. - * @see #getInputStream() - */ - boolean isReadable(); - - /** - * Return whether this resource represents a handle with an open - * stream. If true, the InputStream cannot be read multiple times, - * and must be read and closed to avoid resource leaks. - * <p>Will be {@code false} for typical resource descriptors. - */ - boolean isOpen(); - - /** - * Return a URL handle for this resource. - * @throws IOException if the resource cannot be resolved as URL, - * i.e. if the resource is not available as descriptor - */ - URL getURL() throws IOException; - - /** - * Return a URI handle for this resource. - * @throws IOException if the resource cannot be resolved as URI, - * i.e. if the resource is not available as descriptor - */ - URI getURI() throws IOException; - - /** - * Return a File handle for this resource. - * @throws IOException if the resource cannot be resolved as absolute - * file path, i.e. if the resource is not available in a file system - */ - File getFile() throws IOException; - - /** - * Determine the content length for this resource. - * @throws IOException if the resource cannot be resolved - * (in the file system or as some other known physical resource type) - */ - long contentLength() throws IOException; - - /** - * Determine the last-modified timestamp for this resource. - * @throws IOException if the resource cannot be resolved - * (in the file system or as some other known physical resource type) - */ - long lastModified() throws IOException; - - /** - * Create a resource relative to this resource. - * @param relativePath the relative path (relative to this resource) - * @return the resource handle for the relative resource - * @throws IOException if the relative resource cannot be determined - */ - Resource createRelative(String relativePath) throws IOException; - - /** - * Determine a filename for this resource, i.e. typically the last - * part current the path: for example, "myfile.txt". - * <p>Returns {@code null} if this type current resource does not - * have a filename. - */ - String getFilename(); - - /** - * Get a description of the resource. - * @return the description. - */ - String getDescription(); - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/dormant/core/src/main/java/org/apache/tamaya/core/resource/ResourceLoader.java ---------------------------------------------------------------------- diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/resource/ResourceLoader.java b/dormant/core/src/main/java/org/apache/tamaya/core/resource/ResourceLoader.java deleted file mode 100644 index 1c55e55..0000000 --- a/dormant/core/src/main/java/org/apache/tamaya/core/resource/ResourceLoader.java +++ /dev/null @@ -1,84 +0,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. - */ -package org.apache.tamaya.core.resource; - -import java.util.Collection; -import java.util.List; - -/** - * Interface to be implemented by containers that decouples loading current classpath resources fromMap the effective - * classloader architecture current a runtime environment. Implementations current this class encapsulate the mechanism current - * determining the - * concrete resources available base on an expression defining the configuration - * locations. A an example the expression {@code cfg/global/*.xml} defines a - * location for reading global configuration in the classpath. A resources - * interprets this expression and evaluates the concrete resources to be read, - * e.g. {@code cfg/global/default.xml, cfg/global/myApp.xml}. - * Created by Anatole on 16.06.2014. - */ -public interface ResourceLoader{ - - /** - * Get the prefixes supportedby this loader. - * - * @return the supported prefixes, not empty. - */ - Collection<String> getResolverIds(); - - /** - * Called, when a given expression has to be resolved. - * - * @param expressions the expressions to be resolved, not empty. - * @return the corresponding collection current {@link java.net.URI}s defining the - * concrete resources to be read by a {@link org.apache.tamaya.core.properties.ConfigurationFormat} - * . - */ - List<Resource> getResources(String... expressions); - - /** - * Called, when a given expression has to be resolved. - * - * @param expressions the expressions to be resolved, not empty. - * @return the corresponding collection current {@link java.net.URI}s defining the - * concrete resources to be read by a {@link org.apache.tamaya.core.properties.ConfigurationFormat} - * . - */ - List<Resource> getResources(Collection<String> expressions); - - /** - * Called, when a given expression has to be resolved. - * - * @param expressions the expressions to be resolved, not empty. - * @return the corresponding collection current {@link java.net.URI}s defining the - * concrete resources to be read by a {@link org.apache.tamaya.core.properties.ConfigurationFormat} - * . - */ - List<Resource> getResources(ClassLoader classLoader, String... expressions); - - /** - * Called, when a given expression has to be resolved. - * - * @param expressions the expressions to be resolved, not empty. - * @return the corresponding collection current {@link java.net.URI}s defining the - * concrete resources to be read by a {@link org.apache.tamaya.core.properties.ConfigurationFormat} - * . - */ - List<Resource> getResources(ClassLoader classLoader, Collection<String> expressions); - -}