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

[15/34] incubator-tamaya git commit: first step: move all sources to a 'dormant' directory

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/format/PropertiesFormat.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/format/PropertiesFormat.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/format/PropertiesFormat.java
new file mode 100644
index 0000000..10355ef
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/format/PropertiesFormat.java
@@ -0,0 +1,61 @@
+/*
+ * 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.format;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tamaya.core.resource.Resource;
+import org.apache.tamaya.core.properties.ConfigurationFormat;
+
+public class PropertiesFormat implements ConfigurationFormat{
+
+    private final static Logger LOG = Logger.getLogger(PropertiesFormat.class.getName());
+
+    @Override
+    public String getFormatName(){
+        return "properties";
+    }
+
+    @Override
+	public boolean isAccepted(Resource resource) {
+		String path = resource.getFilename();
+		return path != null && path.endsWith(".properties");
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public Map<String,String> readConfiguration(Resource resource) {
+		if (isAccepted(resource) && resource.exists()) {
+			try (InputStream is = resource.getInputStream()) {
+				Properties p = new Properties();
+				p.load(is);
+				return Map.class.cast(p);
+			} catch (Exception e) {
+                LOG.log(Level.FINEST, e, () -> "Failed to read config from resource: " + resource);
+			}
+		}
+		return Collections.emptyMap();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/format/PropertiesXmlFormat.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/format/PropertiesXmlFormat.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/format/PropertiesXmlFormat.java
new file mode 100644
index 0000000..660c092
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/format/PropertiesXmlFormat.java
@@ -0,0 +1,62 @@
+/*
+ * 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.format;
+
+import org.apache.tamaya.core.resource.Resource;
+import org.apache.tamaya.core.properties.ConfigurationFormat;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+public class PropertiesXmlFormat implements ConfigurationFormat{
+
+    private final static Logger LOG = Logger.getLogger(PropertiesXmlFormat.class.getName());
+
+    @Override
+    public String getFormatName(){
+        return "xml-properties";
+    }
+
+    @Override
+    public boolean isAccepted(Resource resource){
+        String path = resource.getFilename();
+        return path != null && path.endsWith(".xml");
+    }
+
+    @SuppressWarnings("unchecked")
+	@Override
+    public Map<String,String> readConfiguration(Resource resource) {
+        if (isAccepted(resource) && resource.exists()) {
+            try (InputStream is = resource.getInputStream()) {
+                Properties p = new Properties();
+                p.loadFromXML(is);
+                return Map.class.cast(p);
+            } catch (Exception e) {
+                LOG.log(Level.FINEST, e, () -> "Failed to read config from resource: " + resource);
+            }
+        }
+        return Collections.emptyMap();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigChangeCallbackMethod.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigChangeCallbackMethod.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigChangeCallbackMethod.java
new file mode 100644
index 0000000..f929f8e
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigChangeCallbackMethod.java
@@ -0,0 +1,67 @@
+/*
+ * 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.inject;
+
+import org.apache.tamaya.core.properties.PropertyChangeSet;
+import org.apache.tamaya.Configuration;
+
+import java.lang.reflect.Method;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * This class holds a method object that is annotated to be a callback method to be called on configuration
+ * changes.
+ */
+public final class ConfigChangeCallbackMethod {
+
+    private static final Logger LOG = Logger.getLogger(ConfigChangeCallbackMethod.class.getName());
+
+    private Method callbackMethod;
+
+    public ConfigChangeCallbackMethod(Method callbackMethod) {
+        this.callbackMethod = Optional.of(callbackMethod).filter(
+                (m) -> void.class.equals(m.getReturnType()) &&
+                        m.getParameterCount() == 1 &&
+                        m.getParameterTypes()[0].equals(PropertyChangeSet.class)).get();
+    }
+
+    public Consumer<PropertyChangeSet> createConsumer(Object instance, Configuration... configurations){
+        // TODO consider also environment !
+        return event -> {
+            for(Configuration cfg:configurations){
+                if(event.getPropertySource().getName().equals(cfg.getName())){
+                    return;
+                }
+            }
+            call(instance, event);
+        };
+    }
+
+    public void call(Object instance, PropertyChangeSet configChangeEvent) {
+        try {
+            callbackMethod.setAccessible(true);
+            callbackMethod.invoke(instance, configChangeEvent);
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, e, () -> "Error calling ConfigChange callback method " + callbackMethod.getDeclaringClass().getName() + '.' + callbackMethod.getName() + " on " + instance);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigTemplateInvocationHandler.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigTemplateInvocationHandler.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigTemplateInvocationHandler.java
new file mode 100644
index 0000000..ff2c309
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigTemplateInvocationHandler.java
@@ -0,0 +1,76 @@
+/*
+ * 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.inject;
+
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.core.internal.inject.ConfiguredType;
+import org.apache.tamaya.core.internal.inject.InjectionUtils;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+/**
+ * Invocation handler that handles request against a configuration template.
+ */
+public final class ConfigTemplateInvocationHandler implements InvocationHandler {
+
+    /*
+    TODO
+    the given method (in case of a template) can use different caching strategies:
+    1) no caching (always evaluate the values completely) - slow.
+    2) instance caching (a cache per instance).
+    3) classloader caching...
+    4) global shared cache.
+     */
+
+
+    /**
+     * Any overriding configurations.
+     */
+    private Configuration[] configurations;
+    /**
+     * The configured type.
+     */
+    private ConfiguredType type;
+
+    /**
+     * Creates a new handler instance.
+     * @param type           the target type, not null.
+     * @param configurations overriding configurations to be used for evaluating the values for injection into {@code instance}, not null.
+     *                       If no such config is passed, the default configurationa provided by the current
+     *                       registered providers are used.
+     */
+    public ConfigTemplateInvocationHandler(Class<?> type, Configuration... configurations) {
+        this.configurations = Objects.requireNonNull(configurations).clone();
+        this.type = new ConfiguredType(Objects.requireNonNull(type));
+        if (!type.isInterface()) {
+            throw new IllegalArgumentException("Can only proxy interfaces as configuration templates.");
+        }
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        if ("toString".equals(method.getName())) {
+            return "Configured Proxy -> " + this.type.getType().getName();
+        }
+        String configValue = InjectionUtils.getConfigValue(method, configurations);
+        return InjectionUtils.adaptValue(method, method.getReturnType(), configValue);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigurationInjector.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigurationInjector.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigurationInjector.java
new file mode 100644
index 0000000..8a51375
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfigurationInjector.java
@@ -0,0 +1,61 @@
+/*
+ * 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.inject;
+
+import org.apache.tamaya.Configuration;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Simple injector singleton that also registers instances configured using weak references.
+ */
+@SuppressWarnings("rawtypes")
+public final class ConfigurationInjector {
+
+    private static final ConfigurationInjector INSTANCE = new ConfigurationInjector();
+
+	private Map<Class, ConfiguredType> configuredTypes = new ConcurrentHashMap<>();
+
+    /**
+     * Extract the configuration annotation config and registers it per class, for later reuse.
+     * @param type the type to be configured.
+     * @return the configured type registered.
+     */
+    public static ConfiguredType registerType(Class<?> type){
+        return INSTANCE.configuredTypes.computeIfAbsent(type, ConfiguredType::new);
+    }
+
+    /**
+     * Configured the current instance and reigsterd necessary listener to forward config change events as
+     * defined by the current annotations in place.
+     * @param instance the instance to be configured
+     * @param configurations Configuration instances that replace configuration served by services. This allows
+     *                       more easily testing and adaption.
+     */
+    public static void configure(Object instance, Configuration... configurations){
+        Class type = Objects.requireNonNull(instance).getClass();
+        ConfiguredType configuredType = registerType(type);
+        Objects.requireNonNull(configuredType).configure(instance, configurations);
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredField.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredField.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredField.java
new file mode 100644
index 0000000..51c3904
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredField.java
@@ -0,0 +1,126 @@
+/*
+ * 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.inject;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.annotation.ConfiguredProperties;
+import org.apache.tamaya.annotation.ConfiguredProperty;
+import org.apache.tamaya.annotation.DefaultAreas;
+import org.apache.tamaya.core.internal.Utils;
+
+/**
+ * Small class that contains and manages all information anc access to a configured field and a concrete instance current
+ * it (referenced by a weak reference). It also implements all aspects current keys filtering, converting any applying the
+ * final keys by reflection.
+ */
+public class ConfiguredField {
+
+
+    /**
+     * The configured field instance.
+     */
+    private Field annotatedField;
+
+    /**
+     * Models a configured field and provides mechanisms for injection.
+     *
+     * @param field the field instance.
+     */
+    public ConfiguredField(Field field) {
+        Objects.requireNonNull(field);
+        this.annotatedField = field;
+    }
+
+    /**
+     * Evaluate the initial keys fromMap the configuration and applyChanges it to the field.
+     *
+     * @param target the target instance.
+     * @param configurations Configuration instances that replace configuration served by services. This allows
+     *                       more easily testing and adaption.
+     * @throws ConfigException if evaluation or conversion failed.
+     */
+    public void applyInitialValue(Object target, Configuration... configurations) throws ConfigException {
+        String configValue = InjectionUtils.getConfigValue(this.annotatedField, configurations);
+        applyValue(target, configValue, false, configurations);
+    }
+
+
+    /**
+     * This method reapplies a changed configuration keys to the field.
+     *
+     * @param target      the target instance, not null.
+     * @param configValue the new keys to be applied, null will trigger the evaluation current the configured default keys.
+     * @param resolve     set to true, if expression resolution should be applied on the keys passed.
+     * @throws ConfigException if the configuration required could not be resolved or converted.
+     */
+    public void applyValue(Object target, String configValue, boolean resolve, Configuration... configurations) throws ConfigException {
+        Objects.requireNonNull(target);
+        try {
+            if (resolve && configValue != null) {
+                // net step perform exression resolution, if any
+                configValue = Configuration.evaluateValue(configValue, configurations);
+            }
+            // Check for adapter/filter
+            Object value = InjectionUtils.adaptValue(this.annotatedField, this.annotatedField.getType(), configValue);
+            annotatedField.setAccessible(true);
+            annotatedField.set(target, value);
+        } catch (Exception e) {
+            throw new ConfigException("Failed to annotation configured field: " + this.annotatedField.getDeclaringClass()
+                    .getName() + '.' + annotatedField.getName(), e);
+        }
+    }
+
+
+    /**
+     * This method checks if the given (qualified) configuration key is referenced fromMap this field.
+     * This is useful to determine, if a key changed in a configuration should trigger any change events
+     * on the related instances.
+     *
+     * @param key the (qualified) configuration key, not null.
+     * @return true, if the key is referenced.
+     */
+    public boolean matchesKey(String configName, String key) {
+        Collection<ConfiguredProperty> configuredProperties = Utils.getAnnotations(this.annotatedField, ConfiguredProperty.class,
+                ConfiguredProperties.class );
+        for(ConfiguredProperty prop: configuredProperties){
+            String currentName = prop.config().trim();
+            if(currentName.isEmpty()){
+                if(!"default".equals(configName)){
+                    continue;
+                }
+            }
+            else if(!currentName.equals(configName)){
+                continue;
+            }
+            DefaultAreas areasAnnot = this.annotatedField.getDeclaringClass().getAnnotation(DefaultAreas.class);
+            List<String> keys = InjectionUtils.evaluateKeys(this.annotatedField, areasAnnot, prop);
+            if( keys.contains(key)){
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredSetterMethod.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredSetterMethod.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredSetterMethod.java
new file mode 100644
index 0000000..90497ae
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredSetterMethod.java
@@ -0,0 +1,136 @@
+/*
+ * 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.inject;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+import org.apache.tamaya.core.properties.PropertyChangeSet;
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.annotation.*;
+import org.apache.tamaya.core.internal.Utils;
+
+/**
+ * Small class that contains and manages all information and access to a configured field and a concrete instance current
+ * it (referenced by a weak reference). It also implements all aspects current keys filtering, conversions any applying the
+ * final keys by reflection.
+ */
+public class ConfiguredSetterMethod {
+
+    /**
+     * The configured field instance.
+     */
+    private Method setterMethod;
+
+    /**
+     * Models a configured field and provides mechanisms for injection.
+     *
+     * @param method the method instance.
+     */
+    public ConfiguredSetterMethod(Method method) {
+        this.setterMethod = Optional.of(method).filter(
+                (m) -> void.class.equals(m.getReturnType()) &&
+                        m.getParameterCount() == 1).get();
+    }
+
+    public Consumer<PropertyChangeSet> createConsumer(Object instance, Configuration... configurations){
+        // TODO consider environment as well
+        return event -> {
+            for(Configuration cfg:configurations){
+                if(event.getPropertySource().getName().equals(cfg.getName())){
+                    // ignore these changes, since this config is overridden.
+                    return;
+                }
+            }
+            String configValue = InjectionUtils.getConfigValue(setterMethod, configurations);
+            applyValue(instance,configValue, false, configurations);
+        };
+    }
+
+
+    /**
+     * Evaluate the initial keys fromMap the configuration and applyChanges it to the field.
+     *
+     * @param target the target instance.
+     * @param configurations Configuration instances that replace configuration served by services. This allows
+     *                       more easily testing and adaption.
+     * @throws ConfigException if evaluation or conversion failed.
+     */
+    public void applyInitialValue(Object target, Configuration... configurations) throws ConfigException {
+        String configValue = InjectionUtils.getConfigValue(this.setterMethod, configurations);
+        applyValue(target, configValue, false, configurations);
+    }
+
+    /**
+     * This method reapplies a changed configuration keys to the field.
+     *
+     * @param target      the target instance, not null.
+     * @param configValue the new keys to be applied, null will trigger the evaluation current the configured default keys.
+     * @param resolve     set to true, if expression resolution should be applied on the keys passed.
+     * @throws org.apache.tamaya.ConfigException if the configuration required could not be resolved or converted.
+     */
+    public void applyValue(Object target, String configValue, boolean resolve, Configuration... configurations) throws ConfigException {
+        Objects.requireNonNull(target);
+        try {
+            if (resolve && configValue != null) {
+                // net step perform exression resolution, if any
+                configValue = Configuration.evaluateValue(configValue, configurations);
+            }
+            // Check for adapter/filter
+            Object value = InjectionUtils.adaptValue(this.setterMethod, this.setterMethod.getParameterTypes()[0], configValue);
+            setterMethod.setAccessible(true);
+            setterMethod.invoke(target, value);
+        } catch (Exception e) {
+            throw new ConfigException("Failed to annotation configured method: " + this.setterMethod.getDeclaringClass()
+                    .getName() + '.' + setterMethod.getName(), e);
+        }
+    }
+
+
+
+    /**
+     * This method checks if the given (qualified) configuration key is referenced fromMap this field.
+     * This is useful to determine, if a key changed in a configuration should trigger any change events
+     * on the related instances.
+     *
+     * @param key the (qualified) configuration key, not null.
+     * @return true, if the key is referenced.
+     */
+    public boolean matchesKey(String key) {
+        DefaultAreas areasAnnot = this.setterMethod.getDeclaringClass().getAnnotation(DefaultAreas.class);
+        Collection<ConfiguredProperty> configuredProperties =
+                Utils.getAnnotations(this.setterMethod, ConfiguredProperty.class, ConfiguredProperties.class);
+        for(ConfiguredProperty prop: configuredProperties) {
+            if (InjectionUtils.evaluateKeys(this.setterMethod, areasAnnot, prop).contains(key)) {
+                return true;
+            }
+        }
+        if (InjectionUtils.evaluateKeys(this.setterMethod, areasAnnot).contains(key)) {
+            return true;
+        }
+        return false;
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredType.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredType.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredType.java
new file mode 100644
index 0000000..879d54a
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/ConfiguredType.java
@@ -0,0 +1,222 @@
+/*
+ * 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.inject;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.*;
+
+import org.apache.tamaya.core.properties.PropertyChangeSet;
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.PropertySource;
+import org.apache.tamaya.annotation.*;
+import org.apache.tamaya.core.internal.Utils;
+
+/**
+ * Structure that contains and manages configuration related things for a configured type registered.
+ * Created by Anatole on 03.10.2014.
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class ConfiguredType {
+    /**
+     * A list with all annotated instance variables.
+     */
+    private List<ConfiguredField> configuredFields = new ArrayList<>();
+    /**
+     * A list with all annotated methods (templates).
+     */
+    private List<ConfiguredSetterMethod> configuredSetterMethods = new ArrayList<>();
+    /**
+     * A list with all callback methods listening to config changes.
+     */
+    private List<ConfigChangeCallbackMethod> callbackMethods = new ArrayList<>();
+    /**
+     * The basic type.
+     */
+    private Class type;
+
+    /**
+     * Creates an instance of this class hereby evaluating the config annotations given for later effective
+     * injection (configuration) of instances.
+     *
+     * @param type the instance type.
+     */
+
+    public ConfiguredType(Class type) {
+        this.type = Objects.requireNonNull(type);
+        initFields(type);
+        initMethods(type);
+    }
+
+    private void initFields(Class type) {
+        for (Field f : type.getDeclaredFields()) {
+            if (f.isAnnotationPresent(NoConfig.class)) {
+                continue;
+            }
+            try {
+                ConfiguredField configuredField = new ConfiguredField(f);
+                configuredFields.add(configuredField);
+            } catch (Exception e) {
+                throw new ConfigException("Failed to initialized configured field: " +
+                        f.getDeclaringClass().getName() + '.' + f.getName(), e);
+            }
+        }
+    }
+
+    private void initMethods(Class type) {
+        // TODO revisit this logic here...
+        for (Method m : type.getDeclaredMethods()) {
+            if (m.isAnnotationPresent(NoConfig.class)) {
+                continue;
+            }
+            ObservesConfigChange mAnnot = m.getAnnotation(ObservesConfigChange.class);
+            Collection<ConfiguredProperty> propertiesAnnots = Utils.getAnnotations(m, ConfiguredProperty.class, ConfiguredProperties.class);
+            if (type.isInterface()) {
+                // it is a template
+                if (mAnnot != null) {
+                    if (m.isDefault()) {
+                        addObserverMethod(m);
+                    }
+                } else {
+                    if (m.isDefault()) {
+                        addPropertySetter(m, propertiesAnnots);
+                    }
+                }
+            } else {
+                if (mAnnot != null) {
+                    addObserverMethod(m);
+                } else {
+                    addPropertySetter(m, propertiesAnnots);
+                }
+            }
+        }
+    }
+
+    private boolean addPropertySetter(Method m, Collection<ConfiguredProperty> propertiesAnnots) {
+        if (!propertiesAnnots.isEmpty()) {
+            if (m.getParameterTypes().length == 0) {
+                // getter method
+                Class<?> returnType = m.getReturnType();
+                if (!void.class.equals(returnType)) {
+                    try {
+                        configuredSetterMethods.add(new ConfiguredSetterMethod(m));
+                        return true;
+                    } catch (Exception e) {
+                        throw new ConfigException("Failed to initialized configured setter method: " +
+                                m.getDeclaringClass().getName() + '.' + m.getName(), e);
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+
+
+    private void addObserverMethod(Method m) {
+        if (m.getParameterTypes().length != 1) {
+            return;
+        }
+        if (!m.getParameterTypes()[0].equals(PropertyChangeSet.class)) {
+            return;
+        }
+        if (!void.class.equals(m.getReturnType())) {
+            return;
+        }
+        try {
+            this.callbackMethods.add(new ConfigChangeCallbackMethod(m));
+        } catch (Exception e) {
+            throw new ConfigException("Failed to initialized configured callback method: " +
+                    m.getDeclaringClass().getName() + '.' + m.getName(), e);
+        }
+    }
+
+
+    /**
+     * Method called to configure an instance.
+     *
+     * @param instance       The instance to be configured.
+     * @param configurations Configuration instances that replace configuration served by services. This allows
+     *                       more easily testing and adaption.
+     */
+    public void configure(Object instance, Configuration... configurations) {
+        for (ConfiguredField field : configuredFields) {
+            field.applyInitialValue(instance, configurations);
+        }
+        for (ConfiguredSetterMethod method : configuredSetterMethods) {
+            method.applyInitialValue(instance, configurations);
+            // TODO, if method should be recalled on changes, corresponding callbacks could be registered here
+            WeakConfigListenerManager.of().registerConsumer(instance, method.createConsumer(instance, configurations));
+        }
+        // Register callbacks for this intance (weakly)
+        for (ConfigChangeCallbackMethod callback : callbackMethods) {
+            WeakConfigListenerManager.of().registerConsumer(instance, callback.createConsumer(instance, configurations));
+        }
+    }
+
+
+    private String getName(Object source) {
+        if (source instanceof PropertySource) {
+            PropertySource ps = (PropertySource) source;
+            return ps.getName();
+        }
+        return "N/A";
+    }
+
+
+    public boolean isConfiguredBy(Configuration configuration) {
+        // TODO implement this
+        return true;
+    }
+
+    public static boolean isConfigured(Class type) {
+        if (type.getAnnotation(DefaultAreas.class) != null) {
+            return true;
+        }
+        // if no class level annotation is there we might have field level annotations only
+        for (Field field : type.getDeclaredFields()) {
+            if (field.isAnnotationPresent(ConfiguredProperties.class)) {
+                return true;
+            }
+        }
+        // if no class level annotation is there we might have method level annotations only
+        for (Method method : type.getDeclaredMethods()) {
+            if (method.isAnnotationPresent(ConfiguredProperties.class)) {
+                return true;
+            }
+        }
+        for (Field field : type.getDeclaredFields()) {
+            if (field.isAnnotationPresent(ConfiguredProperty.class)) {
+                return true;
+            }
+        }
+        // if no class level annotation is there we might have method level annotations only
+        for (Method method : type.getDeclaredMethods()) {
+            if (method.isAnnotationPresent(ConfiguredProperty.class)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Class getType() {
+        return this.type;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/InjectionUtils.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/InjectionUtils.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/InjectionUtils.java
new file mode 100644
index 0000000..d80ee80
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/InjectionUtils.java
@@ -0,0 +1,221 @@
+package org.apache.tamaya.core.internal.inject;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.PropertyAdapter;
+import org.apache.tamaya.annotation.*;
+import org.apache.tamaya.annotation.WithPropertyAdapter;
+import org.apache.tamaya.core.internal.Utils;
+import org.apache.tamaya.spi.PropertyAdapterSpi;
+
+/**
+ * Created by Anatole on 19.12.2014.
+ */
+@SuppressWarnings("unchecked")
+final class InjectionUtils {
+
+    private InjectionUtils(){}
+
+    /**
+     * This method evaluates the {@link org.apache.tamaya.Configuration} that currently is valid for the given target field/method.
+     *
+     * @return the {@link org.apache.tamaya.Configuration} instance to be used, never null.
+     */
+    public static Configuration getConfiguration(ConfiguredProperty prop, Configuration... configuration) {
+        String name = prop.config();
+        if (name != null && !name.trim().isEmpty()) {
+            return Configuration.current(name.trim());
+        }
+        return Configuration.current();
+    }
+
+    /**
+     * Evaluates all absolute configuration key based on the annotations found on a class.
+     *
+     * @param areasAnnot          the (optional) annotation definining areas to be looked up.
+     * @param propertyAnnotation  the annotation on field/method level that may defined one or
+     *                            several keys to be looked up (in absolute or relative form).
+     * @return the list current keys in order how they should be processed/looked up.
+     */
+    public static List<String> evaluateKeys(Member member, DefaultAreas areasAnnot, ConfiguredProperty propertyAnnotation) {
+        List<String> keys = new ArrayList<>(Arrays.asList(propertyAnnotation.keys()));
+        if (keys.isEmpty()) //noinspection UnusedAssignment
+            keys.add(member.getName());
+        ListIterator<String> iterator = keys.listIterator();
+        while (iterator.hasNext()) {
+            String next = iterator.next();
+            if (next.startsWith("[") && next.endsWith("]")) {
+                // absolute key, strip away brackets, take key as is
+                iterator.set(next.substring(1, next.length() - 1));
+            } else {
+                if (areasAnnot != null) {
+                    // Remove original entry, since it will be replaced with prefixed entries
+                    iterator.remove();
+                    // Add prefixed entries, including absolute (root) entry for "" area keys.
+                    for (String area : areasAnnot.value()) {
+                        iterator.add(area.isEmpty() ? next : area + '.' + next);
+                    }
+                }
+            }
+        }
+        return keys;
+    }
+
+    /**
+     * Evaluates all absolute configuration key based on the member name found.
+     *
+     * @param areasAnnot          the (optional) annotation definining areas to be looked up.
+     * @return the list current keys in order how they should be processed/looked up.
+     */
+    public static List<String> evaluateKeys(Member member, DefaultAreas areasAnnot) {
+        List<String> keys = new ArrayList<>();
+        String name = member.getName();
+        String mainKey;
+        if(name.startsWith("get") || name.startsWith("set")){
+            mainKey = Character.toLowerCase(name.charAt(3)) + name.substring(4);
+        }
+        else{
+            mainKey = Character.toLowerCase(name.charAt(0)) + name.substring(1);
+        }
+        keys.add(mainKey);
+        if (areasAnnot != null) {
+            // Add prefixed entries, including absolute (root) entry for "" area keys.
+            for (String area : areasAnnot.value()) {
+                if(!area.isEmpty()) {
+                    keys.add(area + '.' + mainKey);
+                }
+            }
+        }
+        else{ // add package name
+            keys.add(member.getDeclaringClass().getName()+'.'+mainKey);
+        }
+        return keys;
+    }
+
+    /**
+     * Internally evaluated the current valid configuration keys based on the given annotations present.
+     *
+     * @return the keys to be returned, or null.
+     */
+    public static String getConfigValue(Method method, Configuration... configurations) {
+        DefaultAreas areasAnnot = method.getDeclaringClass().getAnnotation(DefaultAreas.class);
+        WithLoadPolicy loadPolicy = Utils.getAnnotation(WithLoadPolicy.class, method, method.getDeclaringClass());
+        return getConfigValueInternal(method, areasAnnot, loadPolicy, configurations);
+    }
+
+
+    /**
+     * Internally evaluated the current valid configuration keys based on the given annotations present.
+     *
+     * @return the keys to be returned, or null.
+     */
+    public static String getConfigValue(Field field, Configuration... configurations) {
+        DefaultAreas areasAnnot = field.getDeclaringClass().getAnnotation(DefaultAreas.class);
+        WithLoadPolicy loadPolicy = Utils.getAnnotation(WithLoadPolicy.class, field, field.getDeclaringClass());
+        return getConfigValueInternal(field, areasAnnot, loadPolicy, configurations);
+    }
+
+    /**
+     * Internally evaluated the current valid configuration keys based on the given annotations present.
+     *
+     * @return the keys to be returned, or null.
+     */
+    private static String getConfigValueInternal(AnnotatedElement element, DefaultAreas areasAnnot, WithLoadPolicy loadPolicy, Configuration... configurations) {
+        Collection<ConfiguredProperty> configuredProperties = Utils.getAnnotations(
+                element, ConfiguredProperty.class, ConfiguredProperties.class);
+        DefaultValue defaultAnnot = element.getAnnotation(DefaultValue.class);
+        String configValue = null;
+        if(configuredProperties.isEmpty()){
+            List<String> keys = InjectionUtils.evaluateKeys((Member)element, areasAnnot);
+            Configuration config = InjectionUtils.getConfiguration("default", configurations);
+            configValue = evaluteConfigValue(configValue, keys, config);
+        }
+        else {
+            for (ConfiguredProperty prop : configuredProperties) {
+                List<String> keys = InjectionUtils.evaluateKeys((Member) element, areasAnnot, prop);
+                Configuration config = InjectionUtils.getConfiguration(prop, configurations);
+                configValue = evaluteConfigValue(configValue, keys, config);
+            }
+        }
+        if (configValue == null && defaultAnnot != null) {
+            return defaultAnnot.value();
+        }
+        return configValue;
+    }
+
+    private static String evaluteConfigValue(String configValue, List<String> keys, Configuration config) {
+        for (String key : keys) {
+            configValue = config.get(key).orElse(null);
+            if (configValue != null) {
+                break;
+            }
+        }
+        if (configValue != null) {
+            // net step perform expression resolution, if any
+            configValue =  Configuration.evaluateValue(configValue, config);
+        }
+        return configValue;
+    }
+
+
+    @SuppressWarnings("rawtypes")
+	public static <T> T adaptValue(AnnotatedElement element, Class<T> targetType, String configValue){
+        try {
+            // Check for adapter/filter
+//            T adaptedValue = null;
+            WithPropertyAdapter codecAnnot = element.getAnnotation(WithPropertyAdapter.class);
+            Class<? extends PropertyAdapter> codecType;
+            if (codecAnnot != null) {
+                codecType = codecAnnot.value();
+                if (!codecType.equals(PropertyAdapter.class)) {
+                    // TODO cache here...
+//                    Codec<String> codec = codecType.newInstance();
+//                    adaptedValue = (T) codec.adapt(configValue);
+                }
+            }
+            if (String.class.equals(targetType)) {
+                 return (T)configValue;
+            } else {
+                PropertyAdapter<?> adapter = PropertyAdapter.getInstance(targetType);
+                 return (T)adapter.adapt(configValue);
+            }
+        } catch (Exception e) {
+            throw new ConfigException("Failed to annotate configured member: " + element, e);
+        }
+    }
+
+    /**
+     * This method evaluates the {@link Configuration} that currently is valid for the given target field/method.
+     * @param configurations Configuration instances that replace configuration served by services. This allows
+     *                       more easily testing and adaption.
+     * @return the {@link Configuration} instance to be used, never null.
+     */
+    public static Configuration getConfiguration(String name, Configuration... configurations) {
+        if(name!=null) {
+            for(Configuration conf: configurations){
+                if(name.equals(conf.getName())){
+                    return conf;
+                }
+            }
+            return Configuration.current(name);
+        }
+        else{
+            for(Configuration conf: configurations){
+                if("default".equals(conf.getName())){
+                    return conf;
+                }
+            }
+        }
+        return Configuration.current();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/WeakConfigListenerManager.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/WeakConfigListenerManager.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/WeakConfigListenerManager.java
new file mode 100644
index 0000000..e9b9ec3
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/inject/WeakConfigListenerManager.java
@@ -0,0 +1,117 @@
+/*
+ * 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.inject;
+
+import org.apache.tamaya.core.properties.PropertyChangeSet;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.StampedLock;
+import java.util.function.Consumer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Simple listener container that only holds weak references on the listeners.
+ */
+public final class WeakConfigListenerManager{
+
+    private static final WeakConfigListenerManager INSTANCE = new WeakConfigListenerManager();
+
+    private static final Logger LOG = Logger.getLogger(WeakConfigListenerManager.class.getName());
+    private StampedLock lock = new StampedLock();
+    private Map<Object,Consumer<PropertyChangeSet>> listenerReferences = new WeakHashMap<>();
+
+    /** Private singleton constructor. */
+    private WeakConfigListenerManager(){}
+
+    public static WeakConfigListenerManager of(){
+        return INSTANCE;
+    }
+
+    /**
+     * Registers the given consumer for the instance. If a consumer already exists for this instance the given
+     * consumer is appended.
+     * @param instance the instance, not null.
+     * @param listener the consumer.
+     */
+    public void registerConsumer(Object instance, Consumer<PropertyChangeSet> listener){
+        Lock writeLock = lock.asWriteLock();
+        try {
+            writeLock.lock();
+            Consumer<PropertyChangeSet> l = listenerReferences.get(instance);
+            if (l == null) {
+                listenerReferences.put(instance, listener);
+            } else {
+                listenerReferences.put(instance, l.andThen(listener));
+            }
+        }
+        finally{
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * Unregisters all consumers for the given instance.
+     * @param instance the instance, not null.
+     */
+    public void unregisterConsumer(Object instance) {
+        Lock writeLock = lock.asWriteLock();
+        try {
+            writeLock.lock();
+            listenerReferences.remove(instance);
+        }
+        finally{
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * Publishes a change event to all consumers registered.
+     * @param change the change event, not null.
+     */
+    public void publishChangeEvent(PropertyChangeSet change){
+        Lock readLock = lock.asReadLock();
+        try{
+            readLock.lock();
+            listenerReferences.values().parallelStream().forEach(l -> {
+                try{
+                    l.accept(change);
+                }
+                catch(Exception e){
+                    LOG.log(Level.SEVERE, "ConfigChangeListener failed: " + l.getClass().getName(), e);
+                }
+            });
+        }
+        finally{
+            readLock.unlock();
+        }
+    }
+
+
+    @Override
+    public String toString(){
+        return "WeakConfigListenerManager{" +
+                "listenerReferences=" + listenerReferences +
+                '}';
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/AbstractDelegatingLogger.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/AbstractDelegatingLogger.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/AbstractDelegatingLogger.java
new file mode 100644
index 0000000..cc0ac45
--- /dev/null
+++ b/dormant/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/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4j2Logger.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4j2Logger.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4j2Logger.java
new file mode 100644
index 0000000..35ae4ab
--- /dev/null
+++ b/dormant/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/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4jLogger.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4jLogger.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/Log4jLogger.java
new file mode 100644
index 0000000..224378c
--- /dev/null
+++ b/dormant/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/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/Slf4jLogger.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/Slf4jLogger.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/logging/Slf4jLogger.java
new file mode 100644
index 0000000..a580128
--- /dev/null
+++ b/dormant/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/d9964c64/dormant/core/src/main/java/org/apache/tamaya/core/internal/resources/AntPathClasspathResolver.java
----------------------------------------------------------------------
diff --git a/dormant/core/src/main/java/org/apache/tamaya/core/internal/resources/AntPathClasspathResolver.java b/dormant/core/src/main/java/org/apache/tamaya/core/internal/resources/AntPathClasspathResolver.java
new file mode 100644
index 0000000..38a9644
--- /dev/null
+++ b/dormant/core/src/main/java/org/apache/tamaya/core/internal/resources/AntPathClasspathResolver.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.resources;
+
+import org.apache.tamaya.core.internal.resources.io.PathMatchingResourcePatternResolver;
+import org.apache.tamaya.core.spi.PathResolver;
+import org.apache.tamaya.core.resource.Resource;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class AntPathClasspathResolver implements PathResolver {
+
+    private static final Logger LOG = Logger.getLogger(AntPathClasspathResolver.class.getName());
+
+    @Override
+    public String getResolverId(){
+        return "classpath";
+    }
+
+    @Override
+    public Collection<Resource> resolve(ClassLoader classLoader, Collection<String> expressions){
+        PathMatchingResourcePatternResolver resolver = PathMatchingResourcePatternResolver.of(classLoader);
+        List<Resource> result = new ArrayList<>();
+        expressions.forEach((expression) -> {
+            try {
+                Resource[] resources = resolver.getResources(expression);
+                for (Resource res : resources) {
+                    try {
+                        result.add(res);
+                    } catch (Exception e) {
+                        LOG.log(Level.FINEST, "URI could not be extracted from Resource: " + res.toString(), e);
+                    }
+                }
+            }
+            catch(IOException e){
+                LOG.log(Level.FINE, "Failed to load resource expression: " + expression, e);
+            }
+        });
+        return result;
+    }
+}