Repository: incubator-tamaya
Updated Branches:
  refs/heads/master c2aee961b -> 9c073a739


TAMAYA-210: Added additional resource location logic. Tested and implemented 
especially with OSGI. Added create method.


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

Branch: refs/heads/master
Commit: b31278a39be485a5b72d50408e3a2d2e557f1008
Parents: c2aee96
Author: anatole <anat...@apache.org>
Authored: Wed Dec 21 16:41:02 2016 +0100
Committer: anatole <anat...@apache.org>
Committed: Wed Dec 21 16:41:02 2016 +0100

----------------------------------------------------------------------
 .../org/apache/tamaya/spi/ServiceContext.java   |  35 +++++++
 .../tamaya/spi/ServiceContextManagerTest.java   |  18 ++++
 .../apache/tamaya/spi/ServiceContextTest.java   |  22 +++-
 .../apache/tamaya/spi/TestServiceContext.java   |  38 ++++---
 code/core/bnd.bnd                               |   4 +-
 .../core/internal/DefaultServiceContext.java    |  63 +++++++++--
 .../tamaya/core/internal/OSGIActivator.java     |   5 +-
 .../core/internal/OSGIServiceContext.java       |  83 ++++++++++++---
 .../tamaya/core/internal/OSGIServiceLoader.java | 104 ++++++++++++++++---
 .../internal/PriorityServiceComparator.java     |   3 +
 .../provider/JavaConfigurationProvider.java     |  16 +--
 pom.xml                                         |   1 +
 12 files changed, 324 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
----------------------------------------------------------------------
diff --git a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java 
b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
index c66b87b..9f1d28e 100644
--- a/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
+++ b/code/api/src/main/java/org/apache/tamaya/spi/ServiceContext.java
@@ -18,6 +18,9 @@
  */
 package org.apache.tamaya.spi;
 
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
 import java.util.List;
 
 
@@ -45,6 +48,19 @@ public interface ServiceContext {
     <T> T getService(Class<T> serviceType);
 
     /**
+     * Factory method to create a type, hereby a new instance is created on 
each access.
+     * If multiple implementations for the very serviceType exist then
+     * the one with the highest {@link javax.annotation.Priority} will be used 
as the base
+     * for creating subsequent instances.
+     *
+     * @param <T> the type of the service type.
+     * @param serviceType the service type.
+     * @return The new instance to be used, or {@code null}
+     * @throws org.apache.tamaya.ConfigException if there are multiple service 
implementations with the maximum priority.
+     */
+    <T> T create(Class<T> serviceType);
+
+    /**
      * Access a list current services, given its type. The bootstrap mechanism 
should
      * order the instance for precedence, hereby the most significant should be
      * first in order.
@@ -56,4 +72,23 @@ public interface ServiceContext {
      */
      <T> List<T> getServices(Class<T> serviceType);
 
+    /**
+     * Loads resources from the current runtime context. This method allows to 
use runtime
+     * specific code to load resources, e.g. within OSGI environments.
+     * @param resource the resource, not null.
+     * @param cl the desired classloader context, if null, the current thread 
context classloader is used.
+     * @return the resources found
+     * @throws IOException
+     */
+    Enumeration<URL> getResources(String resource, ClassLoader cl) throws 
IOException;
+
+    /**
+     * Loads a resource from the current runtime context. This method allows 
to use runtime
+     * specific code to load a resource, e.g. within OSGI environments.
+     * @param resource the resource, not null.
+     * @param cl the desired classloader context, if null, the current thread 
context classloader is used.
+     * @return the resource found, or null.
+     * @throws IOException
+     */
+    URL getResource(String resource, ClassLoader cl);
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
----------------------------------------------------------------------
diff --git 
a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java 
b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
index 7e9a010..423a707 100644
--- 
a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
+++ 
b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextManagerTest.java
@@ -20,7 +20,10 @@ package org.apache.tamaya.spi;
 
 import org.junit.Test;
 
+import java.io.IOException;
+import java.net.URL;
 import java.util.Collections;
+import java.util.Enumeration;
 import java.util.List;
 
 import static org.junit.Assert.*;
@@ -59,9 +62,24 @@ public class ServiceContextManagerTest {
         }
 
         @Override
+        public <T> T create(Class<T> serviceType) {
+            return null;
+        }
+
+        @Override
         public <T> List<T> getServices(Class<T> serviceType) {
             return Collections.emptyList();
         }
+
+        @Override
+        public Enumeration<URL> getResources(String resource, ClassLoader cl) 
throws IOException {
+            return null;
+        }
+
+        @Override
+        public URL getResource(String resource, ClassLoader cl) {
+            return null;
+        }
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
----------------------------------------------------------------------
diff --git 
a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java 
b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
index dc544ed..652ea1c 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/ServiceContextTest.java
@@ -24,10 +24,9 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
 
 import org.junit.Test;
 
@@ -49,6 +48,11 @@ public class ServiceContextTest {
         }
 
         @Override
+        public <T> T create(Class<T> serviceType) {
+            return getService(serviceType);
+        }
+
+        @Override
         public <T> List<T> getServices(Class<T> serviceType) {
             if(String.class.equals(serviceType)){
                 List<String> list = new ArrayList<>();
@@ -57,6 +61,16 @@ public class ServiceContextTest {
             }
             return Collections.emptyList();
         }
+
+        @Override
+        public Enumeration<URL> getResources(String resource, ClassLoader cl) 
throws IOException {
+            return cl.getResources(resource);
+        }
+
+        @Override
+        public URL getResource(String resource, ClassLoader cl) {
+            return cl.getResource(resource);
+        }
     };
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
----------------------------------------------------------------------
diff --git 
a/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java 
b/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
index 4df7340..65071de 100644
--- a/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
+++ b/code/api/src/test/java/org/apache/tamaya/spi/TestServiceContext.java
@@ -18,12 +18,9 @@
  */
 package org.apache.tamaya.spi;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.ServiceLoader;
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -47,13 +44,7 @@ public final class TestServiceContext implements 
ServiceContext {
     public <T> T getService(Class<T> serviceType) {
         T cached = serviceType.cast(singletons.get(serviceType));
         if(cached==null) {
-            Collection<T> services = getServices(serviceType);
-            if (services.isEmpty()) {
-                cached = (T) Object.class; // as marker for 'nothing here'
-            }
-            else{
-                cached = services.iterator().next();
-            }
+            cached = create(serviceType);
             singletons.put((Class)serviceType, cached);
         }
         if (cached == Object.class) {
@@ -62,6 +53,17 @@ public final class TestServiceContext implements 
ServiceContext {
         return cached;
     }
 
+    @Override
+    public <T> T create(Class<T> serviceType) {
+        Collection<T> services = getServices(serviceType);
+        if (services.isEmpty()) {
+            return (T) Object.class; // as marker for 'nothing here'
+        }
+        else{
+            return services.iterator().next();
+        }
+    }
+
     /**
      * Loads and registers services.
      *
@@ -87,4 +89,14 @@ public final class TestServiceContext implements 
ServiceContext {
         }
     }
 
+    @Override
+    public Enumeration<URL> getResources(String resource, ClassLoader cl) 
throws IOException {
+        return cl.getResources(resource);
+    }
+
+    @Override
+    public URL getResource(String resource, ClassLoader cl) {
+        return cl.getResource(resource);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/core/bnd.bnd
----------------------------------------------------------------------
diff --git a/code/core/bnd.bnd b/code/core/bnd.bnd
index a8eb68b..eec2853 100644
--- a/code/core/bnd.bnd
+++ b/code/core/bnd.bnd
@@ -1,5 +1,7 @@
 Export-Package: \
        org.apache.tamaya.core,\
        org.apache.tamaya.core.propertysource,\
-       org.apache.tamaya.core.provider
+       org.apache.tamaya.core.provider,\
+    org.apache.tamaya.core.internal,\
+    org.apache.tamaya.core.internal.converters
 Bundle-Activator: org.apache.tamaya.core.internal.OSGIActivator
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java
 
b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java
index 9e1fe1c..5285d87 100644
--- 
a/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/internal/DefaultServiceContext.java
@@ -22,6 +22,8 @@ import org.apache.tamaya.ConfigException;
 import org.apache.tamaya.spi.ServiceContext;
 
 import javax.annotation.Priority;
+import java.io.IOException;
+import java.net.URL;
 import java.text.MessageFormat;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
@@ -33,6 +35,7 @@ import java.util.logging.Logger;
  * {@link java.util.ServiceLoader} to load the services required.
  */
 public final class DefaultServiceContext implements ServiceContext {
+    private static final Logger LOG = 
Logger.getLogger(DefaultServiceContext.class.getName());
     /**
      * List current services loaded, per class.
      */
@@ -41,17 +44,13 @@ public final class DefaultServiceContext implements 
ServiceContext {
      * Singletons.
      */
     private final Map<Class<?>, Object> singletons = new ConcurrentHashMap<>();
+    private Map<Class, Class> factoryTypes = new ConcurrentHashMap<>();
 
     @Override
     public <T> T getService(Class<T> serviceType) {
         Object cached = singletons.get(serviceType);
         if (cached == null) {
-            Collection<T> services = getServices(serviceType);
-            if (services.isEmpty()) {
-                cached = null;
-            } else {
-                cached = getServiceWithHighestPriority(services, serviceType);
-            }
+            cached = create(serviceType);
             if(cached!=null) {
                 singletons.put(serviceType, cached);
             }
@@ -59,6 +58,25 @@ public final class DefaultServiceContext implements 
ServiceContext {
         return serviceType.cast(cached);
     }
 
+    @Override
+    public <T> T create(Class<T> serviceType) {
+        Class<? extends T> implType = factoryTypes.get(serviceType);
+        if(implType==null) {
+            Collection<T> services = getServices(serviceType);
+            if (services.isEmpty()) {
+                return null;
+            } else {
+                return getServiceWithHighestPriority(services, serviceType);
+            }
+        }
+        try {
+            return implType.newInstance();
+        } catch (Exception e) {
+            LOG.log(Level.SEVERE, "Failed to create instabce of " + 
implType.getName(), e);
+            return  null;
+        }
+    }
+
     /**
      * Loads and registers services.
      *
@@ -80,7 +98,7 @@ public final class DefaultServiceContext implements 
ServiceContext {
             Collections.sort(services, 
PriorityServiceComparator.getInstance());
             services = Collections.unmodifiableList(services);
         } catch (ServiceConfigurationError e) {
-            
Logger.getLogger(DefaultServiceContext.class.getName()).log(Level.WARNING,
+            LOG.log(Level.WARNING,
                     "Error loading services current type " + serviceType, e);
             if(services==null){
                 services = Collections.emptyList();
@@ -114,15 +132,16 @@ public final class DefaultServiceContext implements 
ServiceContext {
      * @throws ConfigException if there are multiple service implementations 
with the maximum priority
      */
     private <T> T getServiceWithHighestPriority(Collection<T> services, 
Class<T> serviceType) {
-
+        T highestService = null;
         // we do not need the priority stuff if the list contains only one 
element
         if (services.size() == 1) {
-            return services.iterator().next();
+            highestService = services.iterator().next();
+            this.factoryTypes.put(serviceType, highestService.getClass());
+            return highestService;
         }
 
         Integer highestPriority = null;
         int highestPriorityServiceCount = 0;
-        T highestService = null;
 
         for (T service : services) {
             int prio = getPriority(service);
@@ -142,7 +161,7 @@ public final class DefaultServiceContext implements 
ServiceContext {
                                                            highestPriority,
                                                            services));
         }
-
+        this.factoryTypes.put(serviceType, highestService.getClass());
         return highestService;
     }
 
@@ -151,5 +170,27 @@ public final class DefaultServiceContext implements 
ServiceContext {
         return 1;
     }
 
+    @Override
+    public Enumeration<URL> getResources(String resource, ClassLoader cl) 
throws IOException {
+        if(cl==null){
+            cl = Thread.currentThread().getContextClassLoader();
+        }
+        if(cl==null){
+            cl = getClass().getClassLoader();
+        }
+        return cl.getResources(resource);
+    }
+
+    @Override
+    public URL getResource(String resource, ClassLoader cl) {
+        if(cl==null){
+            cl = Thread.currentThread().getContextClassLoader();
+        }
+        if(cl==null){
+            cl = getClass().getClassLoader();
+        }
+        return cl.getResource(resource);
+    }
+
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java 
b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
index 8a54d35..17c778e 100644
--- a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
+++ b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
@@ -38,9 +38,10 @@ public class OSGIActivator implements BundleActivator {
     @Override
     public void start(BundleContext context) {
         // Register marker service
-        ServiceContextManager.set(new OSGIServiceContext(context));
+        serviceLoader = new OSGIServiceLoader(context);
+        ServiceContextManager.set(new OSGIServiceContext(serviceLoader));
         LOG.info("Registered OSGI enabled ServiceContext...");
-        serviceLoader = new OSGIServiceLoader();
+
         context.addBundleListener(serviceLoader);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
 
b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
index 4cc6749..501c42f 100644
--- 
a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
@@ -18,16 +18,15 @@
  */
 package org.apache.tamaya.core.internal;
 
+import org.apache.tamaya.spi.ConfigurationProviderSpi;
 import org.apache.tamaya.spi.ServiceContext;
-import org.osgi.framework.BundleContext;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
 
 /**
  * ServiceContext implementation based on OSGI Service mechanisms.
@@ -36,14 +35,14 @@ public class OSGIServiceContext implements ServiceContext{
 
     private static final OSGIServiceComparator REF_COMPARATOR = new 
OSGIServiceComparator();
 
-    private final BundleContext bundleContext;
+    private final OSGIServiceLoader osgiServiceLoader;
 
-    public OSGIServiceContext(BundleContext bundleContext){
-        this.bundleContext = Objects.requireNonNull(bundleContext);
+    public OSGIServiceContext(OSGIServiceLoader osgiServiceLoader){
+        this.osgiServiceLoader = Objects.requireNonNull(osgiServiceLoader);
     }
 
     public boolean isInitialized(){
-        return bundleContext != null;
+        return osgiServiceLoader != null;
     }
 
 
@@ -54,9 +53,30 @@ public class OSGIServiceContext implements ServiceContext{
 
     @Override
     public <T> T getService(Class<T> serviceType) {
-        ServiceReference<T> ref = 
this.bundleContext.getServiceReference(serviceType);
+        ServiceReference<T> ref = 
this.osgiServiceLoader.getBundleContext().getServiceReference(serviceType);
         if(ref!=null){
-            return this.bundleContext.getService(ref);
+            return this.osgiServiceLoader.getBundleContext().getService(ref);
+        }
+        if(ConfigurationProviderSpi.class==serviceType){
+            T service = (T)new DefaultConfigurationProvider();
+            this.osgiServiceLoader.getBundleContext().registerService(
+                    serviceType.getName(),
+                    service,
+                    new Hashtable<String, Object>());
+            return service;
+        }
+        return null;
+    }
+
+    @Override
+    public <T> T create(Class<T> serviceType) {
+        ServiceReference<T> ref = 
this.osgiServiceLoader.getBundleContext().getServiceReference(serviceType);
+        if(ref!=null){
+            try {
+                return 
(T)this.osgiServiceLoader.getBundleContext().getService(ref).getClass().newInstance();
+            } catch (Exception e) {
+                return null;
+            }
         }
         return null;
     }
@@ -65,11 +85,11 @@ public class OSGIServiceContext implements ServiceContext{
     public <T> List<T> getServices(Class<T> serviceType) {
         List<ServiceReference<T>> refs = new ArrayList<>();
         try {
-            refs.addAll(this.bundleContext.getServiceReferences(serviceType, 
null));
+            
refs.addAll(this.osgiServiceLoader.getBundleContext().getServiceReferences(serviceType,
 null));
             Collections.sort(refs, REF_COMPARATOR);
             List<T> services = new ArrayList<>(refs.size());
             for(ServiceReference<T> ref:refs){
-                T service = bundleContext.getService(ref);
+                T service = 
osgiServiceLoader.getBundleContext().getService(ref);
                 if(service!=null) {
                     services.add(service);
                 }
@@ -80,4 +100,39 @@ public class OSGIServiceContext implements ServiceContext{
             return Collections.emptyList();
         }
     }
+
+    @Override
+    public Enumeration<URL> getResources(String resource, ClassLoader cl) 
throws IOException{
+        List<URL> result = new ArrayList<>();
+        URL url = osgiServiceLoader.getBundleContext().getBundle()
+                .getEntry(resource);
+        if(url != null) {
+            result.add(url);
+        }
+        for(Bundle bundle: osgiServiceLoader.getResourceBundles()) {
+            url = bundle.getEntry(resource);
+            if (url != null) {
+                if(!result.contains(url)) {
+                    result.add(url);
+                }
+            }
+        }
+        return Collections.enumeration(result);
+    }
+
+    @Override
+    public URL getResource(String resource, ClassLoader cl){
+        URL url = osgiServiceLoader.getBundleContext().getBundle()
+                .getEntry(resource);
+        if(url!=null){
+            return url;
+        }
+        for(Bundle bundle: osgiServiceLoader.getResourceBundles()) {
+            url = bundle.getEntry(resource);
+            if(url != null){
+                return url;
+            }
+        }
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
 
b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
index 7cd98d2..89d28c0 100644
--- 
a/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
@@ -22,21 +22,12 @@ import java.io.BufferedReader;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URL;
-import java.util.ConcurrentModificationException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.*;
 import org.osgi.util.tracker.ServiceTracker;
 
 /**
@@ -48,13 +39,36 @@ public class OSGIServiceLoader implements BundleListener {
     // Provide logging
     private static final Logger log = 
Logger.getLogger(OSGIServiceLoader.class.getName());
 
+    private BundleContext context;
+
     private Map<Class, ServiceTracker<Object,Object>> services = new 
ConcurrentHashMap<>();
 
+    private Set<Bundle> resourceBundles = Collections.synchronizedSet(new 
HashSet<Bundle>());
+
+    public OSGIServiceLoader(BundleContext context){
+        this.context = Objects.requireNonNull(context);
+    }
+
+    public BundleContext getBundleContext(){
+        return context;
+    }
+
+    public Set<Bundle> getResourceBundles(){
+        synchronized (resourceBundles){
+            return new HashSet<>(resourceBundles);
+        }
+    }
+
     @Override
     public void bundleChanged(BundleEvent bundleEvent) {
         // Parse and create metadta on STARTING
         if (bundleEvent.getType() == BundleEvent.STARTED) {
             Bundle bundle = bundleEvent.getBundle();
+            if (bundle.getEntry("META-INF/OSGIResource") != null) {
+                synchronized (resourceBundles){
+                    resourceBundles.add(bundle);
+                }
+            }
             if (bundle.getEntry("META-INF/services/") == null) {
                 return;
             }
@@ -65,6 +79,23 @@ public class OSGIServiceLoader implements BundleListener {
                     processEntryPath(bundle, entryPath);
                 }
             }
+        }else if (bundleEvent.getType() == BundleEvent.STOPPED) {
+            Bundle bundle = bundleEvent.getBundle();
+            if (bundle.getEntry("META-INF/OSGIResources") != null) {
+                synchronized (resourceBundles){
+                    resourceBundles.remove(bundle);
+                }
+            }
+            if (bundle.getEntry("META-INF/services/") == null) {
+                return;
+            }
+            Enumeration<String> entryPaths = 
bundle.getEntryPaths("META-INF/services/");
+            while (entryPaths.hasMoreElements()) {
+                String entryPath = entryPaths.nextElement();
+                if(!entryPath.endsWith("/")) {
+                    removeEntryPath(bundle, entryPath);
+                }
+            }
         }
     }
 
@@ -127,6 +158,55 @@ public class OSGIServiceLoader implements BundleListener {
         }
     }
 
+    private void removeEntryPath(Bundle bundle, String entryPath) {
+        try {
+            String serviceName = 
entryPath.substring("META-INF/services/".length());
+            Class<?> serviceClass = bundle.loadClass(serviceName);
+
+            URL child = bundle.getEntry(entryPath);
+            InputStream inStream = child.openStream();
+
+            BufferedReader br = new BufferedReader(new 
InputStreamReader(inStream, "UTF-8"));
+            String implClassName = br.readLine();
+            while (implClassName != null){
+                int hashIndex = implClassName.indexOf("#");
+                if (hashIndex > 0) {
+                    implClassName = implClassName.substring(0, hashIndex-1);
+                }
+                else if (hashIndex == 0) {
+                    implClassName = "";
+                }
+                implClassName = implClassName.trim();
+                if (implClassName.length() > 0) {
+                    try {
+                        // Load the service class
+                        Class<?> implClass = bundle.loadClass(implClassName);
+                        if (!serviceClass.isAssignableFrom(implClass)) {
+                            log.warning("Configured service: " + implClassName 
+ " is not assignble to " +
+                                    serviceClass.getName());
+                            continue;
+                        }
+                        ServiceReference<?> ref = 
bundle.getBundleContext().getServiceReference(implClass);
+                        if(ref!=null){
+                            bundle.getBundleContext().ungetService(ref);
+                        }
+                    }
+                    catch(Exception e){
+                        log.log(Level.SEVERE,
+                                "Failed to unload service class using 
ServiceLoader logic: " + implClassName, e);
+                    }
+                }
+                implClassName = br.readLine();
+            }
+            br.close();
+        }
+        catch (RuntimeException rte) {
+            throw rte;
+        }
+        catch (Exception e) {
+            log.log(Level.SEVERE, "Failed to read services from: " + 
entryPath, e);
+        }
+    }
 
     /**
      * Service factory simply instantiating the configured service.
@@ -146,7 +226,7 @@ public class OSGIServiceLoader implements BundleListener {
             }
             catch (Exception ex) {
                 ex.printStackTrace();
-                throw new IllegalStateException("Cannot instanciate service", 
ex);
+                throw new IllegalStateException("Cannot create service: " + 
serviceClass.getName(), ex);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
 
b/code/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
index 671c3fb..f0d855e 100644
--- 
a/code/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
@@ -28,6 +28,9 @@ public class PriorityServiceComparator implements 
Comparator<Object> {
 
     private static final PriorityServiceComparator INSTANCE = new 
PriorityServiceComparator();
 
+    /** Singleton constructor. */
+    private PriorityServiceComparator(){}
+
     /**
      * Get the shared instance of the comparator.
      * @return the shared instance, never null.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/code/core/src/main/java/org/apache/tamaya/core/provider/JavaConfigurationProvider.java
----------------------------------------------------------------------
diff --git 
a/code/core/src/main/java/org/apache/tamaya/core/provider/JavaConfigurationProvider.java
 
b/code/core/src/main/java/org/apache/tamaya/core/provider/JavaConfigurationProvider.java
index 79017a5..7d14ed8 100644
--- 
a/code/core/src/main/java/org/apache/tamaya/core/provider/JavaConfigurationProvider.java
+++ 
b/code/core/src/main/java/org/apache/tamaya/core/provider/JavaConfigurationProvider.java
@@ -22,6 +22,7 @@ import org.apache.tamaya.ConfigException;
 import org.apache.tamaya.core.propertysource.SimplePropertySource;
 import org.apache.tamaya.spi.PropertySource;
 import org.apache.tamaya.spi.PropertySourceProvider;
+import org.apache.tamaya.spi.ServiceContextManager;
 
 import java.io.IOException;
 import java.net.URL;
@@ -86,18 +87,11 @@ public class JavaConfigurationProvider implements 
PropertySourceProvider {
     }
 
     private Collection<? extends PropertySource> 
loadPropertySourcesByName(String filename) {
-        URL currentUrl = null;
-
         List<PropertySource> propertySources = new ArrayList<>();
-        Enumeration<URL> propertyLocations = Collections.emptyEnumeration();
-
+        Enumeration<URL> propertyLocations;
         try {
-            ClassLoader cl = currentThread().getContextClassLoader();
-
-            if (cl != null) {
-                propertyLocations = currentThread().getContextClassLoader()
-                                                   .getResources(filename);
-            }
+            propertyLocations = ServiceContextManager.getServiceContext()
+                    .getResources(filename, 
currentThread().getContextClassLoader());
         } catch (IOException e) {
             String msg = format("Error while searching for %s", filename);
 
@@ -105,7 +99,7 @@ public class JavaConfigurationProvider implements 
PropertySourceProvider {
         }
 
         while (propertyLocations.hasMoreElements()) {
-            currentUrl = propertyLocations.nextElement();
+            URL currentUrl = propertyLocations.nextElement();
             SimplePropertySource sps = new SimplePropertySource(currentUrl);
 
             propertySources.add(sps);

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b31278a3/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 5dc14f8..99f4031 100644
--- a/pom.xml
+++ b/pom.xml
@@ -436,6 +436,7 @@ under the License.
                     <artifactId>maven-jar-plugin</artifactId>
                     <configuration>
                         <archive>
+                            
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
                             <addMavenDescriptor>false</addMavenDescriptor>
                             <manifestEntries>
                                 <Specification-Title>Apache 
${project.name}</Specification-Title>

Reply via email to