You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2015/01/03 12:59:27 UTC

[18/27] incubator-tamaya git commit: TAMAYA-19: Reorganized dormant part for better focus of future discussions.

TAMAYA-19: Reorganized dormant part for better focus of future discussions.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/b56817f7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/b56817f7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/b56817f7

Branch: refs/heads/master
Commit: b56817f7a2754d93aa143c848597e7280484a23f
Parents: 5f58e71
Author: anatole <an...@apache.org>
Authored: Sat Jan 3 09:43:40 2015 +0100
Committer: anatole <an...@apache.org>
Committed: Sat Jan 3 09:43:43 2015 +0100

----------------------------------------------------------------------
 .../core/internal/PropertyConverterManager.java |  240 ++++
 .../logging/AbstractDelegatingLogger.java       |  411 ++++++
 .../core/internal/logging/Log4j2Logger.java     |   97 ++
 .../core/internal/logging/Log4jLogger.java      |  200 +++
 .../core/internal/logging/Slf4jLogger.java      |  181 +++
 .../resource/AbstractFileResolvingResource.java |  230 ++++
 .../core/internal/resource/AntPathMatcher.java  |  779 +++++++++++
 .../internal/resource/ClassPathResource.java    |  254 ++++
 .../internal/resource/FileSystemResource.java   |  220 ++++
 .../internal/resource/InputStreamResource.java  |  122 ++
 .../PathMatchingDefaultResourceLoader.java      |  139 ++
 .../PathMatchingResourcePatternResolver.java    |  731 +++++++++++
 .../core/internal/resource/ReflectionUtils.java |  192 +++
 .../core/internal/resource/ResourceUtils.java   |  257 ++++
 .../core/internal/resource/UrlResource.java     |  274 ++++
 .../core/internal/resource/VfsResource.java     |  134 ++
 .../tamaya/core/internal/resource/VfsUtils.java |  209 +++
 .../core/resources/InputStreamSource.java       |   46 +
 .../apache/tamaya/core/resources/Resource.java  |  186 +++
 .../tamaya/core/resources/ResourceLoader.java   |   87 ++
 .../org/apache/tamaya/core/util/ClassUtils.java | 1074 +++++++++++++++
 .../apache/tamaya/core/util/StringUtils.java    |  463 +++++++
 .../testdata/TestPropertySourceProvider.java    |   32 +
 dormant/api/PropertyMapSupplier.java            |   37 +
 .../java/org/apache/tamaya/ConfigQuery.java     |   37 -
 .../java/org/apache/tamaya/ConfiguredValue.java |  256 ----
 .../java/org/apache/tamaya/DynamicValue.java    |  500 -------
 .../org/apache/tamaya/PropertyMapSupplier.java  |   37 -
 .../tamaya/annotation/ConfiguredProperties.java |   41 -
 .../tamaya/annotation/ConfiguredProperty.java   |   87 --
 .../apache/tamaya/annotation/DefaultAreas.java  |   43 -
 .../apache/tamaya/annotation/DefaultValue.java  |   41 -
 .../apache/tamaya/annotation/LoadPolicy.java    |   48 -
 .../org/apache/tamaya/annotation/NoConfig.java  |   32 -
 .../tamaya/annotation/ObservesConfigChange.java |   38 -
 .../tamaya/annotation/WithConfigOperator.java   |   45 -
 .../tamaya/annotation/WithLoadPolicy.java       |   40 -
 .../tamaya/annotation/WithPropertyAdapter.java  |   45 -
 .../tamaya/spi/ConfigurationFactorySpi.java     |   60 -
 .../org/apache/tamaya/spi/ConfigurationSpi.java |   98 --
 .../apache/tamaya/spi/PropertyAdapterSpi.java   |   72 -
 .../test/java/annottext/AnnotatedConfig.java    |   51 -
 .../java/annottext/AnnotatedFullConfig.java     |   52 -
 .../tamaya/TestConfigServiceSingletonSpi.java   |   90 --
 .../TestPropertyAdaptersSingletonSpi.java       |   99 --
 .../api/src/test/resources/META-INF/beans.xml   |   25 -
 .../org.apache.tamaya.spi.ConfigurationSpi      |   19 -
 .../org.apache.tamaya.spi.PropertyAdapterSpi    |   19 -
 .../AbstractClasspathAwarePropertySource.java   |   82 ++
 .../main/java/old/AbstractPropertySource.java   |   60 +
 .../main/java/old/AggregatedPropertySource.java |   98 ++
 .../src/main/java/old/AggregationPolicy.java    |  133 ++
 .../main/java/old/BuildablePropertySource.java  |   60 +
 .../src/main/java/old/ConfigurationBuilder.java |  375 ++++++
 .../main/java/old/ConfigurationProviderSpi.java |   46 +
 .../main/java/old/ContextualPropertySource.java |  142 ++
 .../main/java/old/DefaultConfigurationSpi.java  |  116 ++
 .../main/java/old/DefaultServiceComparator.java |   85 ++
 .../java/old/DefaultServiceContextProvider.java |  112 ++
 .../main/java/old/DelegatingPropertySource.java |   80 ++
 .../java/old/EnvPropertiesConfigProvider.java   |   54 +
 .../src/main/java/old/MappedConfiguration.java  |   57 +
 dormant/core/src/main/java/old/Orderable.java   |   34 +
 .../core/src/main/java/old/OrdinalProvider.java |   37 +
 .../java/old/PropertyAdapterProviderSpi.java    |   36 +
 .../src/main/java/old/PropertyChangeSet.java    |  169 +++
 .../main/java/old/PropertyChangeSetBuilder.java |  347 +++++
 .../java/old/SubtractingPropertySource.java     |   56 +
 .../old/SystemPropertiesConfigProvider.java     |   54 +
 .../core/config/AbstractConfiguration.java      |    2 +-
 .../tamaya/core/config/ConfigFunctions.java     |    1 +
 .../core/config/ConfigurationBuilder.java       |  374 ------
 .../tamaya/core/config/ConfigurationFormat.java |  111 --
 .../core/config/FreezedConfiguration.java       |   81 --
 .../tamaya/core/config/FrozenConfiguration.java |   81 ++
 .../tamaya/core/config/MappedConfiguration.java |   56 -
 .../apache/tamaya/core/internal/MetaConfig.java |   20 +-
 .../config/DefaultConfigurationSpi.java         |  116 --
 .../config/DefaultPropertyAdapterSpi.java       |  168 ---
 .../config/EnvPropertiesConfigProvider.java     |   54 -
 .../config/FallbackSimpleConfigProvider.java    |   11 +-
 .../internal/config/FileChangeListener.java     |    2 +-
 .../config/FilesPropertiesConfigProvider.java   |    2 +-
 .../config/SystemPropertiesConfigProvider.java  |   54 -
 .../internal/el/DefaultExpressionEvaluator.java |  144 --
 .../el/EnvironmentPropertyResolver.java         |   44 -
 .../internal/el/SystemPropertyResolver.java     |   44 -
 .../format/DefaultConfigurationFormatSpi.java   |   40 -
 .../inject/ConfigChangeCallbackMethod.java      |   67 -
 .../inject/ConfigTemplateInvocationHandler.java |   76 --
 .../internal/inject/ConfigurationInjector.java  |   61 -
 .../core/internal/inject/ConfiguredField.java   |  126 --
 .../internal/inject/ConfiguredSetterMethod.java |  136 --
 .../core/internal/inject/ConfiguredType.java    |  222 ----
 .../core/internal/inject/InjectionUtils.java    |  221 ----
 .../inject/WeakConfigListenerManager.java       |  117 --
 .../logging/AbstractDelegatingLogger.java       |  411 ------
 .../core/internal/logging/Log4j2Logger.java     |   97 --
 .../core/internal/logging/Log4jLogger.java      |  200 ---
 .../core/internal/logging/Slf4jLogger.java      |  181 ---
 .../io/AbstractFileResolvingResource.java       |  221 ----
 .../internal/resources/io/AbstractResource.java |  217 ---
 .../internal/resources/io/AntPathMatcher.java   |  777 -----------
 .../resources/io/ClassPathResource.java         |  252 ----
 .../core/internal/resources/io/ClassUtils.java  | 1232 ------------------
 .../resources/io/DefaultResourceLoader.java     |  138 --
 .../resources/io/FileSystemResource.java        |  220 ----
 .../resources/io/InputStreamResource.java       |  121 --
 .../io/PathMatchingResourcePatternResolver.java |  729 -----------
 .../internal/resources/io/ReflectionUtils.java  |  191 ---
 .../internal/resources/io/ResourceUtils.java    |  350 -----
 .../core/internal/resources/io/StringUtils.java | 1165 -----------------
 .../core/internal/resources/io/UrlResource.java |  263 ----
 .../core/internal/resources/io/VfsResource.java |  134 --
 .../core/internal/resources/io/VfsUtils.java    |  209 ---
 .../internal/resources/io/WritableResource.java |   54 -
 .../AbstractClasspathAwarePropertySource.java   |   82 --
 .../core/properties/AbstractPropertySource.java |   96 --
 .../properties/AggregatedPropertySource.java    |   98 --
 .../core/properties/AggregationPolicy.java      |  133 --
 .../properties/BuildablePropertySource.java     |   60 -
 .../core/properties/ConfigurationFormat.java    |  111 --
 .../properties/ContextualPropertySource.java    |  142 --
 .../properties/DelegatingPropertySource.java    |   79 --
 .../properties/EnvironmentPropertySource.java   |   16 +-
 .../properties/FileSystemPropertySource.java    |   97 --
 .../core/properties/FilteredPropertySource.java |   51 -
 .../core/properties/FreezedPropertySource.java  |   74 --
 .../core/properties/FrozenPropertySource.java   |   35 +-
 .../properties/IntersectingPropertySource.java  |   55 -
 .../core/properties/MapBasedPropertySource.java |   72 +-
 .../core/properties/MappedPropertySource.java   |   53 -
 .../properties/PathBasedPropertySource.java     |   83 --
 .../core/properties/PropertyChangeSet.java      |  169 ---
 .../properties/PropertyChangeSetBuilder.java    |  347 -----
 .../core/properties/PropertySourceBuilder.java  |  477 -------
 .../core/properties/PropertySourceFactory.java  |  287 ----
 .../properties/PropertySourceFunctions.java     |   53 +
 .../properties/ReplacingPropertySource.java     |   75 --
 .../properties/SubtractingPropertySource.java   |   56 -
 .../SystemPropertiesPropertySource.java         |   25 +-
 .../core/properties/URLBasedPropertySource.java |   81 --
 .../properties/ValueFilteredPropertySource.java |   51 -
 .../factories/PropertySourceFactory.java        |  279 ++++
 .../factories/PropertySourcesBuilder.java       |  367 ++++++
 .../ResourcePropertySourceProvider.java         |   70 +
 .../filtered/AggregatedPropertySource.java      |   97 ++
 .../filtered/FilteredPropertySource.java        |   68 +
 .../filtered/IntersectingPropertySource.java    |   55 +
 .../filtered/MappedPropertySource.java          |   67 +
 .../filtered/ValueFilteredPropertySource.java   |   55 +
 .../tamaya/core/resource/InputStreamSource.java |   55 -
 .../apache/tamaya/core/resource/Resource.java   |  124 --
 .../tamaya/core/resource/ResourceLoader.java    |   84 --
 .../tamaya/core/spi/ConfigurationFormatSpi.java |   61 -
 .../core/spi/ConfigurationProviderSpi.java      |   46 -
 .../core/spi/DefaultServiceComparator.java      |   85 --
 .../core/spi/DefaultServiceContextProvider.java |  112 --
 .../tamaya/core/spi/ExpressionEvaluator.java    |   38 -
 .../tamaya/core/spi/ExpressionResolver.java     |   55 -
 .../org/apache/tamaya/core/spi/Orderable.java   |   34 -
 .../apache/tamaya/core/spi/OrdinalProvider.java |   37 -
 .../core/spi/PropertyAdapterProviderSpi.java    |   36 -
 .../tamaya/core/spi/PropertyAdapterService.java |   64 -
 .../services/old.ConfigurationProviderSpi       |   20 +
 .../org.apache.tamaya.core.ConfigurationFormat  |   21 +
 ...e.tamaya.core.properties.ConfigurationFormat |   21 -
 ...g.apache.tamaya.core.resource.ResourceLoader |   20 -
 ....apache.tamaya.core.resources.ResourceLoader |   20 +
 ...che.tamaya.core.spi.ConfigurationProviderSpi |   20 -
 .../org.apache.tamaya.spi.ConfigurationSpi      |    2 +-
 .../org.apache.tamaya.spi.PropertyAdapterSpi    |    2 +-
 ...tionManagerSingletonSpiSingletonSpiTest.java |    6 +-
 .../java/org/apache/tamaya/JavaOneDemo.java     |    4 +-
 .../tamaya/core/config/MutableConfigTest.java   |    2 +-
 .../FilesPropertiesConfigProviderTest.java      |    2 +-
 .../properties/PropertySourceBuilderTest.java   |    4 +-
 .../internal/MutableTestConfigProvider.java     |    4 +-
 .../tamaya/internal/TestConfigProvider.java     |    6 +-
 .../samples/annotations/ConfiguredClass.java    |    8 +-
 .../samples/devops/DeploymentProvider.java      |    4 +-
 .../simple/SimplePropertiesAndCLISample.java    |    4 +-
 .../apache/tamaya/ucs/UC1ReadProperties.java    |    2 +-
 .../apache/tamaya/ucs/UC2CombineProperties.java |    2 +-
 .../services/old.ConfigurationProviderSpi       |   19 +
 ...che.tamaya.core.spi.ConfigurationProviderSpi |   19 -
 .../core/src/test/resources/cfg/autoloaded.xml  |    2 +-
 dormant/core/src/test/resources/cfg/test.xml    |    2 +-
 dormant/modules/integration/cdi/pom.xml         |  178 ---
 .../tamaya/integration/cdi/ConfiguredClass.java |   12 +-
 .../integration/cdi/TestConfigProvider.java     |    6 +-
 dormant/modules/integration/managed/pom.xml     |   71 -
 .../management/ManagedEnvironmentMBean.java     |    4 +-
 dormant/modules/integration/pom.xml             |   40 -
 dormant/modules/metamodels/environment/pom.xml  |   73 --
 .../environment/EnvironmentManagerTest.java     |    2 +-
 dormant/modules/metamodels/pom.xml              |   46 -
 dormant/modules/metamodels/simple/pom.xml       |   73 --
 .../services/old.ConfigurationProviderSpi       |   19 +
 ...che.tamaya.core.spi.ConfigurationProviderSpi |   19 -
 dormant/modules/pom.xml                         |   60 -
 modules/injection/pom.xml                       |   40 +
 .../tamaya/inject/ConfiguredProperties.java     |   41 +
 .../tamaya/inject/ConfiguredProperty.java       |   87 ++
 .../org/apache/tamaya/inject/DefaultAreas.java  |   43 +
 .../org/apache/tamaya/inject/DefaultValue.java  |   41 +
 .../org/apache/tamaya/inject/DynamicValue.java  |  500 +++++++
 .../org/apache/tamaya/inject/LoadPolicy.java    |   48 +
 .../java/org/apache/tamaya/inject/NoConfig.java |   32 +
 .../tamaya/inject/ObservesConfigChange.java     |   38 +
 .../tamaya/inject/WithConfigOperator.java       |   45 +
 .../apache/tamaya/inject/WithLoadPolicy.java    |   40 +
 .../tamaya/inject/WithPropertyAdapter.java      |   45 +
 .../internal/ConfigChangeCallbackMethod.java    |   67 +
 .../ConfigTemplateInvocationHandler.java        |   76 ++
 .../inject/internal/ConfigurationInjector.java  |   61 +
 .../tamaya/inject/internal/ConfiguredField.java |  126 ++
 .../inject/internal/ConfiguredSetterMethod.java |  136 ++
 .../tamaya/inject/internal/ConfiguredType.java  |  222 ++++
 .../tamaya/inject/internal/InjectionUtils.java  |  221 ++++
 .../internal/WeakConfigListenerManager.java     |  117 ++
 .../inject/spi/ConfigurationFactorySpi.java     |   60 +
 .../tamaya/inject/spi/ConfigurationSpi.java     |   98 ++
 .../tamaya/inject/spi/PropertyAdapterSpi.java   |   72 +
 .../test/java/annottext/AnnotatedConfig.java    |   51 +
 .../java/annottext/AnnotatedFullConfig.java     |   52 +
 .../tamaya/TestConfigServiceSingletonSpi.java   |   90 ++
 .../TestPropertyAdaptersSingletonSpi.java       |   99 ++
 .../src/test/resources/META-INF/beans.xml       |   25 +
 .../org.apache.tamaya.spi.ConfigurationSpi      |   19 +
 .../org.apache.tamaya.spi.PropertyAdapterSpi    |   19 +
 modules/integration/pom.xml                     |   39 +
 modules/management/pom.xml                      |   41 +
 modules/metamodels/environment/pom.xml          |   34 +
 modules/metamodels/pom.xml                      |   39 +
 modules/metamodels/simple/pom.xml               |   34 +
 modules/pom.xml                                 |   42 +
 .../tamaya/resolver/ExpressionEvaluator.java    |   38 +
 .../internal/DefaultExpressionEvaluator.java    |  144 ++
 .../internal/EnvironmentPropertyResolver.java   |   44 +
 .../internal/SystemPropertyResolver.java        |   44 +
 .../tamaya/resolver/spi/ExpressionResolver.java |   53 +
 242 files changed, 13435 insertions(+), 15690 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java b/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java
new file mode 100644
index 0000000..a4d5ff6
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/PropertyConverterManager.java
@@ -0,0 +1,240 @@
+/*
+ * 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.Constructor;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Currency;
+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.StampedLock;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.spi.PropertyConverter;
+
+/**
+ * Manager that deals with {@link org.apache.tamaya.spi.PropertyConverter} instances.
+ */
+public class PropertyConverterManager {
+
+	private Map<Class<?>,List<PropertyConverter<?>>> converters = new ConcurrentHashMap<>();
+    private StampedLock lock = new StampedLock();
+
+    /**
+     * Constructor.
+     */
+    public PropertyConverterManager(){
+        initDefaultConverters();
+    }
+
+    /**
+     * Registers the default converters provided out of the box.
+     */
+    protected void initDefaultConverters(){
+        // Add default converters
+        register(char.class, (s) -> s.charAt(0));
+        register(byte.class, Byte::parseByte);
+        register(short.class, Short::parseShort);
+        register(int.class, Integer::parseInt);
+        register(long.class, Long::parseLong);
+        register(boolean.class, Boolean::parseBoolean);
+        register(float.class, Float::parseFloat);
+        register(double.class, Double::parseDouble);
+
+        register(Character.class, (s) -> s.charAt(0));
+        register(Byte.class, Byte::valueOf);
+        register(Short.class, Short::valueOf);
+        register(Integer.class, Integer::valueOf);
+        register(Long.class, Long::valueOf);
+        register(Boolean.class, Boolean::valueOf);
+        register(Float.class, Float::valueOf);
+        register(Double.class, Double::valueOf);
+        register(BigDecimal.class, BigDecimal::new);
+        register(BigInteger.class, BigInteger::new);
+
+        register(Currency.class, Currency::getInstance);
+
+        register(LocalDate.class, LocalDate::parse);
+        register(LocalTime.class, LocalTime::parse);
+        register(LocalDateTime.class, LocalDateTime::parse);
+        register(ZoneId.class, ZoneId::of);
+    }
+
+    /**
+     * 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.asWriteLock();;
+        try{
+            writeLock.lock();
+            List<PropertyConverter<T>> converters = List.class.cast(this.converters.get(targetType));
+            List<PropertyConverter<T>> 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.
+     * @see #createDefaultPropertyConverter(Class)
+     * @return the current map of instantiated and registered converters.
+     */
+    public Map<Class<?>, List<PropertyConverter<?>>> getPropertyConverters(){
+        Lock readLock = lock.asReadLock();
+        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.
+     * @see #createDefaultPropertyConverter(Class)
+     * @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).
+     */
+    public <T> List<PropertyConverter<T>> getPropertyConverters(Class<T> targetType){
+        Lock readLock = lock.asReadLock();
+        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(Class<T> targetType) {
+        PropertyConverter<T> converter = null;
+        Method factoryMethod = getFactoryMethod(targetType, "of", "valueOf", "instanceOf", "getInstance", "from", "parse");
+        if(factoryMethod!=null){
+            converter = (s) -> {
+                try{
+                    factoryMethod.setAccessible(true);
+                    return targetType.cast(factoryMethod.invoke(s));
+                }
+                catch (Exception e){
+                    throw new ConfigException("Failed to decode '"+s+"'", e);
+                }
+            };
+        }
+        if(converter==null) {
+            try {
+                Constructor<T> constr = targetType.getDeclaredConstructor(String.class);
+                converter = (s) -> {
+                    try{
+                        constr.setAccessible(true);
+                        return constr.newInstance(s);
+                    }
+                    catch (Exception e){
+                        throw new ConfigException("Failed to decode '"+s+"'", e);
+                    }
+                };
+            } catch (Exception e) {
+                //X ignore, TODO log finest
+            }
+        }
+        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(Exception e){
+                //X ignore, TODO log finest
+            }
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/logging/AbstractDelegatingLogger.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/logging/AbstractDelegatingLogger.java b/core/src/main/java/org/apache/tamaya/core/internal/logging/AbstractDelegatingLogger.java
new file mode 100644
index 0000000..cc0ac45
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/logging/AbstractDelegatingLogger.java
@@ -0,0 +1,411 @@
+/*
+ * 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.logging;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.logging.*;
+
+/**
+ * java.util.logging.Logger implementation delegating to another framework.
+ * All methods can be used except:
+ * setLevel
+ * addHandler / getHandlers
+ * setParent / getParent
+ * setUseParentHandlers / getUseParentHandlers
+ *
+ * @author gnodet
+ */
+public abstract class AbstractDelegatingLogger extends Logger {
+
+    protected AbstractDelegatingLogger(final String name, final String resourceBundleName) {
+        super(name, resourceBundleName);
+    }
+
+    public void log(final LogRecord record) {
+        if (isLoggable(record.getLevel())) {
+            doLog(record);
+        }
+    }
+
+    public void log(final Level level, final String msg) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            doLog(lr);
+        }
+    }
+
+    public void log(final Level level, final String msg, final Object param1) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            final Object[] params = {param1};
+            lr.setParameters(params);
+            doLog(lr);
+        }
+    }
+
+    public void log(final Level level, final String msg, final Object[] params) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setParameters(params);
+            doLog(lr);
+        }
+    }
+
+    public void log(final Level level, final String msg, final Throwable thrown) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setThrown(thrown);
+            doLog(lr);
+        }
+    }
+
+    public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            doLog(lr);
+        }
+    }
+
+    public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg, final Object param1) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            final Object[] params = {param1};
+            lr.setParameters(params);
+            doLog(lr);
+        }
+    }
+
+    public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg, final Object[] params) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            lr.setParameters(params);
+            doLog(lr);
+        }
+    }
+
+    public void logp(final Level level, final String sourceClass, final String sourceMethod, final String msg, final Throwable thrown) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            lr.setThrown(thrown);
+            doLog(lr);
+        }
+    }
+
+    public void logrb(final Level level, final String sourceClass, final String sourceMethod, final String bundleName, final String msg) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            doLog(lr, bundleName);
+        }
+    }
+
+    public void logrb(final Level level, final String sourceClass, final String sourceMethod,
+                      final String bundleName, final String msg, final Object param1) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            final Object[] params = {param1};
+            lr.setParameters(params);
+            doLog(lr, bundleName);
+        }
+    }
+
+    public void logrb(final Level level, final String sourceClass, final String sourceMethod,
+                      final String bundleName, final String msg, final Object[] params) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            lr.setParameters(params);
+            doLog(lr, bundleName);
+        }
+    }
+
+    public void logrb(final Level level, final String sourceClass, final String sourceMethod,
+                      final String bundleName, final String msg, final Throwable thrown) {
+        if (isLoggable(level)) {
+            final LogRecord lr = new LogRecord(level, msg);
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            lr.setThrown(thrown);
+            doLog(lr, bundleName);
+        }
+    }
+
+    public void entering(final String sourceClass, final String sourceMethod) {
+        if (isLoggable(Level.FINER)) {
+            logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
+        }
+    }
+
+    public void entering(final String sourceClass, final String sourceMethod, final Object param1) {
+        if (isLoggable(Level.FINER)) {
+            final Object[] params = {param1};
+            logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", params);
+        }
+    }
+
+    public void entering(final String sourceClass, final String sourceMethod, final Object[] params) {
+        if (isLoggable(Level.FINER)) {
+            final String msg = "ENTRY";
+            if (params == null) {
+                logp(Level.FINER, sourceClass, sourceMethod, msg);
+                return;
+            }
+            final StringBuilder builder = new StringBuilder(msg);
+            for (int i = 0; i < params.length; i++) {
+                builder.append(" {");
+                builder.append(Integer.toString(i));
+                builder.append("}");
+            }
+            logp(Level.FINER, sourceClass, sourceMethod, builder.toString(), params);
+        }
+    }
+
+    public void exiting(final String sourceClass, final String sourceMethod) {
+        if (isLoggable(Level.FINER)) {
+            logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
+        }
+    }
+
+    public void exiting(final String sourceClass, final String sourceMethod, final Object result) {
+        if (isLoggable(Level.FINER)) {
+            final Object[] params = {result};
+            logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", params);
+        }
+    }
+
+    public void throwing(final String sourceClass, final String sourceMethod, final Throwable thrown) {
+        if (isLoggable(Level.FINER)) {
+            final LogRecord lr = new LogRecord(Level.FINER, "THROW");
+            lr.setSourceClassName(sourceClass);
+            lr.setSourceMethodName(sourceMethod);
+            lr.setThrown(thrown);
+            doLog(lr);
+        }
+    }
+
+    public void severe(final String msg) {
+        if (isLoggable(Level.SEVERE)) {
+            final LogRecord lr = new LogRecord(Level.SEVERE, msg);
+            doLog(lr);
+        }
+    }
+
+    public void warning(final String msg) {
+        if (isLoggable(Level.WARNING)) {
+            final LogRecord lr = new LogRecord(Level.WARNING, msg);
+            doLog(lr);
+        }
+    }
+
+    public void info(final String msg) {
+        if (isLoggable(Level.INFO)) {
+            final LogRecord lr = new LogRecord(Level.INFO, msg);
+            doLog(lr);
+        }
+    }
+
+    public void config(final String msg) {
+        if (isLoggable(Level.CONFIG)) {
+            final LogRecord lr = new LogRecord(Level.CONFIG, msg);
+            doLog(lr);
+        }
+    }
+
+    public void fine(final String msg) {
+        if (isLoggable(Level.FINE)) {
+            final LogRecord lr = new LogRecord(Level.FINE, msg);
+            doLog(lr);
+        }
+    }
+
+    public void finer(final String msg) {
+        if (isLoggable(Level.FINER)) {
+            final LogRecord lr = new LogRecord(Level.FINER, msg);
+            doLog(lr);
+        }
+    }
+
+    public void finest(final String msg) {
+        if (isLoggable(Level.FINEST)) {
+            final LogRecord lr = new LogRecord(Level.FINEST, msg);
+            doLog(lr);
+        }
+    }
+
+    public void setLevel(final Level newLevel) throws SecurityException {
+        throw new UnsupportedOperationException();
+    }
+
+    public abstract Level getLevel();
+
+    public boolean isLoggable(final Level level) {
+        final Level l = getLevel();
+        return level.intValue() >= l.intValue() && l != Level.OFF;
+    }
+
+    protected boolean supportsHandlers() {
+        return false;
+    }
+
+    public synchronized void addHandler(final Handler handler) throws SecurityException {
+        if (supportsHandlers()) {
+            super.addHandler(handler);
+            return;
+        }
+        throw new UnsupportedOperationException();
+    }
+
+    public synchronized void removeHandler(final Handler handler) throws SecurityException {
+        if (supportsHandlers()) {
+            super.removeHandler(handler);
+            return;
+        }
+        throw new UnsupportedOperationException();
+    }
+
+    public synchronized Handler[] getHandlers() {
+        if (supportsHandlers()) {
+            return super.getHandlers();
+        }
+        throw new UnsupportedOperationException();
+    }
+
+    public synchronized void setUseParentHandlers(final boolean useParentHandlers) {
+        if (supportsHandlers()) {
+            super.setUseParentHandlers(useParentHandlers);
+            return;
+        }
+        throw new UnsupportedOperationException();
+    }
+
+    public synchronized boolean getUseParentHandlers() {
+        if (supportsHandlers()) {
+            return super.getUseParentHandlers();
+        }
+        throw new UnsupportedOperationException();
+    }
+
+    public Logger getParent() {
+        return null;
+    }
+
+    public void setParent(final Logger parent) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected void doLog(final LogRecord lr) {
+        lr.setLoggerName(getName());
+        final String rbname = getResourceBundleName();
+        if (rbname != null) {
+            lr.setResourceBundleName(rbname);
+            lr.setResourceBundle(getResourceBundle());
+        }
+        internalLog(lr);
+    }
+
+    protected void doLog(final LogRecord lr, final String rbname) {
+        lr.setLoggerName(getName());
+        if (rbname != null) {
+            lr.setResourceBundleName(rbname);
+            lr.setResourceBundle(loadResourceBundle(rbname));
+        }
+        internalLog(lr);
+    }
+
+    protected void internalLog(final LogRecord record) {
+        final Filter filter = getFilter();
+        if (filter != null && !filter.isLoggable(record)) {
+            return;
+        }
+        final String msg = formatMessage(record);
+        internalLogFormatted(msg, record);
+    }
+
+    protected abstract void internalLogFormatted(String msg, LogRecord record);
+
+    protected String formatMessage(final LogRecord record) {
+        String format = record.getMessage();
+        final ResourceBundle catalog = record.getResourceBundle();
+        if (catalog != null) {
+            try {
+                format = catalog.getString(record.getMessage());
+            } catch (final MissingResourceException ex) {
+                format = record.getMessage();
+            }
+        }
+        try {
+            final Object[] parameters = record.getParameters();
+            if (parameters == null || parameters.length == 0) {
+                return format;
+            }
+            if (format.contains("{0") || format.contains("{1")
+                || format.contains("{2") || format.contains("{3")) {
+                return MessageFormat.format(format, parameters);
+            }
+            return format;
+        } catch (final Exception ex) {
+            return format;
+        }
+    }
+
+    /**
+     * Load the specified resource bundle
+     *
+     * @param resourceBundleName the name current the resource bundle to load, cannot be null
+     * @return the loaded resource bundle.
+     * @throws MissingResourceException If the specified resource bundle can not be loaded.
+     */
+    static ResourceBundle loadResourceBundle(final String resourceBundleName) {
+        // try context class loader to load the resource
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if (null != cl) {
+            try {
+                return ResourceBundle.getBundle(resourceBundleName, Locale.getDefault(), cl);
+            } catch (final MissingResourceException e) {
+                // Failed to load using context classloader, ignore
+            }
+        }
+        // try system class loader to load the resource
+        cl = ClassLoader.getSystemClassLoader();
+        if (null != cl) {
+            try {
+                return ResourceBundle.getBundle(resourceBundleName, Locale.getDefault(), cl);
+            } catch (final MissingResourceException e) {
+                // Failed to load using system classloader, ignore
+            }
+        }
+        return null;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4j2Logger.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4j2Logger.java b/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4j2Logger.java
new file mode 100644
index 0000000..35ae4ab
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4j2Logger.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tamaya.core.internal.logging;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+public class Log4j2Logger extends AbstractDelegatingLogger {
+    private static final Map<Level, org.apache.logging.log4j.Level> TO_LOG4J = new HashMap<>();
+
+    private final Logger log;
+
+    static {
+        //older versions current log4j don't have TRACE, use debug
+//        org.apache.logging.log4j.Level t = org.apache.logging.log4j.Level.DEBUG;
+
+        TO_LOG4J.put(Level.ALL, org.apache.logging.log4j.Level.ALL);
+        TO_LOG4J.put(Level.SEVERE, org.apache.logging.log4j.Level.ERROR);
+        TO_LOG4J.put(Level.WARNING, org.apache.logging.log4j.Level.WARN);
+        TO_LOG4J.put(Level.INFO, org.apache.logging.log4j.Level.INFO);
+        TO_LOG4J.put(Level.CONFIG, org.apache.logging.log4j.Level.DEBUG);
+        TO_LOG4J.put(Level.FINE, org.apache.logging.log4j.Level.DEBUG);
+        TO_LOG4J.put(Level.FINER, org.apache.logging.log4j.Level.TRACE);
+        TO_LOG4J.put(Level.FINEST, org.apache.logging.log4j.Level.TRACE);
+        TO_LOG4J.put(Level.OFF, org.apache.logging.log4j.Level.OFF);
+    }
+
+    public Log4j2Logger(final String name, final String resourceBundleName) {
+        super(name, resourceBundleName);
+        log = LogManager.getLogger(name);
+    }
+
+    public Level getLevel() {
+        final org.apache.logging.log4j.Level l = log.getLevel();
+        if (l != null) {
+            return fromL4J(l);
+        }
+        return null;
+    }
+
+    protected void internalLogFormatted(final String msg, final LogRecord record) {
+        log.log(TO_LOG4J.get(record.getLevel()), msg, record.getThrown());
+    }
+
+
+    private Level fromL4J(final org.apache.logging.log4j.Level l) {
+        Level l2 = null;
+        switch (l.getStandardLevel()) {
+            case ALL:
+                l2 = Level.ALL;
+                break;
+            case FATAL:
+                l2 = Level.SEVERE;
+                break;
+            case ERROR:
+                l2 = Level.SEVERE;
+                break;
+            case WARN:
+                l2 = Level.WARNING;
+                break;
+            case INFO:
+                l2 = Level.INFO;
+                break;
+            case DEBUG:
+                l2 = Level.FINE;
+                break;
+            case OFF:
+                l2 = Level.OFF;
+                break;
+            case TRACE:
+                l2 = Level.FINEST;
+                break;
+            default:
+                l2 = Level.FINE;
+        }
+        return l2;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4jLogger.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4jLogger.java b/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4jLogger.java
new file mode 100644
index 0000000..224378c
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4jLogger.java
@@ -0,0 +1,200 @@
+/*
+ * 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.logging;
+
+import org.apache.log4j.Appender;
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Priority;
+import org.apache.log4j.spi.LoggingEvent;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+/**
+ * java.util.logging.Logger implementation delegating to Log4j.
+ * All methods can be used except:
+ * setLevel
+ * addHandler / getHandlers
+ * setParent / getParent
+ * setUseParentHandlers / getUseParentHandlers
+ *
+ * @author gnodet
+ */
+public class Log4jLogger extends AbstractDelegatingLogger {
+    private static final Map<Level, org.apache.log4j.Level> TO_LOG4J = new HashMap<>();
+    private static final org.apache.log4j.Level TRACE;
+
+    private final Logger log;
+
+    static {
+        //older versions current log4j don't have TRACE, use debug
+        org.apache.log4j.Level t = org.apache.log4j.Level.DEBUG;
+        try {
+            final Field f = org.apache.log4j.Level.class.getField("TRACE");
+            t = (org.apache.log4j.Level) f.get(null);
+        } catch (final Throwable ex) {
+            //ignore, assume old version current log4j
+        }
+        TRACE = t;
+
+        TO_LOG4J.put(Level.ALL, org.apache.log4j.Level.ALL);
+        TO_LOG4J.put(Level.SEVERE, org.apache.log4j.Level.ERROR);
+        TO_LOG4J.put(Level.WARNING, org.apache.log4j.Level.WARN);
+        TO_LOG4J.put(Level.INFO, org.apache.log4j.Level.INFO);
+        TO_LOG4J.put(Level.CONFIG, org.apache.log4j.Level.DEBUG);
+        TO_LOG4J.put(Level.FINE, org.apache.log4j.Level.DEBUG);
+        TO_LOG4J.put(Level.FINER, TRACE);
+        TO_LOG4J.put(Level.FINEST, TRACE);
+        TO_LOG4J.put(Level.OFF, org.apache.log4j.Level.OFF);
+    }
+
+    public Log4jLogger(final String name, final String resourceBundleName) {
+        super(name, resourceBundleName);
+        log = LogManager.getLogger(name);
+    }
+
+    public Level getLevel() {
+        final org.apache.log4j.Level l = log.getEffectiveLevel();
+        if (l != null) {
+            return fromL4J(l);
+        }
+        return null;
+    }
+
+    public void setLevel(final Level newLevel) throws SecurityException {
+        log.setLevel(TO_LOG4J.get(newLevel));
+    }
+
+    public synchronized void addHandler(final Handler handler) throws SecurityException {
+        log.addAppender(new HandlerWrapper(handler));
+    }
+
+    public synchronized void removeHandler(final Handler handler) throws SecurityException {
+        log.removeAppender("HandlerWrapper-" + handler.hashCode());
+    }
+
+    public synchronized Handler[] getHandlers() {
+        final List<Handler> ret = new ArrayList<>();
+        final Enumeration<?> en = log.getAllAppenders();
+        while (en.hasMoreElements()) {
+            final Appender ap = (Appender) en.nextElement();
+            if (ap instanceof HandlerWrapper) {
+                ret.add(((HandlerWrapper) ap).getHandler());
+            }
+        }
+        return ret.toArray(new Handler[ret.size()]);
+    }
+
+    protected void internalLogFormatted(final String msg, final LogRecord record) {
+        log.log(AbstractDelegatingLogger.class.getName(),
+            TO_LOG4J.get(record.getLevel()),
+            msg,
+            record.getThrown());
+    }
+
+
+    private Level fromL4J(final org.apache.log4j.Level l) {
+        Level l2 = null;
+        switch (l.toInt()) {
+            case org.apache.log4j.Level.ALL_INT:
+                l2 = Level.ALL;
+                break;
+            case org.apache.log4j.Level.FATAL_INT:
+                l2 = Level.SEVERE;
+                break;
+            case org.apache.log4j.Level.ERROR_INT:
+                l2 = Level.SEVERE;
+                break;
+            case org.apache.log4j.Level.WARN_INT:
+                l2 = Level.WARNING;
+                break;
+            case org.apache.log4j.Level.INFO_INT:
+                l2 = Level.INFO;
+                break;
+            case org.apache.log4j.Level.DEBUG_INT:
+                l2 = Level.FINE;
+                break;
+            case org.apache.log4j.Level.OFF_INT:
+                l2 = Level.OFF;
+                break;
+            default:
+                if (l.toInt() == TRACE.toInt()) {
+                    l2 = Level.FINEST;
+                }
+        }
+        return l2;
+    }
+
+
+    private class HandlerWrapper extends AppenderSkeleton {
+        Handler handler;
+
+        public HandlerWrapper(final Handler h) {
+            handler = h;
+            name = "HandlerWrapper-" + h.hashCode();
+        }
+
+        public Handler getHandler() {
+            return handler;
+        }
+
+        @Override
+        protected void append(final LoggingEvent event) {
+            final LogRecord lr = new LogRecord(fromL4J(event.getLevel()),
+                event.getMessage().toString());
+            lr.setLoggerName(event.getLoggerName());
+            if (event.getThrowableInformation() != null) {
+                lr.setThrown(event.getThrowableInformation().getThrowable());
+            }
+            final String rbname = getResourceBundleName();
+            if (rbname != null) {
+                lr.setResourceBundleName(rbname);
+                lr.setResourceBundle(getResourceBundle());
+            }
+            handler.publish(lr);
+        }
+
+        public void close() {
+            handler.close();
+            closed = true;
+        }
+
+        public boolean requiresLayout() {
+            return false;
+        }
+
+        @Override
+        public Priority getThreshold() {
+            return TO_LOG4J.get(handler.getLevel());
+        }
+
+        @Override
+        public boolean isAsSevereAsThreshold(final Priority priority) {
+            final Priority p = getThreshold();
+            return p == null || priority.isGreaterOrEqual(p);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/logging/Slf4jLogger.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/logging/Slf4jLogger.java b/core/src/main/java/org/apache/tamaya/core/internal/logging/Slf4jLogger.java
new file mode 100644
index 0000000..a580128
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/logging/Slf4jLogger.java
@@ -0,0 +1,181 @@
+/*
+ * 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.logging;
+
+import org.slf4j.spi.LocationAwareLogger;
+
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+
+/**
+ * <p>
+ * java.util.logging.Logger implementation delegating to SLF4J.
+ * </p>
+ * <p>
+ * Methods {@link java.util.logging.Logger#setParent(Logger)}, {@link java.util.logging.Logger#getParent()},
+ * {@link java.util.logging.Logger#setUseParentHandlers(boolean)} and
+ * {@link java.util.logging.Logger#getUseParentHandlers()} are not overrriden.
+ * </p>
+ * <p>
+ * Level annotation inspired by {@link org.slf4j.bridge.SLF4JBridgeHandler}:
+ * </p>
+ * <p/>
+ * <pre>
+ * FINEST  -&gt; TRACE
+ * FINER   -&gt; DEBUG
+ * FINE    -&gt; DEBUG
+ * CONFIG  -&gt; DEBUG
+ * INFO    -&gt; INFO
+ * WARN ING -&gt; WARN
+ * SEVER   -&gt; ERROR
+ * </pre>
+ */
+public class Slf4jLogger extends AbstractDelegatingLogger {
+
+    private static final String FQCN = AbstractDelegatingLogger.class.getName();
+
+    private final org.slf4j.Logger logger;
+    private LocationAwareLogger locationAwareLogger;
+
+
+    public Slf4jLogger(final String name, final String resourceBundleName) {
+        super(name, resourceBundleName);
+        logger = org.slf4j.LoggerFactory.getLogger(name);
+        if (logger instanceof LocationAwareLogger) {
+            locationAwareLogger = (LocationAwareLogger) logger;
+        }
+    }
+
+    @Override
+    protected boolean supportsHandlers() {
+        return true;
+    }
+
+    @Override
+    public Level getLevel() {
+        final Level level;
+        // Verify fromMap the wider (trace) to the narrower (error)
+        if (logger.isTraceEnabled()) {
+            level = Level.FINEST;
+        } else if (logger.isDebugEnabled()) {
+            // map to the lowest between FINER, FINE and CONFIG
+            level = Level.FINER;
+        } else if (logger.isInfoEnabled()) {
+            level = Level.INFO;
+        } else if (logger.isWarnEnabled()) {
+            level = Level.WARNING;
+        } else if (logger.isErrorEnabled()) {
+            level = Level.SEVERE;
+        } else {
+            level = Level.OFF;
+        }
+        return level;
+    }
+
+    @Override
+    public boolean isLoggable(final Level level) {
+        final int i = level.intValue();
+        if (i == Level.OFF.intValue()) {
+            return false;
+        } else if (i >= Level.SEVERE.intValue()) {
+            return logger.isErrorEnabled();
+        } else if (i >= Level.WARNING.intValue()) {
+            return logger.isWarnEnabled();
+        } else if (i >= Level.INFO.intValue()) {
+            return logger.isInfoEnabled();
+        } else if (i >= Level.FINER.intValue()) {
+            return logger.isDebugEnabled();
+        }
+        return logger.isTraceEnabled();
+    }
+
+
+    @Override
+    protected void internalLogFormatted(final String msg, final LogRecord record) {
+
+        final Level level = record.getLevel();
+        final Throwable t = record.getThrown();
+
+        final Handler[] targets = getHandlers();
+        if (targets != null) {
+            for (final Handler h : targets) {
+                h.publish(record);
+            }
+        }
+        if (!getUseParentHandlers()) {
+            return;
+        }
+
+        /*
+        * As we can not use a "switch ... case" block but only a "if ... else if ..." block, the order current the
+        * comparisons is important. We first try log level FINE then INFO, WARN, FINER, etc
+        */
+        if (Level.FINE.equals(level)) {
+            if (locationAwareLogger == null) {
+                logger.debug(msg, t);
+            } else {
+                locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, t);
+            }
+        } else if (Level.INFO.equals(level)) {
+            if (locationAwareLogger == null) {
+                logger.info(msg, t);
+            } else {
+                locationAwareLogger.log(null, FQCN, LocationAwareLogger.INFO_INT, msg, null, t);
+            }
+        } else if (Level.WARNING.equals(level)) {
+            if (locationAwareLogger == null) {
+                logger.warn(msg, t);
+            } else {
+                locationAwareLogger.log(null, FQCN, LocationAwareLogger.WARN_INT, msg, null, t);
+            }
+        } else if (Level.FINER.equals(level)) {
+            if (locationAwareLogger == null) {
+                logger.trace(msg, t);
+            } else {
+                locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, t);
+            }
+        } else if (Level.FINEST.equals(level)) {
+            if (locationAwareLogger == null) {
+                logger.trace(msg, t);
+            } else {
+                locationAwareLogger.log(null, FQCN, LocationAwareLogger.TRACE_INT, msg, null, t);
+            }
+        } else if (Level.ALL.equals(level)) {
+            // should never occur, all is used to configure java.util.logging
+            // but not accessible by the API Logger.xxx() API
+            if (locationAwareLogger == null) {
+                logger.error(msg, t);
+            } else {
+                locationAwareLogger.log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, null, t);
+            }
+        } else if (Level.SEVERE.equals(level)) {
+            if (locationAwareLogger == null) {
+                logger.error(msg, t);
+            } else {
+                locationAwareLogger.log(null, FQCN, LocationAwareLogger.ERROR_INT, msg, null, t);
+            }
+        } else if (Level.CONFIG.equals(level)) {
+            if (locationAwareLogger == null) {
+                logger.debug(msg, t);
+            } else {
+                locationAwareLogger.log(null, FQCN, LocationAwareLogger.DEBUG_INT, msg, null, t);
+            }
+        }
+        // don't log if Level.OFF
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/resource/AbstractFileResolvingResource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/resource/AbstractFileResolvingResource.java b/core/src/main/java/org/apache/tamaya/core/internal/resource/AbstractFileResolvingResource.java
new file mode 100644
index 0000000..5860923
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/resource/AbstractFileResolvingResource.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tamaya.core.internal.resource;
+
+import org.apache.tamaya.core.resources.Resource;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Objects;
+
+/**
+ * Abstract base class for resources which resolve URLs into File references,
+ * such as {@code UrlResource} or {@link ClassPathResource}.
+ *
+ * <p>Detects the "file" protocol as well as the JBoss "vfs" protocol in URLs,
+ * resolving file system references accordingly.
+ *
+ * @author Juergen Hoeller
+ * @since 3.0
+ */
+abstract class AbstractFileResolvingResource implements Resource {
+
+	/**
+	 * This implementation returns a File reference for the underlying class path
+	 * resource, provided that it refers to a file in the file system.
+	 */
+	@Override
+	public File toFile() throws IOException {
+		URL url = toURL();
+		return ResourceUtils.getFile(url);
+	}
+
+	/**
+	 * This implementation determines the underlying File
+	 * (or jar file, in case current a resource in a jar/zip).
+	 */
+	protected File getFileForLastModifiedCheck() throws IOException {
+		URL url = toURL();
+		if (ResourceUtils.isJarURL(url)) {
+			URL actualUrl = ResourceUtils.extractJarFileURL(url);
+			return ResourceUtils.getFile(actualUrl, "Jar URL");
+		}
+		else {
+			return toFile();
+		}
+	}
+
+	/**
+	 * This implementation returns a File reference for the underlying class path
+	 * resource, provided that it refers to a file in the file system.
+	 * @see ResourceUtils#getFile(java.net.URI, String)
+	 */
+	protected File getFile(URI uri) throws IOException {
+		return ResourceUtils.getFile(uri);
+	}
+
+
+	@Override
+	public boolean exists() {
+		try {
+			URL url = toURL();
+			if (ResourceUtils.isFileURL(url)) {
+				// Proceed with file system resolution...
+				return toFile().exists();
+			}
+			else {
+				// Try a URL connection content-length header...
+				URLConnection con = url.openConnection();
+				customizeConnection(con);
+				HttpURLConnection httpCon =
+						(con instanceof HttpURLConnection ? (HttpURLConnection) con : null);
+				if (httpCon != null) {
+					int code = httpCon.getResponseCode();
+					if (code == HttpURLConnection.HTTP_OK) {
+						return true;
+					}
+					else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
+						return false;
+					}
+				}
+				if (con.getContentLength() >= 0) {
+					return true;
+				}
+				if (httpCon != null) {
+					// no HTTP OK status, and no content-length header: give up
+					httpCon.disconnect();
+					return false;
+				}
+				else {
+					// Fall back to stream existence: can we open the stream?
+					InputStream is = getInputStream();
+					is.close();
+					return true;
+				}
+			}
+		}
+		catch (IOException ex) {
+			return false;
+		}
+	}
+
+	@Override
+	public boolean isReadable() {
+		try {
+			URL url = toURL();
+			if (ResourceUtils.isFileURL(url)) {
+				// Proceed with file system resolution...
+				File file = toFile();
+				return (file.canRead() && !file.isDirectory());
+			}
+			else {
+				return true;
+			}
+		}
+		catch (IOException ex) {
+			return false;
+		}
+	}
+
+	@Override
+	public long contentLength() throws IOException {
+		URL url = toURL();
+		if (ResourceUtils.isFileURL(url)) {
+			// Proceed with file system resolution...
+			return toFile().length();
+		}
+		else {
+			// Try a URL connection content-length header...
+			URLConnection con = url.openConnection();
+			customizeConnection(con);
+			return con.getContentLength();
+		}
+	}
+
+	@Override
+	public long lastModified() throws IOException {
+		URL url = toURL();
+		if (ResourceUtils.isFileURL(url) || ResourceUtils.isJarURL(url)) {
+			// Proceed with file system resolution...
+            long lastModified = getFileForLastModifiedCheck().lastModified();
+            if (lastModified == 0L) {
+                throw new FileNotFoundException(getDisplayName() +
+                        " cannot be resolved in the file system for resolving its last-modified timestamp");
+            }
+            return lastModified;
+		}
+		else {
+			// Try a URL connection last-modified header...
+			URLConnection con = url.openConnection();
+			customizeConnection(con);
+			return con.getLastModified();
+		}
+	}
+
+
+	/**
+	 * Customize the given {@link URLConnection}, obtained in the course current an
+	 * {@link #exists()}, {@link #contentLength()} or {@link #lastModified()} call.
+	 * <p>Calls {@link ResourceUtils#useCachesIfNecessary(URLConnection)} and
+	 * delegates to {@link #customizeConnection(HttpURLConnection)} if possible.
+	 * Can be overridden in subclasses.
+	 * @param con the URLConnection to customize
+	 * @throws IOException if thrown from URLConnection methods
+	 */
+	protected void customizeConnection(URLConnection con) throws IOException {
+		ResourceUtils.useCachesIfNecessary(con);
+		if (con instanceof HttpURLConnection) {
+			customizeConnection((HttpURLConnection) con);
+		}
+	}
+
+	/**
+	 * Customize the given {@link HttpURLConnection}, obtained in the course current an
+	 * {@link #exists()}, {@link #contentLength()} or {@link #lastModified()} call.
+	 * <p>Sets request method "HEAD" by default. Can be overridden in subclasses.
+	 * @param con the HttpURLConnection to customize
+	 * @throws IOException if thrown from HttpURLConnection methods
+	 */
+	protected void customizeConnection(HttpURLConnection con) throws IOException {
+		con.setRequestMethod("HEAD");
+	}
+
+    /**
+     	 * Resolve the given resource URL to a {@code java.io.File},
+     	 * i.e. to a file in the file system.
+     	 * @param resourceUrl the resource URL to resolve
+     	 * @param description a description current the original resource that
+     	 * the URL was created for (for example, a class path location)
+     	 * @return a corresponding File object
+     	 * @throws FileNotFoundException if the URL cannot be resolved to
+     	 * a file in the file system
+     	 */
+	private File getFile(URL resourceUrl, String description) throws FileNotFoundException {
+		Objects.requireNonNull(resourceUrl, "Resource URL must not be null");
+		if (!"file".equals(resourceUrl.getProtocol())) {
+			throw new FileNotFoundException(
+					description + " cannot be resolved to absolute file path " +
+					"because it does not reside in the file system: " + resourceUrl);
+		}
+		try {
+			return new File(ResourceUtils.toURI(resourceUrl).getSchemeSpecificPart());
+		}
+		catch (URISyntaxException ex) {
+			// Fallback for URLs that are not valid URIs (should hardly ever happen).
+			return new File(resourceUrl.getFile());
+		}
+	}
+
+
+}