TAMAYA-63: Implemented backport for Java 7.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/bc62f716 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/bc62f716 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/bc62f716 Branch: refs/heads/master Commit: bc62f716262666003ad6cbcc9364e80e867e7e45 Parents: ffffdc8 Author: anatole <[email protected]> Authored: Sat Jan 24 11:18:08 2015 +0100 Committer: anatole <[email protected]> Committed: Sat Jan 24 21:06:16 2015 +0100 ---------------------------------------------------------------------- java7/core/pom.xml | 54 ++++ .../core/internal/DefaultConfiguration.java | 242 +++++++++++++++++ .../internal/DefaultConfigurationContext.java | 205 ++++++++++++++ .../core/internal/DefaultServiceContext.java | 146 ++++++++++ .../core/internal/PropertiesFileLoader.java | 102 +++++++ .../core/internal/PropertyConverterManager.java | 267 +++++++++++++++++++ .../tamaya/core/internal/ReflectionUtil.java | 42 +++ .../converters/BigDecimalConverter.java | 37 +++ .../converters/BigIntegerConverter.java | 38 +++ .../internal/converters/BooleanConverter.java | 57 ++++ .../core/internal/converters/ByteConverter.java | 34 +++ .../core/internal/converters/CharConverter.java | 38 +++ .../internal/converters/CurrencyConverter.java | 37 +++ .../internal/converters/DoubleConverter.java | 36 +++ .../core/internal/converters/EnumConverter.java | 58 ++++ .../internal/converters/FloatConverter.java | 36 +++ .../internal/converters/IntegerConverter.java | 35 +++ .../core/internal/converters/LongConverter.java | 35 +++ .../internal/converters/NumberConverter.java | 37 +++ .../internal/converters/ShortConverter.java | 35 +++ .../core/propertysource/BasePropertySource.java | 82 ++++++ .../core/propertysource/DefaultOrdinal.java | 54 ++++ .../EnvironmentPropertySource.java | 52 ++++ .../PropertiesFilePropertySource.java | 51 ++++ .../PropertiesPropertySource.java | 51 ++++ .../propertysource/SystemPropertySource.java | 91 +++++++ .../provider/JavaConfigurationProvider.java | 58 ++++ ....apache.tamaya.core.resources.ResourceLoader | 19 ++ .../org.apache.tamaya.spi.ConfigurationContext | 19 ++ .../org.apache.tamaya.spi.PropertyConverter | 30 +++ .../org.apache.tamaya.spi.ServiceContext | 19 ++ .../apache/tamaya/core/ConfigurationTest.java | 68 +++++ .../internal/DefaultServiceContextTest.java | 129 +++++++++ .../core/internal/PropetiesFileLoaderTest.java | 75 ++++++ .../converters/BooleanConverterTest.java | 106 ++++++++ .../internal/converters/ByteConverterTest.java | 55 ++++ .../ConverterTestsPropertySource.java | 117 ++++++++ .../propertysource/BasePropertySourceTest.java | 106 ++++++++ .../PropertiesFilePropertySourceTest.java | 71 +++++ .../SystemPropertySourceTest.java | 101 +++++++ .../provider/JavaConfigurationProviderTest.java | 60 +++++ .../testdata/TestPropertyDefaultSource.java | 56 ++++ .../core/testdata/TestPropertyFilter.java | 37 +++ .../testdata/TestPropertyFilterRemoving.java | 42 +++ .../testdata/TestPropertySourceProvider.java | 78 ++++++ ...tServiceContextTest$InvalidPriorityInterface | 19 ++ ...efaultServiceContextTest$MultiImplsInterface | 20 ++ .../org.apache.tamaya.spi.PropertyFilter | 20 ++ .../org.apache.tamaya.spi.PropertySource | 22 ++ ...org.apache.tamaya.spi.PropertySourceProvider | 20 ++ .../test/resources/javaconfiguration.properties | 22 ++ .../test/resources/overrideOrdinal.properties | 25 ++ .../core/src/test/resources/testfile.properties | 22 ++ java7/pom.xml | 2 - 54 files changed, 3368 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/pom.xml ---------------------------------------------------------------------- diff --git a/java7/core/pom.xml b/java7/core/pom.xml new file mode 100644 index 0000000..4727712 --- /dev/null +++ b/java7/core/pom.xml @@ -0,0 +1,54 @@ +<!-- +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 current the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-java7</artifactId> + <version>0.1-incubating-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <artifactId>tamaya-java7-core</artifactId> + <name>Apache Tamaya Java 7 Core</name> + + + <dependencies> + <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-java7-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-library</artifactId> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-core</artifactId> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfiguration.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfiguration.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfiguration.java new file mode 100644 index 0000000..720efe0 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfiguration.java @@ -0,0 +1,242 @@ +/* + * 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.internal; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.ConfigOperator; +import org.apache.tamaya.ConfigQuery; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.spi.ConfigurationContext; +import org.apache.tamaya.spi.PropertyConverter; +import org.apache.tamaya.spi.PropertyFilter; +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.ServiceContextManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Implementation of the Configuration API. This class uses the current {@link ConfigurationContext} to evaluate the + * chain of {@link org.apache.tamaya.spi.PropertySource} and {@link org.apache.tamaya.spi.PropertyFilter} + * instance to evaluate the current Configuration. + */ +public class DefaultConfiguration implements Configuration { + /** + * The logger. + */ + private static final Logger LOG = Logger.getLogger(DefaultConfiguration.class.getName()); + /** + * The maximal number of filter cycles performed before aborting. + */ + private static final int MAX_FILTER_LOOPS = 10; + + /** + * The current {@link org.apache.tamaya.spi.ConfigurationContext} of the current instance. + */ + private final ConfigurationContext configurationContext = ServiceContextManager.getServiceContext().getService(ConfigurationContext.class); + + /** + * This method evaluates the given configuration key. Hereby if goes down the chain or PropertySource instances + * provided by the current {@link org.apache.tamaya.spi.ConfigurationContext}. The first non-null-value returned + * is taken as an intermediate value. Finally the value is filtered through the + * {@link org.apache.tamaya.spi.PropertyFilter} instances installed, before it is returned as the final result of + * this method. + * + * @param key the property's key, not null. + * @return the optional configuration value, never null. + */ + @Override + public String get(String key) { + List<PropertySource> propertySources = configurationContext.getPropertySources(); + String unfilteredValue = null; + for (PropertySource propertySource : propertySources) { + String value = propertySource.get(key); + if (value != null) { + unfilteredValue = value.length() > 0 ? value : null; + break; + } + } + return applyFilter(key, unfilteredValue); + } + + /** + * Apply filters to a single property value. + * + * @param key the key, used for logging, not null. + * @param unfilteredValue the unfiltered property value. + * @return the filtered value, or null. + */ + private String applyFilter(String key, String unfilteredValue) { + // Apply filters to values, prevent values filtered to null! + for (int i = 0; i < MAX_FILTER_LOOPS; i++) { + boolean changed = false; + // Apply filters to values, prevent values filtered to null! + for (PropertyFilter filter : configurationContext.getPropertyFilters()) { + String newValue = filter.filterProperty(key, unfilteredValue); + if (newValue != null && !newValue.equals(unfilteredValue)) { + changed = true; + if (LOG.isLoggable(Level.FINEST)) { + LOG.finest("Filter - " + key + ": " + unfilteredValue + " -> " + newValue + " by " + filter); + } + } else if (unfilteredValue != null && !unfilteredValue.equals(newValue)) { + changed = true; + if (LOG.isLoggable(Level.FINEST)) { + LOG.finest("Filter - " + key + ": " + unfilteredValue + " -> " + newValue + " by " + filter); + } + } + unfilteredValue = newValue; + } + if (!changed) { + LOG.finest("Finishing filter loop, no changes detected."); + break; + } else { + if (i == (MAX_FILTER_LOOPS - 1)) { + if (LOG.isLoggable(Level.WARNING)) { + LOG.warning("Maximal filter loop count reached, aborting filter evaluation after cycles: " + i); + } + } else { + LOG.finest("Repeating filter loop, changes detected."); + } + } + } + return unfilteredValue; + } + + /** + * Get the current properties, composed by the loaded {@link org.apache.tamaya.spi.PropertySource} and filtered + * by registered {@link org.apache.tamaya.spi.PropertyFilter}. + * + * @return the final properties. + */ + @Override + public Map<String, String> getProperties() { + List<PropertySource> propertySources = new ArrayList<>(configurationContext.getPropertySources()); + Collections.reverse(propertySources); + Map<String, String> result = new HashMap<>(); + for (PropertySource propertySource : propertySources) { + try { + int origSize = result.size(); + Map<String, String> otherMap = propertySource.getProperties(); + LOG.log(Level.FINEST, null, "Overriding with properties from " + propertySource.getName()); + result.putAll(otherMap); + LOG.log(Level.FINEST, null, "Handled properties from " + propertySource.getName() + "(new: " + + (result.size() - origSize) + ", overrides: " + origSize + ", total: " + result.size()); + } catch (Exception e) { + LOG.log(Level.SEVERE, "Error adding properties from PropertySource: " + propertySource + ", ignoring PropertySource.", e); + } + } + return applyFilters(result); + } + + /** + * Filter a full configuration property map. + * + * @param inputMap the unfiltered map + * @return the filtered map. + */ + private Map<String, String> applyFilters(Map<String, String> inputMap) { + final Map<String, String> resultMap = new HashMap<>(); + // Apply filters to values, prevent values filtered to null! + for (int i = 0; i < MAX_FILTER_LOOPS; i++) { + AtomicInteger changes = new AtomicInteger(); + for (PropertyFilter filter : configurationContext.getPropertyFilters()) { + + + for (Map.Entry<String, String> entry : inputMap.entrySet()) { + final String k = entry.getKey(); + final String v = entry.getValue(); + + String newValue = filter.filterProperty(k, v); + if (newValue != null && !newValue.equals(v)) { + changes.incrementAndGet(); + LOG.finest("Filter - " + k + ": " + v + " -> " + newValue + " by " + filter); + } else if (v != null && !v.equals(newValue)) { + changes.incrementAndGet(); + LOG.finest("Filter - " + k + ": " + v + " -> " + newValue + " by " + filter); + } + // Remove null values + if (null != newValue) { + resultMap.put(k, newValue); + } + } + } + if (changes.get() == 0) { + LOG.finest("Finishing filter loop, no changes detected."); + break; + } else { + if (i == (MAX_FILTER_LOOPS - 1)) { + if (LOG.isLoggable(Level.WARNING)) { + LOG.warning("Maximal filter loop count reached, aborting filter evaluation after cycles: " + i); + } + } else { + LOG.finest("Repeating filter loop, changes detected: " + changes.get()); + } + changes.set(0); + } + } + + return resultMap; + } + + /** + * Accesses the current String value for the given key and tries to convert it + * using the {@link org.apache.tamaya.spi.PropertyConverter} instances provided by the current + * {@link org.apache.tamaya.spi.ConfigurationContext}. + * + * @param key the property's absolute, or relative path, e.g. @code + * a/b/c/d.myProperty}. + * @param type The target type required, not null. + * @param <T> the value type + * @return the converted value, never null. + */ + @Override + public <T> T get(String key, Class<T> type) { + String value = get(key); + if (value != null) { + List<PropertyConverter<T>> converters = configurationContext.getPropertyConverters(type); + for (PropertyConverter<T> converter : converters) { + try { + T t = converter.convert(value); + if (t != null) { + return t; + } + } catch (Exception e) { + LOG.log(Level.FINEST, "PropertyConverter: " + converter + " failed to convert value: " + value, e); + } + } + throw new ConfigException("Unparseable config value for type: " + type.getName() + ": " + key); + } + + return null; + } + + public Configuration with(ConfigOperator operator) { + return operator.operate(this); + } + + public <T> T query(ConfigQuery<T> query) { + return query.query(this); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContext.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContext.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContext.java new file mode 100644 index 0000000..3abae9d --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultConfigurationContext.java @@ -0,0 +1,205 @@ +/* + * 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.internal; + +import org.apache.tamaya.spi.ConfigurationContext; +import org.apache.tamaya.spi.PropertyConverter; +import org.apache.tamaya.spi.PropertyFilter; +import org.apache.tamaya.spi.PropertySource; +import org.apache.tamaya.spi.PropertySourceProvider; +import org.apache.tamaya.spi.ServiceContextManager; + +import javax.annotation.Priority; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Default Implementation of a simple ConfigurationContext. + */ +public class DefaultConfigurationContext implements ConfigurationContext { + /** + * Cubcomponent handling {@link org.apache.tamaya.spi.PropertyConverter} instances. + */ + private PropertyConverterManager propertyConverterManager = new PropertyConverterManager(); + + /** + * The current unmodifiable list of loaded {@link org.apache.tamaya.spi.PropertySource} instances. + */ + private List<PropertySource> immutablePropertySources; + + /** + * The current unmodifiable list of loaded {@link org.apache.tamaya.spi.PropertyFilter} instances. + */ + private List<PropertyFilter> immutablePropertyFilters; + + /** + * Lock for internal synchronization. + */ + private ReentrantReadWriteLock propertySourceLock = new ReentrantReadWriteLock(); + + + /** + * The first time the Configuration system gets invoked we do initialize + * all our {@link org.apache.tamaya.spi.PropertySource}s and + * {@link org.apache.tamaya.spi.PropertyFilter}s which are known at startup. + */ + public DefaultConfigurationContext() { + List<PropertySource> propertySources = new ArrayList<>(); + + // first we load all PropertySources which got registered via java.util.ServiceLoader + propertySources.addAll(ServiceContextManager.getServiceContext().getServices(PropertySource.class)); + + // after that we add all PropertySources which get dynamically registered via their PropertySourceProviders + propertySources.addAll(evaluatePropertySourcesFromProviders()); + + // now sort them according to their ordinal values + Collections.sort(propertySources, new PropertySourceComparator()); + + immutablePropertySources = Collections.unmodifiableList(propertySources); + + // as next step we pick up the PropertyFilters pretty much the same way + List<PropertyFilter> propertyFilters = new ArrayList<>(); + propertyFilters.addAll(ServiceContextManager.getServiceContext().getServices(PropertyFilter.class)); + Collections.sort(propertyFilters, new PropertyFilterComparator()); + + immutablePropertyFilters = Collections.unmodifiableList(propertyFilters); + } + + /** + * Pick up all {@link org.apache.tamaya.spi.PropertySourceProvider}s and return all the + * {@link org.apache.tamaya.spi.PropertySource}s they like to register. + */ + private Collection<? extends PropertySource> evaluatePropertySourcesFromProviders() { + List<PropertySource> propertySources = new ArrayList<>(); + List<PropertySourceProvider> propertySourceProviders = ServiceContextManager.getServiceContext().getServices(PropertySourceProvider.class); + for (PropertySourceProvider propertySourceProvider : propertySourceProviders) { + propertySources.addAll(propertySourceProvider.getPropertySources()); + } + + return propertySources; + } + + @Override + public void addPropertySources(PropertySource... propertySourcesToAdd) { + Lock writeLock = propertySourceLock.writeLock(); + try { + writeLock.lock(); + List<PropertySource> newPropertySources = new ArrayList<>(this.immutablePropertySources); + newPropertySources.addAll(Arrays.asList(propertySourcesToAdd)); + Collections.sort(newPropertySources, new PropertySourceComparator()); + + this.immutablePropertySources = Collections.unmodifiableList(newPropertySources); + } finally { + writeLock.unlock(); + } + } + + private static class PropertySourceComparator implements Comparator<PropertySource>, Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Order property source reversely, the most important come first. + * + * @param source1 the first PropertySource + * @param source2 the second PropertySource + * @return the comparison result. + */ + private int comparePropertySources(PropertySource source1, PropertySource source2) { + if (source1.getOrdinal() < source2.getOrdinal()) { + return 1; + } else if (source1.getOrdinal() > source2.getOrdinal()) { + return -1; + } else { + return source2.getClass().getName().compareTo(source1.getClass().getName()); + } + } + + @Override + public int compare(PropertySource source1, PropertySource source2) { + return comparePropertySources(source1, source2); + } + } + + private static class PropertyFilterComparator implements Comparator<PropertyFilter>, Serializable{ + + private static final long serialVersionUID = 1L; + + /** + * Compare 2 filters for ordering the filter chain. + * + * @param filter1 the first filter + * @param filter2 the second filter + * @return the comparison result + */ + private int comparePropertyFilters(PropertyFilter filter1, PropertyFilter filter2) { + Priority prio1 = filter1.getClass().getAnnotation(Priority.class); + Priority prio2 = filter2.getClass().getAnnotation(Priority.class); + int ord1 = prio1 != null ? prio1.value() : 0; + int ord2 = prio2 != null ? prio2.value() : 0; + + if (ord1 < ord2) { + return -1; + } else if (ord1 > ord2) { + return 1; + } else { + return filter1.getClass().getName().compareTo(filter2.getClass().getName()); + } + } + + @Override + public int compare(PropertyFilter filter1, PropertyFilter filter2) { + return comparePropertyFilters(filter1, filter2); + } + } + + @Override + public List<PropertySource> getPropertySources() { + return immutablePropertySources; + } + + @Override + public <T> void addPropertyConverter(Class<T> typeToConvert, PropertyConverter<T> propertyConverter) { + propertyConverterManager.register(typeToConvert, propertyConverter); + } + + @Override + public Map<Class<?>, List<PropertyConverter<?>>> getPropertyConverters() { + return propertyConverterManager.getPropertyConverters(); + } + + @Override + public <T> List<PropertyConverter<T>> getPropertyConverters(Class<T> targetType) { + return propertyConverterManager.getPropertyConverters(targetType); + } + + @Override + public List<PropertyFilter> getPropertyFilters() { + return immutablePropertyFilters; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java new file mode 100644 index 0000000..2e59fa2 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java @@ -0,0 +1,146 @@ +/* + * 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.internal; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.spi.ServiceContext; + +import javax.annotation.Priority; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class implements the (default) {@link org.apache.tamaya.spi.ServiceContext} interface and hereby uses the JDK + * {@link java.util.ServiceLoader} to load the services required. + */ +public final class DefaultServiceContext implements ServiceContext { + /** + * List current services loaded, per class. + */ + private final ConcurrentHashMap<Class, List<Object>> servicesLoaded = new ConcurrentHashMap<>(); + /** + * Singletons. + */ + private final Map<Class, Object> singletons = new ConcurrentHashMap<>(); + + @Override + public <T> T getService(Class<T> serviceType) { + Object cached = singletons.get(serviceType); + if (cached == null) { + List<? extends T> services = getServices(serviceType); + if (services.isEmpty()) { + cached = null; + } else { + cached = getServiceWithHighestPriority(services, serviceType); + } + if(cached!=null) { + singletons.put(serviceType, cached); + } + } + return (T)cached; + } + + /** + * Loads and registers services. + * + * @param serviceType The service type. + * @param <T> the concrete type. + * @return the items found, never {@code null}. + */ + @Override + public <T> List<T> getServices(final Class<T> serviceType) { + List<T> found = (List<T>) servicesLoaded.get(serviceType); + if (found != null) { + return found; + } + List<T> services = new ArrayList<>(); + try { + for (T t : ServiceLoader.load(serviceType)) { + services.add(t); + } + services = Collections.unmodifiableList(services); + } catch (Exception e) { + Logger.getLogger(DefaultServiceContext.class.getName()).log(Level.WARNING, + "Error loading services current type " + serviceType, e); + } + final List<T> previousServices = List.class.cast(servicesLoaded.putIfAbsent(serviceType, (List<Object>) services)); + return previousServices != null ? previousServices : services; + } + + + /** + * @param services to scan + * @param <T> type of the service + * + * @return the service with the highest {@link javax.annotation.Priority#value()} + * + * @throws ConfigException if there are multiple service implementations with the maximum priority + */ + private <T> T getServiceWithHighestPriority(List<? extends T> services, Class<T> serviceType) { + + // we do not need the priority stuff if the list contains only one element + if (services.size() == 1) { + return services.get(0); + } + + Integer highestPriority = null; + int highestPriorityServiceCount = 0; + T highestService = null; + + for (T service : services) { + int prio = 1; //X TODO discuss default priority + Priority priority = service.getClass().getAnnotation(Priority.class); + if (priority != null) { + prio = priority.value(); + } + + if (highestPriority == null || highestPriority < prio) { + highestService = service; + highestPriorityServiceCount = 1; + highestPriority = prio; + } else if (highestPriority == prio) { + highestPriorityServiceCount++; + } + } + + if (highestPriorityServiceCount > 1) { + throw new ConfigException(MessageFormat.format("Found {0} implementations for Service {1} with Priority {2}: {3}", + highestPriorityServiceCount, + serviceType.getName(), + highestPriority, + services)); + } + + return highestService; + } + + @Override + public int ordinal() { + return 1; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertiesFileLoader.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertiesFileLoader.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertiesFileLoader.java new file mode 100644 index 0000000..ffd9a41 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertiesFileLoader.java @@ -0,0 +1,102 @@ +/* + * 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.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; + +public final class PropertiesFileLoader { + + + private PropertiesFileLoader() { + // no instantiation + } + + + /** + * loads all properties-files with the given name. + * If the name do not end with {@code .properties} it will be appended + * + * @param name of the properties file + * + * @return URLs of properties-files or + * an empty {@link java.util.Set} if no files has been found + * + * @throws java.io.IOException in case of problems loading the properties-files + */ + public static Set<URL> resolvePropertiesFiles(String name) throws IOException { + Objects.requireNonNull(name); + + if (!name.endsWith(".properties")) { + name = name + ".properties"; + } + + Set<URL> urls = new HashSet<>(); + + Enumeration<URL> files = Thread.currentThread().getContextClassLoader().getResources(name); + while (files.hasMoreElements()) { + urls.add(files.nextElement()); + } + + return urls; + } + + + /** + * loads the Properties from the given URL + * + * @param propertiesFile {@link java.net.URL} to load Properties from + * + * @return loaded {@link java.util.Properties} + * + * @throws IllegalStateException in case of an error while reading properties-file + */ + public static Properties load(URL propertiesFile) { + + Properties properties = new Properties(); + + InputStream stream = null; + try { + stream = propertiesFile.openStream(); + + if (stream != null) { + properties.load(stream); + } + } catch (IOException e) { + throw new IllegalStateException("Error loading Properties " + propertiesFile, e); + } finally { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + // bad luck -> stream is already closed + } + } + } + + return properties; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java new file mode 100644 index 0000000..67d77b6 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java @@ -0,0 +1,267 @@ +/* + * 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.internal; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.core.internal.converters.EnumConverter; +import org.apache.tamaya.spi.PropertyConverter; +import org.apache.tamaya.spi.ServiceContextManager; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Manager that deals with {@link org.apache.tamaya.spi.PropertyConverter} instances. + * This class is thread-safe. + */ +public class PropertyConverterManager { + /** + * The logger used. + */ + private static final Logger LOG = Logger.getLogger(PropertyConverterManager.class.getName()); + /** + * The registered converters. + */ + private Map<Class<?>, List<PropertyConverter<?>>> converters = new ConcurrentHashMap<>(); + /** + * The lock used. + */ + private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + private static final String CHAR_NULL_ERROR = "Cannot convert null property"; + + /** + * Constructor. + */ + public PropertyConverterManager() { + initConverters(); + } + + /** + * Registers the default converters provided out of the box. + */ + protected void initConverters() { + for (PropertyConverter conv : ServiceContextManager.getServiceContext().getServices(PropertyConverter.class)) { + ParameterizedType type = ReflectionUtil.getParametrizedType(conv.getClass()); + if (type == null || type.getActualTypeArguments().length == 0) { + LOG.warning("Failed to register PropertyConverter, no generic type information available: " + + conv.getClass().getName()); + } else { + Type targetType = type.getActualTypeArguments()[0]; + register((Class<?>) targetType, conv); + } + } + } + + /** + * Registers a ew converter instance. + * + * @param targetType the target type, not null. + * @param converter the converter, not null. + * @param <T> the type. + */ + public <T> void register(Class<T> targetType, PropertyConverter<T> converter) { + Objects.requireNonNull(converter); + Lock writeLock = lock.writeLock(); + try { + writeLock.lock(); + List converters = List.class.cast(this.converters.get(targetType)); + List<PropertyConverter<?>> newConverters = new ArrayList<>(); + if (converters != null) { + newConverters.addAll(converters); + } + newConverters.add(converter); + this.converters.put(targetType, Collections.unmodifiableList(newConverters)); + } finally { + writeLock.unlock(); + } + } + + /** + * Allows to evaluate if a given target type is supported. + * + * @param targetType the target type, not null. + * @return true, if a converter for the given type is registered, or a default one can be created. + */ + public boolean isTargetTypeSupported(Class<?> targetType) { + return converters.containsKey(targetType) + || createDefaultPropertyConverter(targetType) != null; + } + + /** + * Get a map of all property converters currently registered. This will not contain the converters that + * may be created, when an instance is adapted, which provides a String constructor or compatible + * factory methods taking a single String instance. + * + * @return the current map of instantiated and registered converters. + * @see #createDefaultPropertyConverter(Class) + */ + public Map<Class<?>, List<PropertyConverter<?>>> getPropertyConverters() { + Lock readLock = lock.readLock(); + try { + readLock.lock(); + return new HashMap<>(this.converters); + } finally { + readLock.unlock(); + } + } + + /** + * Get the list of all current registered converters for the given target type. + * If not converters are registered, they component tries to create and register a dynamic + * converter based on String costructor or static factory methods available. + * + * @param targetType the target type, not null. + * @param <T> the type class + * @return the ordered list of converters (may be empty for not convertible types). + * @see #createDefaultPropertyConverter(Class) + */ + public <T> List<PropertyConverter<T>> getPropertyConverters(Class<T> targetType) { + Lock readLock = lock.readLock(); + List<PropertyConverter<T>> converters; + try { + readLock.lock(); + converters = List.class.cast(this.converters.get(targetType)); + } finally { + readLock.unlock(); + } + if (converters != null) { + return converters; + } + PropertyConverter<T> defaultConverter = createDefaultPropertyConverter(targetType); + if (defaultConverter != null) { + register(targetType, defaultConverter); + try { + converters = List.class.cast(this.converters.get(targetType)); + } finally { + readLock.unlock(); + } + } + if (converters != null) { + return converters; + } + return Collections.emptyList(); + } + + /** + * Creates a dynamic PropertyConverter for the given target type. + * + * @param targetType the target type + * @param <T> the type class + * @return a new converter, or null. + */ + protected <T> PropertyConverter<T> createDefaultPropertyConverter(final Class<T> targetType) { + if (Enum.class.isAssignableFrom(targetType)) { + return new EnumConverter<T>(targetType); + } + PropertyConverter<T> converter = null; + final Method factoryMethod = getFactoryMethod(targetType, "of", "valueOf", "instanceOf", "getInstance", "from", "fromString", "parse"); + if (factoryMethod != null) { + converter = new ViaMethodPropertyConverter<>(factoryMethod, targetType); + } + if (converter == null) { + try { + final Constructor<T> constr = targetType.getDeclaredConstructor(String.class); + converter = new ViaConstructorPropertyConverter<>(constr); + } catch (Exception e) { + LOG.log(Level.FINEST, "Failed to construct instance of type: " + targetType.getName(), e); + } + } + return converter; + } + + /** + * Tries to evaluate a factory method that can be used to create an instance based on a String. + * + * @param type the target type + * @param methodNames the possible static method names + * @return the first method found, or null. + */ + private Method getFactoryMethod(Class<?> type, String... methodNames) { + Method m; + for (String name : methodNames) { + try { + m = type.getDeclaredMethod(name, String.class); + return m; + } catch (NoSuchMethodException | RuntimeException e) { + LOG.log(Level.FINEST, "No such factory method found on type: " + type.getName() + ", methodName: " + name, e); + } + } + return null; + } + + private static class ViaMethodPropertyConverter<T> implements PropertyConverter<T> { + private final Method factoryMethod; + private final Class<T> targetType; + + public ViaMethodPropertyConverter(Method factoryMethod, Class<T> targetType) { + this.factoryMethod = factoryMethod; + this.targetType = targetType; + } + + public T convert(final String value) { + try { + AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public Object run() { + factoryMethod.setAccessible(true); + return null; + } + }); + return targetType.cast(factoryMethod.invoke(value)); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new ConfigException("Failed to decode '" + value + "'", e); + } + } + } + + private static class ViaConstructorPropertyConverter<T> implements PropertyConverter<T> { + private final Constructor<T> constr; + + public ViaConstructorPropertyConverter(Constructor<T> constr) { + this.constr = constr; + } + + @Override + public T convert(String value) { + try { + constr.setAccessible(true); + return constr.newInstance(value); + } catch (Exception e) { + throw new ConfigException("Failed to decode '" + value + "'", e); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/ReflectionUtil.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/ReflectionUtil.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/ReflectionUtil.java new file mode 100644 index 0000000..6c7a1d2 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/ReflectionUtil.java @@ -0,0 +1,42 @@ +/* + * 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.internal; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + + +/** + * Small utility class used by other parts. + */ +public final class ReflectionUtil { + + private ReflectionUtil(){} + + public static ParameterizedType getParametrizedType(Class<?> clazz) { + Type[] genericTypes = clazz.getGenericInterfaces(); + for (Type type : genericTypes) { + if (type instanceof ParameterizedType) { + return (ParameterizedType) type; + } + + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BigDecimalConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BigDecimalConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BigDecimalConverter.java new file mode 100644 index 0000000..f927e22 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BigDecimalConverter.java @@ -0,0 +1,37 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.math.BigDecimal; +import java.util.Objects; + +/** + * Converter, converting from String to BigDecimal. + * //X TODO not good enough as this is Locale dependent! + */ +public class BigDecimalConverter implements PropertyConverter<BigDecimal>{ + + @Override + public BigDecimal convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + return new BigDecimal(trimmed); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BigIntegerConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BigIntegerConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BigIntegerConverter.java new file mode 100644 index 0000000..f0eba47 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BigIntegerConverter.java @@ -0,0 +1,38 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.math.BigInteger; +import java.util.Objects; + +/** + * Converter, converting from String to BigInteger. + * //X TODO not good enough as this is Locale dependent! + */ +public class BigIntegerConverter implements PropertyConverter<BigInteger>{ + + @Override + public BigInteger convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + return new BigInteger(trimmed); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java new file mode 100644 index 0000000..6c33d7f --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java @@ -0,0 +1,57 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.util.Locale; +import java.util.Objects; +import java.util.logging.Logger; + +/** + * Converter, converting from String to Boolean. + */ +public class BooleanConverter implements PropertyConverter<Boolean> { + + private Logger LOG = Logger.getLogger(getClass().getName()); + + @Override + public Boolean convert(String value) { + String ignoreCaseValue = Objects.requireNonNull(value) + .trim() + .toLowerCase(Locale.ENGLISH); + + switch(ignoreCaseValue) { + case "yes": + case "y": + case "true": + case "t": + return Boolean.TRUE; + case "no": + case "n": + case "false": + case "f": + return Boolean.FALSE; + default: + LOG.warning("Unknown boolean value encountered: " + value); + } + + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java new file mode 100644 index 0000000..1d9bf65 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java @@ -0,0 +1,34 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; +import java.util.Objects; + +/** + * Converter, converting from String to Byte. + */ +public class ByteConverter implements PropertyConverter<Byte>{ + + @Override + public Byte convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + return Byte.decode(trimmed); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/CharConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/CharConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/CharConverter.java new file mode 100644 index 0000000..829c16b --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/CharConverter.java @@ -0,0 +1,38 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.util.Objects; + +/** + * Converter, converting from String to Character. + */ +public class CharConverter implements PropertyConverter<Character>{ + + @Override + public Character convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + if(trimmed.length()!=1){ + return null; + } + return Character.valueOf(value.charAt(0)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/CurrencyConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/CurrencyConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/CurrencyConverter.java new file mode 100644 index 0000000..c3c6e56 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/CurrencyConverter.java @@ -0,0 +1,37 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.util.Currency; +import java.util.Locale; +import java.util.Objects; + +/** + * Converter, converting from String to Currency. + */ +public class CurrencyConverter implements PropertyConverter<Currency>{ + + @Override + public Currency convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + return Currency.getInstance(trimmed.toUpperCase(Locale.ENGLISH)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/DoubleConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/DoubleConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/DoubleConverter.java new file mode 100644 index 0000000..8eb016b --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/DoubleConverter.java @@ -0,0 +1,36 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.util.Objects; + +/** + * Converter, converting from String to Double. + */ +public class DoubleConverter implements PropertyConverter<Double>{ + + @Override + public Double convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + //X TODO not good enough as this is Locale dependent! + return Double.valueOf(trimmed); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/EnumConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/EnumConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/EnumConverter.java new file mode 100644 index 0000000..652c808 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/EnumConverter.java @@ -0,0 +1,58 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.spi.PropertyConverter; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Objects; +import java.util.logging.Logger; + +/** + * Converter, converting from String to tge given enum type. + */ +public class EnumConverter<T> implements PropertyConverter<T> { + private Logger LOG = Logger.getLogger(EnumConverter.class.getName()); + private Class<T> enumType; + private Method factory; + + public EnumConverter(Class<T> enumType) { + if (!Enum.class.isAssignableFrom(enumType)) { + throw new IllegalArgumentException("Not an Enum: " + enumType.getName()); + } + this.enumType = Objects.requireNonNull(enumType); + try { + this.factory = enumType.getMethod("valueOf", String.class); + } catch (NoSuchMethodException e) { + throw new ConfigException("Uncovertible enum type without valueOf method found, please provide a custom " + + "PropertyConverter for: " + enumType.getName()); + } + } + + @Override + public T convert(String value) { + try { + return (T) factory.invoke(null, value); + } catch (InvocationTargetException | IllegalAccessException e) { + throw new ConfigException("Invalid enum value '" + value + "' for " + enumType.getName(), e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/FloatConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/FloatConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/FloatConverter.java new file mode 100644 index 0000000..839dbe0 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/FloatConverter.java @@ -0,0 +1,36 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.util.Objects; + +/** + * Converter, converting from String to Float. + */ +public class FloatConverter implements PropertyConverter<Float>{ + + @Override + public Float convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + //X TODO not good enough as this is Locale dependent! + return Float.valueOf(trimmed); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/IntegerConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/IntegerConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/IntegerConverter.java new file mode 100644 index 0000000..c67e587 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/IntegerConverter.java @@ -0,0 +1,35 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.util.Objects; + +/** + * Converter, converting from String to Integer. + */ +public class IntegerConverter implements PropertyConverter<Integer>{ + + @Override + public Integer convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + return Integer.decode(trimmed); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/LongConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/LongConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/LongConverter.java new file mode 100644 index 0000000..600d875 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/LongConverter.java @@ -0,0 +1,35 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.util.Objects; + +/** + * Converter, converting from String to Long. + */ +public class LongConverter implements PropertyConverter<Long>{ + + @Override + public Long convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + return Long.decode(trimmed); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/NumberConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/NumberConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/NumberConverter.java new file mode 100644 index 0000000..6c8094f --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/NumberConverter.java @@ -0,0 +1,37 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.math.BigDecimal; +import java.util.Objects; + +/** + * Converter, converting from String to BigDecimal. + * //X TODO not good enough as this is Locale dependent! + */ +public class NumberConverter implements PropertyConverter<Number>{ + + @Override + public Number convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + return new BigDecimal(trimmed); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/ShortConverter.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/ShortConverter.java b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/ShortConverter.java new file mode 100644 index 0000000..8a71ef7 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/internal/converters/ShortConverter.java @@ -0,0 +1,35 @@ +/* + * 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.internal.converters; + +import org.apache.tamaya.spi.PropertyConverter; + +import java.util.Objects; + +/** + * Converter, converting from String to Short. + */ +public class ShortConverter implements PropertyConverter<Short>{ + + @Override + public Short convert(String value) { + String trimmed = Objects.requireNonNull(value).trim(); + return Short.decode(trimmed); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/propertysource/BasePropertySource.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/propertysource/BasePropertySource.java b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/BasePropertySource.java new file mode 100644 index 0000000..2172094 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/BasePropertySource.java @@ -0,0 +1,82 @@ +/* + * 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.propertysource; + +import org.apache.tamaya.spi.PropertySource; + +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A base class for {@link PropertySource}s. It provides a {@link #initializeOrdinal(int)} method that + * reads the ordinal from the config source itself, allowing the ordinal to be "self-configured" by + * the configuration read. + */ +public abstract class BasePropertySource implements PropertySource { + + private static final Logger LOG = Logger.getLogger(BasePropertySource.class.getName()); + + + private int ordinal = DefaultOrdinal.PROPERTY_SOURCE; + + + @Override + public int getOrdinal() { + return ordinal; + } + + + @Override + public String get(String key) { + Objects.requireNonNull(key, "key must not be null"); + return getProperties().get(key); + } + + @Override + public boolean isScannable() { + return true; + } + + + /** + * Initializing the ordinal of this {@link PropertySource} with the given defaultOrdinal. + * + * If {@link PropertySource#TAMAYA_ORDINAL} is present via {@link #get(String)} and the + * value is a valid {@link Integer} then, the defaultOrdinal will be overridden. + * + * @param defaultOrdinal of the {@link PropertySource} + */ + protected void initializeOrdinal(final int defaultOrdinal) { + this.ordinal = defaultOrdinal; + + String ordinal = get(PropertySource.TAMAYA_ORDINAL); + if (ordinal != null) { + + try { + this.ordinal = Integer.parseInt(ordinal); + } catch (NumberFormatException e) { + LOG.log(Level.WARNING, + "Specified {0} is not a valid Integer value: {1} - using defaultOrdinal {2}", + new Object[]{PropertySource.TAMAYA_ORDINAL, ordinal, defaultOrdinal}); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/propertysource/DefaultOrdinal.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/propertysource/DefaultOrdinal.java b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/DefaultOrdinal.java new file mode 100644 index 0000000..ff35e3f --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/DefaultOrdinal.java @@ -0,0 +1,54 @@ +/* + * 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.propertysource; + + +/** + * This interface defines the default ordinals for the 'standard' + * {@link org.apache.tamaya.spi.PropertySource}s + * + * DefaultOrdinals can be overwritten via {@link org.apache.tamaya.spi.PropertySource#TAMAYA_ORDINAL} + */ +public final class DefaultOrdinal { + + /** Private constructor. */ + private DefaultOrdinal(){} + + /** + * default ordinal for {@link org.apache.tamaya.core.propertysource.BasePropertySource} if + * not overriden in each class + */ + public static final int PROPERTY_SOURCE = 1000; + + /** + * default ordinal for {@link org.apache.tamaya.core.propertysource.SystemPropertySource} + */ + public static final int SYSTEM_PROPERTIES = 400; + + /** + * default ordinal for {@link org.apache.tamaya.core.propertysource.EnvironmentPropertySource} + */ + public static final int ENVIRONMENT_PROPERTIES = 300; + + /** + * default ordinal for {@link org.apache.tamaya.core.propertysource.PropertiesFilePropertySource} + */ + public static final int FILE_PROPERTIES = 100; + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/propertysource/EnvironmentPropertySource.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/propertysource/EnvironmentPropertySource.java b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/EnvironmentPropertySource.java new file mode 100644 index 0000000..3f60b29 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/EnvironmentPropertySource.java @@ -0,0 +1,52 @@ +/* + * 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.propertysource; + +import java.util.Map; + +/** + * This {@link org.apache.tamaya.spi.PropertySource} provides all Properties which are set + * via <br /> + * {@code export myprop=myval} on UNIX Systems or<br /> + * {@code set myprop=myval} on Windows + */ +public class EnvironmentPropertySource extends BasePropertySource { + + public EnvironmentPropertySource() { + initializeOrdinal(DefaultOrdinal.ENVIRONMENT_PROPERTIES); + } + + + @Override + public String getName() { + return "environment-properties"; + } + + @Override + public Map<String, String> getProperties() { + return System.getenv(); // already a map and unmodifiable + + } + + @Override + public boolean isScannable() { + return true; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/propertysource/PropertiesFilePropertySource.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/propertysource/PropertiesFilePropertySource.java b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/PropertiesFilePropertySource.java new file mode 100644 index 0000000..86597f1 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/PropertiesFilePropertySource.java @@ -0,0 +1,51 @@ +/* + * 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.propertysource; + +import org.apache.tamaya.core.internal.PropertiesFileLoader; + +import java.net.URL; + +/** + * {@link org.apache.tamaya.spi.PropertySource} for properties-files + */ +public class PropertiesFilePropertySource extends PropertiesPropertySource { + + + private String fileName; + + + public PropertiesFilePropertySource(URL propertiesFile) { + super(PropertiesFileLoader.load(propertiesFile)); + + initializeOrdinal(DefaultOrdinal.FILE_PROPERTIES); + this.fileName = propertiesFile.toExternalForm(); + } + + + @Override + public String getName() { + return fileName; + } + + @Override + public boolean isScannable() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/bc62f716/java7/core/src/main/java/org/apache/tamaya/core/propertysource/PropertiesPropertySource.java ---------------------------------------------------------------------- diff --git a/java7/core/src/main/java/org/apache/tamaya/core/propertysource/PropertiesPropertySource.java b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/PropertiesPropertySource.java new file mode 100644 index 0000000..cf68bd6 --- /dev/null +++ b/java7/core/src/main/java/org/apache/tamaya/core/propertysource/PropertiesPropertySource.java @@ -0,0 +1,51 @@ +/* + * 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.propertysource; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * base class for {@link org.apache.tamaya.spi.PropertySource}s which are based on + * {@link java.util.Properties} + */ +abstract class PropertiesPropertySource extends BasePropertySource { + + protected Map<String, String> properties; + + + // package private to not expose this class + PropertiesPropertySource(Properties properties) { + Map<String, String> props = new HashMap<>(); + + for (String key : properties.stringPropertyNames()) { + props.put(key, properties.getProperty(key)); + } + + this.properties = Collections.unmodifiableMap(props); + } + + + @Override + public Map<String, String> getProperties() { + return properties; + } +}
