You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by pl...@apache.org on 2015/12/20 14:05:54 UTC
[7/8] incubator-tamaya git commit: Moved module core to ./code/
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java
new file mode 100644
index 0000000..2a15e1d
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java
@@ -0,0 +1,448 @@
+/*
+ * 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.TypeLiteral;
+import org.apache.tamaya.core.internal.converters.EnumConverter;
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+import org.apache.tamaya.spi.ServiceContextManager;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+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.ReadWriteLock;
+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<TypeLiteral<?>, List<PropertyConverter<?>>> converters = new ConcurrentHashMap<>();
+ /**
+ * The transitive converters.
+ */
+ private Map<TypeLiteral<?>, List<PropertyConverter<?>>> transitiveConverters = new ConcurrentHashMap<>();
+ /**
+ * The lock used.
+ */
+ private ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ private static final Comparator<Object> PRIORITY_COMPARATOR = new Comparator<Object>() {
+
+ @Override
+ public int compare(Object o1, Object o2) {
+ int prio = DefaultServiceContext.getPriority(o1) - DefaultServiceContext.getPriority(o2);
+ if (prio < 0) {
+ return 1;
+ } else if (prio > 0) {
+ return -1;
+ } else {
+ return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
+ }
+ }
+ };
+
+ /**
+ * Constructor.
+ */
+ public PropertyConverterManager() {
+ this(true);
+ }
+
+ public PropertyConverterManager(boolean init) {
+ if (init) {
+ initConverters();
+ }
+ }
+
+ /**
+ * Registers the default converters provided out of the box.
+ */
+ protected void initConverters() {
+ for (PropertyConverter conv : ServiceContextManager.getServiceContext().getServices(PropertyConverter.class)) {
+ Type type = TypeLiteral.getGenericInterfaceTypeParameters(conv.getClass(), PropertyConverter.class)[0];
+ register(TypeLiteral.of(type), 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(TypeLiteral<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);
+ Collections.sort(newConverters, PRIORITY_COMPARATOR);
+ this.converters.put(targetType, Collections.unmodifiableList(newConverters));
+ // evaluate transitive closure for all inherited supertypes and implemented interfaces
+ // direct implemented interfaces
+ for (Class<?> ifaceType : targetType.getRawType().getInterfaces()) {
+ converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType)));
+ newConverters = new ArrayList<>();
+ if (converters != null) {
+ newConverters.addAll(converters);
+ }
+ newConverters.add(converter);
+ Collections.sort(newConverters, PRIORITY_COMPARATOR);
+ this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters));
+ }
+ Class<?> superClass = targetType.getRawType().getSuperclass();
+ while (superClass != null && !superClass.equals(Object.class)) {
+ converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(superClass)));
+ newConverters = new ArrayList<>();
+ if (converters != null) {
+ newConverters.addAll(converters);
+ }
+ newConverters.add(converter);
+ Collections.sort(newConverters, PRIORITY_COMPARATOR);
+ this.transitiveConverters.put(TypeLiteral.of(superClass), Collections.unmodifiableList(newConverters));
+ for (Class<?> ifaceType : superClass.getInterfaces()) {
+ converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType)));
+ newConverters = new ArrayList<>();
+ if (converters != null) {
+ newConverters.addAll(converters);
+ }
+ newConverters.add(converter);
+ Collections.sort(newConverters, PRIORITY_COMPARATOR);
+ this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters));
+ }
+ superClass = superClass.getSuperclass();
+ }
+ } 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(TypeLiteral<?> targetType) {
+ if (converters.containsKey(targetType) || transitiveConverters.containsKey(targetType)) {
+ return true;
+ }
+ return 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(org.apache.tamaya.TypeLiteral)
+ */
+ public Map<TypeLiteral<?>, 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.<br/>
+ * The converters provided are of the following type and returned in the following order:
+ * <ul>
+ * <li>Converters mapped explicitly to the required target type are returned first, ordered
+ * by decreasing priority. This means, if explicit converters are registered these are used
+ * primarly for converting a value.</li>
+ * <li>The target type of each explicitly registered converter also can be transitively mapped to
+ * 1) all directly implemented interfaces, 2) all its superclasses (except Object), 3) all the interfaces
+ * implemented by its superclasses. These groups of transitive converters is returned similarly in the
+ * order as mentioned, whereas also here a priority based decreasing ordering is applied.</li>
+ * <li>java.lang wrapper classes and native types are automatically mapped.</li>
+ * <li>If no explicit converters are registered, for Enum types a default implementation is provided that
+ * compares the configuration values with the different enum members defined (cases sensitive mapping).</li>
+ * </ul>
+ * <p>
+ * So given that list above directly registered mappings always are tried first, before any transitive mapping
+ * should be used. Also in all cases @Priority annotations are honored for ordering of the converters in place.
+ * Transitive conversion is supported for all directly implemented interfaces (including inherited ones) and
+ * the inheritance hierarchy (exception Object). Superinterfaces of implemented interfaces are ignored.
+ *
+ * @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(org.apache.tamaya.TypeLiteral)
+ */
+ public <T> List<PropertyConverter<T>> getPropertyConverters(TypeLiteral<T> targetType) {
+ Lock readLock = lock.readLock();
+ List<PropertyConverter<T>> converterList = new ArrayList<>();
+ List<PropertyConverter<T>> converters;
+ // direct mapped converters
+ try {
+ readLock.lock();
+ converters = List.class.cast(this.converters.get(targetType));
+ } finally {
+ readLock.unlock();
+ }
+ if (converters != null) {
+ converterList.addAll(converters);
+ }
+ // transitive converter
+ try {
+ readLock.lock();
+ converters = List.class.cast(this.transitiveConverters.get(targetType));
+ } finally {
+ readLock.unlock();
+ }
+ if (converters != null) {
+ converterList.addAll(converters);
+ }
+ // handling of java.lang wrapper classes
+ TypeLiteral<T> boxedType = mapBoxedType(targetType);
+ if (boxedType != null) {
+ try {
+ readLock.lock();
+ converters = List.class.cast(this.converters.get(boxedType));
+ } finally {
+ readLock.unlock();
+ }
+ if (converters != null) {
+ converterList.addAll(converters);
+ }
+ }
+ if (converterList.isEmpty()) {
+ // adding any converters created on the fly, e.g. for enum types.
+ PropertyConverter<T> defaultConverter = createDefaultPropertyConverter(targetType);
+ if (defaultConverter != null) {
+ register(targetType, defaultConverter);
+ try {
+ readLock.lock();
+ converters = List.class.cast(this.converters.get(targetType));
+ } finally {
+ readLock.unlock();
+ }
+ }
+ if (converters != null) {
+ converterList.addAll(converters);
+ }
+ }
+ return converterList;
+ }
+
+ /**
+ * Maps native types to the corresponding boxed types.
+ *
+ * @param targetType the native type.
+ * @param <T> the type
+ * @return the boxed type, or null.
+ */
+ private <T> TypeLiteral<T> mapBoxedType(TypeLiteral<T> targetType) {
+ Type parameterType = targetType.getType();
+ if (parameterType == int.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Integer.class));
+ }
+ if (parameterType == short.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Short.class));
+ }
+ if (parameterType == byte.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Byte.class));
+ }
+ if (parameterType == long.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Long.class));
+ }
+ if (parameterType == boolean.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Boolean.class));
+ }
+ if (parameterType == char.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Character.class));
+ }
+ if (parameterType == float.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Float.class));
+ }
+ if (parameterType == double.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Double.class));
+ }
+ if (parameterType == int[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Integer[].class));
+ }
+ if (parameterType == short[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Short[].class));
+ }
+ if (parameterType == byte[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Byte[].class));
+ }
+ if (parameterType == long[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Long[].class));
+ }
+ if (parameterType == boolean.class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Boolean.class));
+ }
+ if (parameterType == char[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Character[].class));
+ }
+ if (parameterType == float[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Float[].class));
+ }
+ if (parameterType == double[].class) {
+ return TypeLiteral.class.cast(TypeLiteral.of(Double[].class));
+ }
+ return null;
+ }
+
+ /**
+ * 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 TypeLiteral<T> targetType) {
+ if (Enum.class.isAssignableFrom(targetType.getRawType())) {
+ return new EnumConverter<>(targetType.getRawType());
+ }
+ PropertyConverter<T> converter = null;
+ final Method factoryMethod = getFactoryMethod(targetType.getRawType(), "of", "valueOf", "instanceOf", "getInstance", "from", "fromString", "parse");
+ if (factoryMethod != null) {
+ converter = new DefaultPropertyConverter<>(factoryMethod, targetType.getRawType());
+ }
+ if (converter == null) {
+ final Constructor<T> constr;
+ try {
+ constr = targetType.getRawType().getDeclaredConstructor(String.class);
+ } catch (NoSuchMethodException e) {
+ LOG.log(Level.FINEST, "No matching constrctor for " + targetType, e);
+ return null;
+ }
+ converter = new PropertyConverter<T>() {
+ @Override
+ public T convert(String value, ConversionContext context) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ constr.setAccessible(true);
+ return null;
+ }
+ });
+ return null;
+ }
+ });
+ try {
+ return constr.newInstance(value);
+ } catch (Exception e) {
+ LOG.log(Level.SEVERE, "Error creating new PropertyConverter instance " + targetType, e);
+ }
+ return null;
+ }
+ };
+ }
+ 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.finest("No such factory method found on type: " + type.getName() + ", methodName: " + name);
+ }
+ }
+ return null;
+ }
+
+ private static class DefaultPropertyConverter<T> implements PropertyConverter<T> {
+
+ private Method factoryMethod;
+ private Class<T> targetType;
+
+ DefaultPropertyConverter(Method factoryMethod, Class<T> targetType){
+ this.factoryMethod = Objects.requireNonNull(factoryMethod);
+ this.targetType = Objects.requireNonNull(targetType);
+ }
+
+ @Override
+ public T convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<String -> "+factoryMethod.toGenericString());
+
+ if (!Modifier.isStatic(factoryMethod.getModifiers())) {
+ throw new ConfigException(factoryMethod.toGenericString() +
+ " is not a static method. Only static " +
+ "methods can be used as factory methods.");
+ }
+ try {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ factoryMethod.setAccessible(true);
+ return null;
+ }
+ });
+ Object invoke = factoryMethod.invoke(null, value);
+ return targetType.cast(invoke);
+ } catch (Exception e) {
+ throw new ConfigException("Failed to decode '" + value + "'", e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyFilterComparator.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyFilterComparator.java b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyFilterComparator.java
new file mode 100644
index 0000000..abf22be
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyFilterComparator.java
@@ -0,0 +1,60 @@
+/*
+ * 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.PropertyFilter;
+
+import javax.annotation.Priority;
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Comparator for PropertyFilters based on their priority annotations.
+ */
+public 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);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyFiltering.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyFiltering.java b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyFiltering.java
new file mode 100644
index 0000000..9f84e7c
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertyFiltering.java
@@ -0,0 +1,131 @@
+/*
+ * 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.PropertyFilter;
+import org.apache.tamaya.spi.PropertySource;
+
+import java.util.HashMap;
+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 PropertySource} and {@link PropertyFilter}
+ * instance to evaluate the current Configuration.
+ */
+public final class PropertyFiltering{
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(PropertyFiltering.class.getName());
+ /**
+ * The maximal number of filter cycles performed before aborting.
+ */
+ private static final int MAX_FILTER_LOOPS = 10;
+
+ /**
+ * Private singleton constructor.
+ */
+ private PropertyFiltering(){}
+
+ public static String applyFilter(String key, String unfilteredValue, ConfigurationContext configurationContext) {
+ // 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;
+ }
+
+ public static Map<String, String> applyFilters(Map<String, String> inputMap, ConfigurationContext configurationContext) {
+ Map<String, String> resultMap = new HashMap<>(inputMap);
+ // 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);
+ }
+ else{
+ resultMap.remove(k);
+ }
+ }
+ }
+ 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;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/PropertySourceComparator.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/PropertySourceComparator.java b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertySourceComparator.java
new file mode 100644
index 0000000..24ee1f2
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/PropertySourceComparator.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.internal;
+
+import org.apache.tamaya.spi.PropertySource;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Comparator for ordering of PropertySources based on their ordinal method and class name.
+ */
+public 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 source1.getClass().getName().compareTo(source2.getClass().getName());
+ }
+ }
+
+ @Override
+ public int compare(PropertySource source1, PropertySource source2) {
+ return comparePropertySources(source1, source2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/ReflectionUtil.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/ReflectionUtil.java b/code/core/src/main/java/org/apache/tamaya/core/internal/ReflectionUtil.java
new file mode 100644
index 0000000..6c7a1d2
--- /dev/null
+++ b/code/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/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BigDecimalConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BigDecimalConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BigDecimalConverter.java
new file mode 100644
index 0000000..7057e73
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BigDecimalConverter.java
@@ -0,0 +1,63 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to BigDecimal, the supported format is one of the following:
+ * <ul>
+ * <li>232573527352.76352753</li>
+ * <li>-23257352.735276352753</li>
+ * <li>-0xFFFFFF (integral numbers only)</li>
+ * <li>-0XFFFFAC (integral numbers only)</li>
+ * <li>0xFFFFFF (integral numbers only)</li>
+ * <li>0XFFFFAC (integral numbers only)</li>
+ * </ul>
+ */
+public class BigDecimalConverter implements PropertyConverter<BigDecimal>{
+ /** The logger. */
+ private static final Logger LOG = Logger.getLogger(BigDecimalConverter.class.getName());
+ /** Converter to be used if the format is not directly supported by BigDecimal, e.g. for integral hex values. */
+ private BigIntegerConverter integerConverter = new BigIntegerConverter();
+
+ @Override
+ public BigDecimal convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<bigDecimal> -> new BigDecimal(String)");
+
+ String trimmed = Objects.requireNonNull(value).trim();
+ try{
+ return new BigDecimal(trimmed);
+ } catch(Exception e){
+ LOG.finest("Parsing BigDecimal failed, trying BigInteger for: " + value);
+ BigInteger bigInt = integerConverter.convert(value, context);
+ if(bigInt!=null){
+ return new BigDecimal(bigInt);
+ }
+ LOG.finest("Failed to parse BigDecimal from: " + value);
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BigIntegerConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BigIntegerConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BigIntegerConverter.java
new file mode 100644
index 0000000..57ff2fb
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BigIntegerConverter.java
@@ -0,0 +1,94 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.math.BigInteger;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to BigInteger, the supported format is one of the following:
+ * <ul>
+ * <li>0xFFFFFF</li>
+ * <li>0XFFFFAC</li>
+ * <li>23257352735276352753</li>
+ * <li>-0xFFFFFF</li>
+ * <li>-0XFFFFAC</li>
+ * <li>-23257352735276352753</li>
+ * </ul>
+ */
+public class BigIntegerConverter implements PropertyConverter<BigInteger>{
+
+ /** The logger. */
+ private static final Logger LOG = Logger.getLogger(BigIntegerConverter.class.getName());
+ /** Converter used to decode hex, octal values. */
+ private ByteConverter byteConverter = new ByteConverter();
+
+ @Override
+ public BigInteger convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "[-]0X.. (hex)", "[-]0x... (hex)", "<bigint> -> new BigInteger(bigint)");
+ String trimmed = Objects.requireNonNull(value).trim();
+ if(trimmed.startsWith("0x") || trimmed.startsWith("0X")){
+ LOG.finest("Parsing Hex value to BigInteger: " + value);
+ trimmed = trimmed.substring(2);
+ StringBuilder decimal = new StringBuilder();
+ for(int offset = 0;offset < trimmed.length();offset+=2){
+ if(offset==trimmed.length()-1){
+ LOG.finest("Invalid Hex-Byte-String: " + value);
+ return null;
+ }
+ byte val = byteConverter.convert("0x" + trimmed.substring(offset, offset + 2), context);
+ if(val<10){
+ decimal.append('0').append(val);
+ } else{
+ decimal.append(val);
+ }
+ }
+ return new BigInteger(decimal.toString());
+ } else if(trimmed.startsWith("-0x") || trimmed.startsWith("-0X")){
+ LOG.finest("Parsing Hex value to BigInteger: " + value);
+ trimmed = trimmed.substring(3);
+ StringBuilder decimal = new StringBuilder();
+ for(int offset = 0;offset < trimmed.length();offset+=2){
+ if(offset==trimmed.length()-1){
+ LOG.finest("Invalid Hex-Byte-String: " + trimmed);
+ return null;
+ }
+ byte val = byteConverter.convert("0x" + trimmed.substring(offset, offset + 2), context);
+ if(val<10){
+ decimal.append('0').append(val);
+ } else{
+ decimal.append(val);
+ }
+ }
+ return new BigInteger('-' + decimal.toString());
+ }
+ try{
+ return new BigInteger(trimmed);
+ } catch(Exception e){
+ LOG.log(Level.FINEST, "Failed to parse BigInteger from: " + value, e);
+ return null;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/BooleanConverter.java
new file mode 100644
index 0000000..d0f596d
--- /dev/null
+++ b/code/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.ConversionContext;
+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, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "yes (ignore case)", "y (ignore case)", "true (ignore case)", "t (ignore case)", "no (ignore case)", "n (ignore case)", "false (ignore case)", "f (ignore case)");
+ 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.finest("Unknown boolean value encountered: " + value);
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java
new file mode 100644
index 0000000..ed193d8
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ByteConverter.java
@@ -0,0 +1,71 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Byte, the supported format is one of the following:
+ * <ul>
+ * <li>123 (byte value)</li>
+ * <li>0xFF (byte value)</li>
+ * <li>0XDF (byte value)</li>
+ * <li>0D1 (byte value)</li>
+ * <li>-123 (byte value)</li>
+ * <li>-0xFF (byte value)</li>
+ * <li>-0XDF (byte value)</li>
+ * <li>-0D1 (byte value)</li>
+ * <li>MIN_VALUE (ignoring case)</li>
+ * <li>MIN (ignoring case)</li>
+ * <li>MAX_VALUE (ignoring case)</li>
+ * <li>MAX (ignoring case)</li>
+ * </ul>
+ */
+public class ByteConverter implements PropertyConverter<Byte>{
+
+ private Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public Byte convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(),"<byte>", "MIN_VALUE", "MIN", "MAX_VALUE", "MAX");
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch(trimmed.toUpperCase(Locale.ENGLISH)){
+ case "MIN_VALUE":
+ case "MIN":
+ return Byte.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Byte.MAX_VALUE;
+ default:
+ try{
+ return Byte.decode(trimmed);
+ }
+ catch(Exception e){
+ LOG.log(Level.FINEST, "Unparseable Byte: " + value);
+ return null;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/CharConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/CharConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/CharConverter.java
new file mode 100644
index 0000000..dd6f557
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/CharConverter.java
@@ -0,0 +1,69 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Character, the supported format is one of the following:
+ * <ul>
+ * <li>'a'</li>
+ * <li>123 (byte value)</li>
+ * <li>0xFF (byte value)</li>
+ * <li>0XDF (byte value)</li>
+ * <li>0D1 (byte value)</li>
+ * </ul>
+ */
+public class CharConverter implements PropertyConverter<Character>{
+
+ private static final Logger LOG = Logger.getLogger(CharConverter.class.getName());
+
+ @Override
+ public Character convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(),"\\'<char>\\'", "<char>", "<charNum>");
+ String trimmed = Objects.requireNonNull(value).trim();
+ if(trimmed.isEmpty()){
+ return null;
+ }
+ if(trimmed.startsWith("'")) {
+ try {
+ trimmed = trimmed.substring(1, trimmed.length() - 1);
+ if (trimmed.isEmpty()) {
+ return null;
+ }
+ return trimmed.charAt(0);
+ } catch (Exception e) {
+ LOG.finest("Invalid character format encountered: '" + value + "', valid formats are 'a', 101 and a.");
+ return null;
+ }
+ }
+ try {
+ Integer val = Integer.parseInt(trimmed);
+ return (char) val.shortValue();
+ } catch (Exception e) {
+ LOG.finest("Character format is not numeric: '" + value + "', using first character.");
+ return trimmed.charAt(0);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ClassConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ClassConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ClassConverter.java
new file mode 100644
index 0000000..8fd3cb8
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ClassConverter.java
@@ -0,0 +1,63 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Class, hereby using the following classloaders:
+ * <ul>
+ * <li>The current ThreadContext ClassLoader</li>
+ * <li>The Classloader of this class</li>
+ * <li>The system Classloader</li>
+ * </ul>
+ */
+public class ClassConverter implements PropertyConverter<Class<?>>{
+
+ private Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public Class<?> convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(),"<fullyQualifiedClassName>");
+ String trimmed = Objects.requireNonNull(value).trim();
+ try{
+ return Class.forName(trimmed, false, Thread.currentThread().getContextClassLoader());
+ }
+ catch(Exception e){
+ LOG.finest("Class not found in context CL: " + trimmed);
+ }
+ try{
+ return Class.forName(trimmed, false, ClassConverter.class.getClassLoader());
+ }
+ catch(Exception e){
+ LOG.finest("Class not found in ClassConverter's CL: " + trimmed);
+ }
+ try{
+ return Class.forName(trimmed, false, ClassLoader.getSystemClassLoader());
+ }
+ catch(Exception e){
+ LOG.finest("Class not found in System CL (giving up): " + trimmed);
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/CurrencyConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/CurrencyConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/CurrencyConverter.java
new file mode 100644
index 0000000..50fded7
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/CurrencyConverter.java
@@ -0,0 +1,89 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.util.Currency;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Currency, the supported format is one of the following:
+ * <ul>
+ * <li>CHF (currency code)</li>
+ * <li>123 (numeric currency value >= 0)</li>
+ * <li>DE (ISO 2-digit country)</li>
+ * <li>de_DE, de_DE_123 (Locale)</li>
+ * </ul>
+ */
+public class CurrencyConverter implements PropertyConverter<Currency> {
+
+ private static final Logger LOG = Logger.getLogger(CurrencyConverter.class.getName());
+
+ @Override
+ public Currency convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<currencyCode>, using Locale.ENGLISH", "<numericValue>", "<locale>");
+ String trimmed = Objects.requireNonNull(value).trim();
+ try {
+ return Currency.getInstance(trimmed.toUpperCase(Locale.ENGLISH));
+ } catch (Exception e) {
+ LOG.log(Level.FINEST, "Not a valid textual currency code: " + trimmed + ", checking for numeric...", e);
+ }
+ try {
+ // Check for numeric code
+ Integer numCode = Integer.parseInt(trimmed);
+ for (Currency currency : Currency.getAvailableCurrencies()) {
+ if (currency.getNumericCode() == numCode) {
+ return currency;
+ }
+ }
+ } catch (Exception e) {
+ LOG.log(Level.FINEST, "Not a valid numeric currency code: " + trimmed + ", checking for locale...", e);
+ }
+ try {
+ // Check for numeric code
+ String[] parts = trimmed.split("\\_");
+ Locale locale;
+ switch (parts.length) {
+ case 1:
+ locale = new Locale("", parts[0]);
+ break;
+ case 2:
+ locale = new Locale(parts[0], parts[1]);
+ break;
+ case 3:
+ locale = new Locale(parts[0], parts[1], parts[2]);
+ break;
+ default:
+ locale = null;
+ }
+ if (locale != null) {
+ return Currency.getInstance(locale);
+ }
+ LOG.finest("Not a valid currency: " + trimmed + ", giving up...");
+ } catch (Exception e) {
+ LOG.log(Level.FINEST, "Not a valid country locale for currency: " + trimmed + ", giving up...", e);
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/DoubleConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/DoubleConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/DoubleConverter.java
new file mode 100644
index 0000000..b843d91
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/DoubleConverter.java
@@ -0,0 +1,81 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Double, using the Java number syntax:
+ * (-)?[0-9]*\.[0-9]*. In case of error the value given also is tried being parsed as integral number using
+ * {@link LongConverter}. Additionally the following values are supported:
+ * <ul>
+ * <li>NaN (ignoring case)</li>
+ * <li>POSITIVE_INFINITY (ignoring case)</li>
+ * <li>NEGATIVE_INFINITY (ignoring case)</li>
+ * </ul>
+ */
+public class DoubleConverter implements PropertyConverter<Double> {
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(DoubleConverter.class.getName());
+ /**
+ * The converter used, when floating point parse failed.
+ */
+ private LongConverter integerConverter = new LongConverter();
+
+ @Override
+ public Double convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<double>", "MIN", "MIN_VALUE", "MAX", "MAX_VALUE", "POSITIVE_INFINITY", "NEGATIVE_INFINITY", "NAN");
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch (trimmed.toUpperCase(Locale.ENGLISH)) {
+ case "POSITIVE_INFINITY":
+ return Double.POSITIVE_INFINITY;
+ case "NEGATIVE_INFINITY":
+ return Double.NEGATIVE_INFINITY;
+ case "NAN":
+ return Double.NaN;
+ case "MIN_VALUE":
+ case "MIN":
+ return Double.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Double.MAX_VALUE;
+ default:
+ try {
+ return Double.valueOf(trimmed);
+ } catch (Exception e) {
+ // OK perhaps we have an integral number that must be converted to the double type...
+ LOG.finest("Parsing of double as floating number failed, trying parsing integral" +
+ " number/hex instead...");
+ }
+ Long val = integerConverter.convert(trimmed, context);
+ if(val!=null){
+ return val.doubleValue();
+ }
+ return null;
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/EnumConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/EnumConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/EnumConverter.java
new file mode 100644
index 0000000..1cf68fe
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/EnumConverter.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.internal.converters;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.spi.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Level;
+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, ConversionContext context) {
+ context.addSupportedFormats(getClass(),"<enumValue>");
+ try {
+ return (T) factory.invoke(null, value);
+ } catch (InvocationTargetException | IllegalAccessException e) {
+ LOG.log(Level.FINEST, "Invalid enum value '" + value + "' for " + enumType.getName(), e);
+ }
+ try {
+ return (T) factory.invoke(null, value.toUpperCase(Locale.ENGLISH));
+ } catch (InvocationTargetException | IllegalAccessException e) {
+ LOG.log(Level.FINEST, "Invalid enum value '" + value + "' for " + enumType.getName(), e);
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/FloatConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/FloatConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/FloatConverter.java
new file mode 100644
index 0000000..1cbb273
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/FloatConverter.java
@@ -0,0 +1,81 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Float, using the Java number syntax:
+ * (-)?[0-9]*\.[0-9]*. In case of error the value given also is tried being parsed as integral number using
+ * {@link LongConverter}. Additionally the following values are supported:
+ * <ul>
+ * <li>NaN (ignoring case)</li>
+ * <li>POSITIVE_INFINITY (ignoring case)</li>
+ * <li>NEGATIVE_INFINITY (ignoring case)</li>
+ * </ul>
+ */
+public class FloatConverter implements PropertyConverter<Float> {
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(FloatConverter.class.getName());
+ /**
+ * The converter used, when floating point parse failed.
+ */
+ private IntegerConverter integerConverter = new IntegerConverter();
+
+ @Override
+ public Float convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<float>", "MIN", "MIN_VALUE", "MAX", "MAX_VALUE", "POSITIVE_INFINITY", "NEGATIVE_INFINITY", "NAN");
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch(trimmed.toUpperCase(Locale.ENGLISH)){
+ case "POSITIVE_INFINITY":
+ return Float.POSITIVE_INFINITY;
+ case "NEGATIVE_INFINITY":
+ return Float.NEGATIVE_INFINITY;
+ case "NAN":
+ return Float.NaN;
+ case "MIN_VALUE":
+ case "MIN":
+ return Float.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Float.MAX_VALUE;
+ default:
+ try {
+ return Float.valueOf(trimmed);
+ } catch(Exception e){
+ // OK perhaps we have an integral number that must be converted to the double type...
+ LOG.finest("Parsing of float as floating number failed, trying parsing integral" +
+ " number/hex instead...");
+ }
+ Integer val = integerConverter.convert(trimmed, context);
+ if(val!=null) {
+ return val.floatValue();
+ }
+ LOG.finest("Unparseable float value: " + trimmed);
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/IntegerConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/IntegerConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/IntegerConverter.java
new file mode 100644
index 0000000..313cb63
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/IntegerConverter.java
@@ -0,0 +1,74 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Integer, the supported format is one of the following:
+ * <ul>
+ * <li>123 (byte value)</li>
+ * <li>0xFF (byte value)</li>
+ * <li>0XDF (byte value)</li>
+ * <li>0D1 (byte value)</li>
+ * <li>-123 (byte value)</li>
+ * <li>-0xFF (byte value)</li>
+ * <li>-0XDF (byte value)</li>
+ * <li>-0D1 (byte value)</li>
+ * <li>MIN_VALUE (ignoring case)</li>
+ * <li>MIN (ignoring case)</li>
+ * <li>MAX_VALUE (ignoring case)</li>
+ * <li>MAX (ignoring case)</li>
+ * </ul>
+ */
+public class IntegerConverter implements PropertyConverter<Integer>{
+
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(IntegerConverter.class.getName());
+
+ @Override
+ public Integer convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<int>", "MIN_VALUE", "MIN", "MAX_VALUE", "MAX");
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch(trimmed.toUpperCase(Locale.ENGLISH)){
+ case "MIN_VALUE":
+ case "MIN":
+ return Integer.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Integer.MAX_VALUE;
+ default:
+ try{
+ return Integer.decode(trimmed);
+ }
+ catch(Exception e){
+ LOG.finest("Unparseable Integer value: " + trimmed);
+ return null;
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LongConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LongConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LongConverter.java
new file mode 100644
index 0000000..11cda90
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/LongConverter.java
@@ -0,0 +1,72 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Long, the supported format is one of the following:
+ * <ul>
+ * <li>123 (byte value)</li>
+ * <li>0xFF (byte value)</li>
+ * <li>0XDF (byte value)</li>
+ * <li>0D1 (byte value)</li>
+ * <li>-123 (byte value)</li>
+ * <li>-0xFF (byte value)</li>
+ * <li>-0XDF (byte value)</li>
+ * <li>-0D1 (byte value)</li>
+ * <li>MIN_VALUE (ignoring case)</li>
+ * <li>MIN (ignoring case)</li>
+ * <li>MAX_VALUE (ignoring case)</li>
+ * <li>MAX (ignoring case)</li>
+ * </ul>
+ */
+public class LongConverter implements PropertyConverter<Long>{
+
+ private static final Logger LOGGER = Logger.getLogger(LongConverter.class.getName());
+
+ @Override
+ public Long convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<long>", "MIN", "MIN_VALUE", "MAX", "MAX_VALUE");
+
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch (trimmed.toUpperCase(Locale.ENGLISH)) {
+ case "MIN_VALUE":
+ case "MIN":
+ return Long.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Long.MAX_VALUE;
+ default:
+ try {
+ return Long.decode(trimmed);
+ }
+ catch(Exception e){
+ LOGGER.finest("Unable to parse Long value: " + value);
+ return null;
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/NumberConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/NumberConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/NumberConverter.java
new file mode 100644
index 0000000..83fd3c0
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/NumberConverter.java
@@ -0,0 +1,72 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.math.BigDecimal;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Number. Valid inputs are:
+ * <pre>
+ * POSITIVE_INFINITY -> Double.POSITIVE_INFINITY
+ * NEGATIVE_INFINITY -> Double.NEGATIVE_INFINITY
+ * NaN -> Double.NaN
+ * 0xFFDCD3D2 -> Long
+ * 1234566789.23642327352735273752 -> new BigDecimal(input)
+ * </pre>
+ */
+public class NumberConverter implements PropertyConverter<Number>{
+ /** the logger. */
+ private static final Logger LOGGER = Logger.getLogger(NumberConverter.class.getName());
+ /** Converter used for trying to parse as an integral value. */
+ private LongConverter longConverter = new LongConverter();
+
+ @Override
+ public Number convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<double>, <long>", "0x (hex)", "0X... (hex)", "POSITIVE_INFINITY",
+ "NEGATIVE_INFINITY", "NAN");
+
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch(trimmed.toUpperCase(Locale.ENGLISH)) {
+ case "POSITIVE_INFINITY":
+ return Double.POSITIVE_INFINITY;
+ case "NEGATIVE_INFINITY":
+ return Double.NEGATIVE_INFINITY;
+ case "NAN":
+ return Double.NaN;
+ default:
+ Long lVal = longConverter.convert(trimmed, context);
+ if (lVal != null) {
+ return lVal;
+ }
+ try{
+ return new BigDecimal(trimmed);
+ }
+ catch(Exception e){
+ LOGGER.finest("Unparseable Number: " + trimmed);
+ return null;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ShortConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ShortConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ShortConverter.java
new file mode 100644
index 0000000..dd9ebdd
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/ShortConverter.java
@@ -0,0 +1,72 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.util.Locale;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to Short, the supported format is one of the following:
+ * <ul>
+ * <li>123 (byte value)</li>
+ * <li>0xFF (byte value)</li>
+ * <li>0XDF (byte value)</li>
+ * <li>0D1 (byte value)</li>
+ * <li>-123 (byte value)</li>
+ * <li>-0xFF (byte value)</li>
+ * <li>-0XDF (byte value)</li>
+ * <li>-0D1 (byte value)</li>
+ * <li>MIN_VALUE (ignoring case)</li>
+ * <li>MIN (ignoring case)</li>
+ * <li>MAX_VALUE (ignoring case)</li>
+ * <li>MAX (ignoring case)</li>
+ * </ul>
+ */
+public class ShortConverter implements PropertyConverter<Short>{
+
+ /** the logger. */
+ private static final Logger LOG = Logger.getLogger(ShortConverter.class.getName());
+
+ @Override
+ public Short convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "short", "MIN", "MIN_VALUE", "MAX", "MAX_VALUE");
+ String trimmed = Objects.requireNonNull(value).trim();
+ switch(trimmed.toUpperCase(Locale.ENGLISH)){
+ case "MIN_VALUE":
+ case "MIN":
+ return Short.MIN_VALUE;
+ case "MAX_VALUE":
+ case "MAX":
+ return Short.MAX_VALUE;
+ default:
+ try{
+ return Short.decode(trimmed);
+ }
+ catch(Exception e){
+ LOG.finest("Unparseable Short: " + trimmed);
+ return null;
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URIConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URIConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URIConverter.java
new file mode 100644
index 0000000..74b1337
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URIConverter.java
@@ -0,0 +1,47 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.net.URI;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to URI, using new URI(value).
+ */
+public class URIConverter implements PropertyConverter<URI> {
+
+ private Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public URI convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(), "<uri> -> new URI(uri)");
+ String trimmed = Objects.requireNonNull(value).trim();
+ try {
+ return new URI(trimmed);
+ } catch (Exception e) {
+ LOG.log(Level.FINE, "Unparseable URI: " + trimmed, e);
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/eadbfe97/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URLConverter.java
----------------------------------------------------------------------
diff --git a/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URLConverter.java b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URLConverter.java
new file mode 100644
index 0000000..4125c8a
--- /dev/null
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/converters/URLConverter.java
@@ -0,0 +1,47 @@
+/*
+ * 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.ConversionContext;
+import org.apache.tamaya.spi.PropertyConverter;
+
+import java.net.URL;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Converter, converting from String to URI, using new URL(value).
+ */
+public class URLConverter implements PropertyConverter<URL> {
+
+ private Logger LOG = Logger.getLogger(getClass().getName());
+
+ @Override
+ public URL convert(String value, ConversionContext context) {
+ context.addSupportedFormats(getClass(),"<URL>");
+ String trimmed = Objects.requireNonNull(value).trim();
+ try {
+ return new URL(trimmed);
+ } catch (Exception e) {
+ LOG.log(Level.FINE, "Unparseable URL: " + trimmed, e);
+ }
+ return null;
+ }
+}