You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2018/02/21 09:05:04 UTC

svn commit: r1824944 [1/2] - in /aries/trunk/jndi/jndi-core/src: main/java/org/apache/aries/jndi/ main/java/org/apache/aries/jndi/startup/ main/java/org/apache/aries/jndi/tracker/ test/java/org/apache/aries/jndi/

Author: gnodet
Date: Wed Feb 21 09:05:04 2018
New Revision: 1824944

URL: http://svn.apache.org/viewvc?rev=1824944&view=rev
Log:
[jndi] Big refactoring, introducing caching per ARIES-1068

Added:
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ServicePair.java
      - copied, changed from r1824943, aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextProvider.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/tracker/CachingServiceTracker.java
Removed:
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/Tuple.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/tracker/ServiceTrackerCustomizers.java
Modified:
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/AugmenterInvokerImpl.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextHelper.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextProvider.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DelegateContext.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DirObjectFactoryHelper.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/JREInitialContextFactoryBuilder.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiInitialContextFactoryBuilder.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiObjectFactoryBuilder.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ObjectFactoryHelper.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ProviderAdminServiceFactory.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/URLContextProvider.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/Utils.java
    aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/startup/Activator.java
    aries/trunk/jndi/jndi-core/src/test/java/org/apache/aries/jndi/InitialContextTest.java
    aries/trunk/jndi/jndi-core/src/test/java/org/apache/aries/jndi/ObjectFactoryTest.java

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/AugmenterInvokerImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/AugmenterInvokerImpl.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/AugmenterInvokerImpl.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/AugmenterInvokerImpl.java Wed Feb 21 09:05:04 2018
@@ -22,43 +22,28 @@ import org.apache.aries.jndi.spi.Augment
 import org.apache.aries.jndi.spi.EnvironmentAugmentation;
 import org.apache.aries.jndi.spi.EnvironmentUnaugmentation;
 import org.apache.aries.jndi.startup.Activator;
+import org.osgi.framework.BundleContext;
 
 import java.util.Hashtable;
 
 
 public class AugmenterInvokerImpl implements AugmenterInvoker {
 
-    private static AugmenterInvokerImpl instance = null;
+    private final BundleContext context;
 
-    public static AugmenterInvokerImpl getInstance() {
-        if (instance == null) {
-            instance = new AugmenterInvokerImpl();
-        }
-        return instance;
+    public AugmenterInvokerImpl(BundleContext context) {
+        this.context = context;
     }
 
-
     public void augmentEnvironment(Hashtable<?, ?> environment) {
-        Object[] objects = Activator.getEnvironmentAugmentors();
-
-        if (objects != null) {
-            for (Object obj : objects) {
-                if (obj instanceof EnvironmentAugmentation) {
-                    ((EnvironmentAugmentation) obj).augmentEnvironment(environment);
-                }
-            }
+        for (EnvironmentAugmentation svc : Activator.getServices(context, EnvironmentAugmentation.class)) {
+            svc.augmentEnvironment(environment);
         }
     }
 
     public void unaugmentEnvironment(Hashtable<?, ?> environment) {
-        Object[] objects = Activator.getEnvironmentUnaugmentors();
-
-        if (objects != null) {
-            for (Object obj : objects) {
-                if (obj instanceof EnvironmentUnaugmentation) {
-                    ((EnvironmentUnaugmentation) obj).unaugmentEnvironment(environment);
-                }
-            }
+        for (EnvironmentUnaugmentation svc : Activator.getServices(context, EnvironmentUnaugmentation.class)) {
+            svc.unaugmentEnvironment(environment);
         }
     }
 }

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextHelper.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextHelper.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextHelper.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextHelper.java Wed Feb 21 09:05:04 2018
@@ -19,9 +19,7 @@
 package org.apache.aries.jndi;
 
 import org.apache.aries.jndi.startup.Activator;
-import org.apache.aries.jndi.tracker.ServiceTrackerCustomizers;
 import org.apache.aries.jndi.urls.URLObjectFactoryFinder;
-import org.apache.aries.util.service.registry.ServicePair;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
@@ -33,9 +31,9 @@ import javax.naming.NoInitialContextExce
 import javax.naming.spi.InitialContextFactory;
 import javax.naming.spi.InitialContextFactoryBuilder;
 import javax.naming.spi.ObjectFactory;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import java.util.Collection;
 import java.util.Hashtable;
+import java.util.Optional;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -57,12 +55,6 @@ public final class ContextHelper {
     /**
      * This method is used to create a URL Context. It does this by looking for
      * the URL context's ObjectFactory in the service registry.
-     *
-     * @param context
-     * @param urlScheme
-     * @param env
-     * @return a Context
-     * @throws NamingException
      */
     public static ContextProvider createURLContext(final BundleContext context,
                                                    final String urlScheme,
@@ -87,33 +79,25 @@ public final class ContextHelper {
             throws NamingException {
         ServicePair<ObjectFactory> result = null;
 
-        ServiceReference ref = ServiceTrackerCustomizers.URL_FACTORY_CACHE.find(urlScheme);
+        ServiceReference<ObjectFactory> ref = Activator.getUrlFactory(urlScheme);
 
         if (ref == null) {
-            ServiceReference<URLObjectFactoryFinder>[] refs = AccessController.doPrivileged(new PrivilegedAction<ServiceReference<URLObjectFactoryFinder>[]>() {
-                public ServiceReference<URLObjectFactoryFinder>[] run() {
-                    return Activator.getURLObjectFactoryFinderServices();
-                }
-            });
 
-            if (refs != null) {
-                for (final ServiceReference<URLObjectFactoryFinder> finderRef : refs) {
-                    URLObjectFactoryFinder finder = Utils.getServicePrivileged(ctx, finderRef);
-
-                    if (finder != null) {
-                        ObjectFactory f = finder.findFactory(urlScheme, environment);
-
-                        if (f != null) {
-                            result = new ServicePair<ObjectFactory>(ctx, finderRef, f);
-                            break;
-                        } else {
-                            ctx.ungetService(finderRef);
-                        }
+            Collection<ServiceReference<URLObjectFactoryFinder>> refs = Activator.getURLObjectFactoryFinderServices();
+            for (final ServiceReference<URLObjectFactoryFinder> finderRef : refs) {
+                URLObjectFactoryFinder finder = Activator.getService(ctx, finderRef);
+
+                if (finder != null) {
+                    ObjectFactory f = finder.findFactory(urlScheme, environment);
+
+                    if (f != null) {
+                        result = new ServicePair<>(ctx, finderRef, f);
+                        break;
                     }
                 }
             }
         } else {
-            result = new ServicePair<ObjectFactory>(ctx, ref);
+            result = new ServicePair<>(ctx, ref);
         }
 
         return result;
@@ -125,13 +109,7 @@ public final class ContextHelper {
         final Bundle jndiBundle = FrameworkUtil.getBundle(ContextHelper.class);
         // if we are outside OSGi (like in our unittests) then we would get Null back here, so just make sure we don't.
         if (jndiBundle != null) {
-
-            BundleContext jndiBundleContext = AccessController.doPrivileged(new PrivilegedAction<BundleContext>() {
-                public BundleContext run() {
-                    return jndiBundle.getBundleContext();
-                }
-            });
-
+            BundleContext jndiBundleContext = Utils.doPrivileged(jndiBundle::getBundleContext);
             if (!jndiBundleContext.getClass().equals(context.getClass())) {
                 //the context passed in must have come from a child framework
                 //use the parent context instead
@@ -161,97 +139,65 @@ public final class ContextHelper {
         String contextFactoryClass = (String) environment.get(Context.INITIAL_CONTEXT_FACTORY);
         if (contextFactoryClass == null) {
             // 1. get ContextFactory using builder
-            provider = getInitialContextUsingBuilder(context, environment);
-
+            provider = getInitialContextUsingBuilder(context, environment)
             // 2. lookup all ContextFactory services
-            if (provider == null) {
-
-                ServiceReference<InitialContextFactory>[] references = AccessController.doPrivileged(new PrivilegedAction<ServiceReference<InitialContextFactory>[]>() {
-                    public ServiceReference<InitialContextFactory>[] run() {
-                        return Activator.getInitialContextFactoryServices();
-                    }
-                });
+                    .orElseGet(() -> getInitialContextUsingFactoryServices(context, environment)
+                            .orElse(null));
 
-                if (references != null) {
-                    Context initialContext;
-                    for (ServiceReference<InitialContextFactory> reference : references) {
-                        InitialContextFactory factory = Utils.getServicePrivileged(context, reference);
-                        try {
-                            initialContext = factory.getInitialContext(environment);
-                            if (initialContext != null) {
-                                provider = new SingleContextProvider(context, reference, initialContext);
-                                break;
-                            }
-                        } finally {
-                            if (provider == null) context.ungetService(reference);
-                        }
-                    }
-                }
-            }
         } else {
-            ServiceReference<InitialContextFactory> ref = ServiceTrackerCustomizers.ICF_CACHE.find(contextFactoryClass);
-
+            // 1. lookup using specified InitialContextFactory
+            ServiceReference<InitialContextFactory> ref = Activator.getInitialContextFactory(contextFactoryClass);
             if (ref != null) {
-                Context initialContext;
-                InitialContextFactory factory = Utils.getServicePrivileged(context, ref);
+                InitialContextFactory factory = Activator.getService(context, ref);
                 if (factory != null) {
-                    try {
-                        initialContext = factory.getInitialContext(environment);
-                        provider = new SingleContextProvider(context, ref, initialContext);
-                    } finally {
-                        if (provider == null) context.ungetService(ref);
-                    }
+                    Context initialContext = factory.getInitialContext(environment);
+                    provider = new SingleContextProvider(context, ref, initialContext);
                 }
             }
 
             // 2. get ContextFactory using builder
             if (provider == null) {
-                provider = getInitialContextUsingBuilder(context, environment);
+                provider = getInitialContextUsingBuilder(context, environment).orElse(null);
             }
         }
 
         return provider;
     }
 
-    private static ContextProvider getInitialContextUsingBuilder(BundleContext context,
-                                                                 Hashtable<?, ?> environment)
-            throws NamingException {
-
-        ContextProvider provider = null;
-        ServiceReference<InitialContextFactoryBuilder>[] refs = AccessController.doPrivileged(new PrivilegedAction<ServiceReference<InitialContextFactoryBuilder>[]>() {
-            public ServiceReference<InitialContextFactoryBuilder>[] run() {
-                return Activator.getInitialContextFactoryBuilderServices();
-            }
-        });
-
-        if (refs != null) {
-            InitialContextFactory factory = null;
-            for (ServiceReference<InitialContextFactoryBuilder> ref : refs) {
-                InitialContextFactoryBuilder builder = Utils.getServicePrivileged(context, ref);
-                try {
-                    factory = builder.createInitialContextFactory(environment);
-                } catch (NamingException ne) {
-                    // TODO: log
-                    // ignore this, if the builder fails we want to move onto the next one
-                } catch (NullPointerException npe) {
-                    logger.log(Level.SEVERE, "NPE caught in ContextHelper.getInitialContextUsingBuilder. context=" + context + " ref=" + ref);
-                    throw npe;
-                }
-
+    private static Optional<ContextProvider> getInitialContextUsingFactoryServices(BundleContext context, Hashtable<?, ?> environment) {
+        for (ServiceReference<InitialContextFactory> reference : Activator.getInitialContextFactoryServices()) {
+            try {
+                InitialContextFactory factory = Activator.getService(context, reference);
+                Context initialContext = factory.getInitialContext(environment);
+                if (initialContext != null) {
+                    return Optional.of(new SingleContextProvider(context, reference, initialContext));
+                }
+            } catch (NamingException e) {
+                // ignore this, if the builder fails we want to move onto the next one
+                logger.log(Level.FINE, "Exception caught", e);
+            }
+        }
+        return Optional.empty();
+    }
+
+    private static Optional<ContextProvider> getInitialContextUsingBuilder(BundleContext context,
+                                                                           Hashtable<?, ?> environment) {
+        for (ServiceReference<InitialContextFactoryBuilder> ref : Activator.getInitialContextFactoryBuilderServices()) {
+            InitialContextFactoryBuilder builder = Activator.getService(context, ref);
+            try {
+                InitialContextFactory factory = builder.createInitialContextFactory(environment);
                 if (factory != null) {
-                    try {
-                        provider = new SingleContextProvider(context, ref, factory.getInitialContext(environment));
-                    } finally {
-                        if (provider == null)
-                            context.ungetService(ref); // we didn't get something back, so this was no good.
-                    }
-                    break;
-                } else {
-                    context.ungetService(ref); // we didn't get something back, so this was no good.
+                    return Optional.of(new SingleContextProvider(context, ref, factory.getInitialContext(environment)));
                 }
+            } catch (NamingException ne) {
+                // ignore this, if the builder fails we want to move onto the next one
+                logger.log(Level.FINE, "Exception caught", ne);
+            } catch (NullPointerException npe) {
+                logger.log(Level.SEVERE, "NPE caught in ContextHelper.getInitialContextUsingBuilder. context=" + context + " ref=" + ref);
+                throw npe;
             }
         }
-        return provider;
+        return Optional.empty();
     }
 
 }

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextProvider.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextProvider.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextProvider.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextProvider.java Wed Feb 21 09:05:04 2018
@@ -38,7 +38,6 @@ public abstract class ContextProvider {
     }
 
     public void close() throws NamingException {
-        if (bc != null) bc.ungetService(reference);
     }
 
     public abstract Context getContext() throws NamingException;

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DelegateContext.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DelegateContext.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DelegateContext.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DelegateContext.java Wed Feb 21 09:05:04 2018
@@ -32,10 +32,10 @@ import java.util.Map;
 
 public class DelegateContext implements DirContext, LdapContext {
 
-    private final Hashtable<Object, Object> env = new Hashtable<Object, Object>();
+    private final Hashtable<Object, Object> env = new Hashtable<>();
 
     private final BundleContext bundleContext;
-    private final Map<String, ContextProvider> urlContexts = new HashMap<String, ContextProvider>();
+    private final Map<String, ContextProvider> urlContexts = new HashMap<>();
     private final boolean rebind;
     private ContextProvider contextProvider;
 
@@ -108,7 +108,7 @@ public class DelegateContext implements
     }
 
     public Hashtable<?, ?> getEnvironment() throws NamingException {
-        Hashtable<Object, Object> theEnv = new Hashtable<Object, Object>();
+        Hashtable<Object, Object> theEnv = new Hashtable<>();
         theEnv.putAll(env);
         return theEnv;
     }
@@ -196,7 +196,7 @@ public class DelegateContext implements
     }
 
     protected Context findContext(String name) throws NamingException {
-        Context toReturn = null;
+        Context toReturn;
 
         if (name.contains(":")) {
             toReturn = getURLContext(name);

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DirObjectFactoryHelper.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DirObjectFactoryHelper.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DirObjectFactoryHelper.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/DirObjectFactoryHelper.java Wed Feb 21 09:05:04 2018
@@ -19,15 +19,8 @@
 package org.apache.aries.jndi;
 
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
 
-import javax.naming.*;
-import javax.naming.directory.Attributes;
 import javax.naming.spi.DirObjectFactory;
-import javax.naming.spi.ObjectFactory;
-import javax.naming.spi.ObjectFactoryBuilder;
-import java.util.Collection;
-import java.util.Hashtable;
 
 public class DirObjectFactoryHelper extends ObjectFactoryHelper implements DirObjectFactory {
 
@@ -35,157 +28,4 @@ public class DirObjectFactoryHelper exte
         super(defaultContext, callerContext);
     }
 
-    public Object getObjectInstance(Object obj,
-                                    Name name,
-                                    Context nameCtx,
-                                    Hashtable<?, ?> environment,
-                                    Attributes attrs) throws Exception {
-
-        // Step 1
-        if (obj instanceof Referenceable) {
-            obj = ((Referenceable) obj).getReference();
-        }
-
-        Object result = obj;
-
-        // Step 2
-        if (obj instanceof Reference) {
-            Reference ref = (Reference) obj;
-            String className = ref.getFactoryClassName();
-
-            if (className != null) {
-                // Step 3
-                result = getObjectInstanceUsingClassName(obj, className, obj, name, nameCtx, environment, attrs);
-            }
-        }
-
-        // Step 4
-        if (result == null || result == obj) {
-            result = getObjectInstanceUsingObjectFactoryBuilders(obj, name, nameCtx, environment, attrs);
-        }
-
-        // Step 5
-        if (result == null || result == obj) {
-            if (!(obj instanceof Reference) || ((Reference) obj).getFactoryClassName() == null) {
-                result = getObjectInstanceUsingObjectFactories(obj, name, nameCtx, environment, attrs);
-            }
-        }
-
-        // Extra, non-standard, bonus step. If javax.naming.OBJECT_FACTORIES is set as 
-        // a property in the environment, use its value to construct additional object factories. 
-        // Added under Aries-822, with reference 
-        // to https://www.osgi.org/bugzilla/show_bug.cgi?id=138 
-        if (result == null || result == obj) {
-            result = getObjectInstanceViaContextDotObjectFactories(obj, name, nameCtx, environment, attrs);
-        }
-
-        return (result == null) ? obj : result;
-    }
-
-    private Object getObjectInstanceUsingObjectFactories(Object obj,
-                                                         Name name,
-                                                         Context nameCtx,
-                                                         Hashtable<?, ?> environment,
-                                                         Attributes attrs)
-            throws Exception {
-
-        Object result = null;
-        Collection<ServiceReference<DirObjectFactory>> refs = Utils.getReferencesPrivileged(callerContext, DirObjectFactory.class);
-        for (ServiceReference<DirObjectFactory> ref : refs) {
-
-            if (canCallObjectFactory(obj, ref)) {
-                DirObjectFactory factory = Utils.getServicePrivileged(callerContext, ref);
-
-                try {
-                    result = factory.getObjectInstance(obj, name, nameCtx, environment, attrs);
-                } finally {
-                    callerContext.ungetService(ref);
-                }
-
-                // if the result comes back and is not null and not the reference
-                // object then we should return the result, so break out of the
-                // loop we are in.
-                if (result != null && result != obj) {
-                    break;
-                }
-            }
-        }
-
-        if (result == null) {
-            result = getObjectInstanceUsingObjectFactories(obj, name, nameCtx, environment);
-        }
-
-        return (result == null) ? obj : result;
-    }
-
-    private boolean canCallObjectFactory(Object obj, ServiceReference ref) {
-        if (obj instanceof Reference) return true;
-
-        Object prop = ref.getProperty("aries.object.factory.requires.reference");
-
-        if (prop == null) return true;
-
-        if (prop instanceof Boolean) return !(Boolean) prop; // if set to true we don't call.
-
-        return true;
-    }
-
-    private Object getObjectInstanceUsingClassName(Object reference,
-                                                   String className,
-                                                   Object obj,
-                                                   Name name,
-                                                   Context nameCtx,
-                                                   Hashtable<?, ?> environment,
-                                                   Attributes attrs)
-            throws Exception {
-
-        Tuple<ServiceReference<ObjectFactory>, ObjectFactory> tuple = ObjectFactoryHelper.findObjectFactoryByClassName(defaultContext, className);
-        Object result = null;
-
-        if (tuple.second != null) {
-            try {
-                result = ((DirObjectFactory) tuple.second).getObjectInstance(reference, name, nameCtx, environment, attrs);
-            } finally {
-                defaultContext.ungetService(tuple.first);
-            }
-        }
-
-        return (result == null) ? obj : result;
-    }
-
-    private Object getObjectInstanceUsingObjectFactoryBuilders(Object obj,
-                                                               Name name,
-                                                               Context nameCtx,
-                                                               Hashtable<?, ?> environment,
-                                                               Attributes attrs)
-            throws Exception {
-        ObjectFactory factory = null;
-        Collection<ServiceReference<ObjectFactoryBuilder>> refs = Utils.getReferencesPrivileged(callerContext, ObjectFactoryBuilder.class);
-        for (ServiceReference<ObjectFactoryBuilder> ref : refs) {
-            ObjectFactoryBuilder builder = Utils.getServicePrivileged(callerContext, ref);
-            try {
-                factory = builder.createObjectFactory(obj, environment);
-            } catch (NamingException e) {
-                // TODO: log it
-            } finally {
-                callerContext.ungetService(ref);
-            }
-            if (factory != null) {
-                break;
-            }
-        }
-
-        Object result = null;
-
-        if (factory != null) {
-            if (factory instanceof DirObjectFactory) {
-                result = ((DirObjectFactory) factory).getObjectInstance(obj, name, nameCtx, environment, attrs);
-            } else {
-                result = factory.getObjectInstance(obj, name, nameCtx, environment);
-            }
-        }
-
-        return (result == null) ? obj : result;
-    }
-
 }

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/JREInitialContextFactoryBuilder.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/JREInitialContextFactoryBuilder.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/JREInitialContextFactoryBuilder.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/JREInitialContextFactoryBuilder.java Wed Feb 21 09:05:04 2018
@@ -22,26 +22,22 @@ import javax.naming.Context;
 import javax.naming.NamingException;
 import javax.naming.spi.InitialContextFactory;
 import javax.naming.spi.InitialContextFactoryBuilder;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.Hashtable;
 
 public class JREInitialContextFactoryBuilder implements InitialContextFactoryBuilder {
 
     public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> environment)
             throws NamingException {
-        final String contextFactoryClass = (String) environment.get(Context.INITIAL_CONTEXT_FACTORY);
+        String contextFactoryClass = (String) environment.get(Context.INITIAL_CONTEXT_FACTORY);
         if (contextFactoryClass != null) {
-            return AccessController.doPrivileged(new PrivilegedAction<InitialContextFactory>() {
-                public InitialContextFactory run() {
-                    try {
-                        @SuppressWarnings("unchecked")
-                        Class<? extends InitialContextFactory> clazz = (Class<? extends InitialContextFactory>) ClassLoader.
-                                getSystemClassLoader().loadClass(contextFactoryClass);
-                        return InitialContextFactory.class.cast(clazz.newInstance());
-                    } catch (Exception e) {
-                        return null;
-                    }
+            return Utils.doPrivileged(() -> {
+                try {
+                    @SuppressWarnings("unchecked")
+                    Class<? extends InitialContextFactory> clazz = (Class<? extends InitialContextFactory>) ClassLoader.
+                            getSystemClassLoader().loadClass(contextFactoryClass);
+                    return InitialContextFactory.class.cast(clazz.newInstance());
+                } catch (Exception e) {
+                    return null;
                 }
             });
         }

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiInitialContextFactoryBuilder.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiInitialContextFactoryBuilder.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiInitialContextFactoryBuilder.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiInitialContextFactoryBuilder.java Wed Feb 21 09:05:04 2018
@@ -18,6 +18,7 @@
  */
 package org.apache.aries.jndi;
 
+import org.apache.aries.jndi.startup.Activator;
 import org.osgi.framework.BundleContext;
 
 import javax.naming.Context;
@@ -30,23 +31,17 @@ import java.util.Hashtable;
 
 public class OSGiInitialContextFactoryBuilder implements InitialContextFactoryBuilder, InitialContextFactory {
 
-    public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> environment)
-            throws NamingException {
+    public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> environment) {
         return this;
     }
 
-    public Context getInitialContext(Hashtable<?, ?> environment)
-            throws NamingException {
-
-        AugmenterInvokerImpl.getInstance().augmentEnvironment(environment);
-
+    public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
+        Activator.getAugmenterInvoker().augmentEnvironment(environment);
         BundleContext context = Utils.getBundleContext(environment, InitialContext.class);
         if (context == null) {
             throw new NoInitialContextException(Utils.MESSAGES.getMessage("cannot.find.callers.bundlecontext"));
         }
-
-        AugmenterInvokerImpl.getInstance().unaugmentEnvironment(environment);
-
+        Activator.getAugmenterInvoker().unaugmentEnvironment(environment);
         return ContextHelper.getInitialContext(context, environment);
     }
 }

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiObjectFactoryBuilder.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiObjectFactoryBuilder.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiObjectFactoryBuilder.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/OSGiObjectFactoryBuilder.java Wed Feb 21 09:05:04 2018
@@ -18,6 +18,7 @@
  */
 package org.apache.aries.jndi;
 
+import org.apache.aries.jndi.startup.Activator;
 import org.osgi.framework.BundleContext;
 
 import javax.naming.Context;
@@ -35,8 +36,7 @@ public class OSGiObjectFactoryBuilder im
         defaultContext = ctx;
     }
 
-    public ObjectFactory createObjectFactory(Object obj, Hashtable<?, ?> environment)
-            throws NamingException {
+    public ObjectFactory createObjectFactory(Object obj, Hashtable<?, ?> environment) {
         return this;
     }
 
@@ -45,16 +45,7 @@ public class OSGiObjectFactoryBuilder im
                                     Context nameCtx,
                                     Hashtable<?, ?> environment) throws Exception {
 
-        if (environment == null) {
-            environment = new Hashtable();
-        }
-
-        BundleContext callerContext = getCallerBundleContext(environment);
-        if (callerContext == null) {
-            return obj;
-        }
-        DirObjectFactoryHelper helper = new DirObjectFactoryHelper(defaultContext, callerContext);
-        return helper.getObjectInstance(obj, name, nameCtx, environment);
+        return getObjectInstance(obj, name, nameCtx, environment, null);
     }
 
     public Object getObjectInstance(Object obj,
@@ -75,13 +66,13 @@ public class OSGiObjectFactoryBuilder im
         return helper.getObjectInstance(obj, name, nameCtx, environment, attrs);
     }
 
-    private BundleContext getCallerBundleContext(Hashtable<?, ?> environment) throws NamingException {
-        AugmenterInvokerImpl.getInstance().augmentEnvironment(environment);
+    private BundleContext getCallerBundleContext(Hashtable<?, ?> environment) {
+        Activator.getAugmenterInvoker().augmentEnvironment(environment);
         BundleContext context = Utils.getBundleContext(environment, NamingManager.class);
         if (context == null) {
             context = Utils.getBundleContext(environment, DirectoryManager.class);
         }
-        AugmenterInvokerImpl.getInstance().unaugmentEnvironment(environment);
+        Activator.getAugmenterInvoker().unaugmentEnvironment(environment);
         return context;
     }
 }

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ObjectFactoryHelper.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ObjectFactoryHelper.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ObjectFactoryHelper.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ObjectFactoryHelper.java Wed Feb 21 09:05:04 2018
@@ -18,9 +18,8 @@
  */
 package org.apache.aries.jndi;
 
-import org.apache.aries.util.service.registry.ServicePair;
+import org.apache.aries.jndi.startup.Activator;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 
 import javax.naming.*;
@@ -30,7 +29,6 @@ import javax.naming.spi.ObjectFactory;
 import javax.naming.spi.ObjectFactoryBuilder;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.Collection;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.logging.Level;
@@ -39,6 +37,7 @@ import java.util.logging.Logger;
 public class ObjectFactoryHelper implements ObjectFactory {
 
     private static final Logger logger = Logger.getLogger(ObjectFactoryHelper.class.getName());
+
     protected BundleContext defaultContext;
     protected BundleContext callerContext;
 
@@ -47,127 +46,164 @@ public class ObjectFactoryHelper impleme
         this.callerContext = callerContext;
     }
 
-    protected static String getUrlScheme(String name) {
-        String scheme = name;
-        int index = name.indexOf(':');
-        if (index != -1) {
-            scheme = name.substring(0, index);
-        }
-        return scheme;
-    }
-
-    static Tuple<ServiceReference<ObjectFactory>, ObjectFactory> findObjectFactoryByClassName(final BundleContext ctx, final String className) {
-        return AccessController.doPrivileged(new PrivilegedAction<Tuple<ServiceReference<ObjectFactory>, ObjectFactory>>() {
-            public Tuple<ServiceReference<ObjectFactory>, ObjectFactory> run() {
-                ServiceReference<ObjectFactory> serviceReference = null;
-
-                try {
-                    ServiceReference<?>[] refs = ctx.getServiceReferences(className, null);
-                    if (refs != null && refs.length > 0) {
-                        serviceReference = (ServiceReference<ObjectFactory>) refs[0];
-                    }
-                } catch (InvalidSyntaxException e) {
-                    // should not happen
-                    throw new RuntimeException(Utils.MESSAGES.getMessage("null.is.invalid.filter"), e);
-                }
-
-                ObjectFactory factory = null;
-
-                if (serviceReference != null) {
-                    factory = ctx.getService(serviceReference);
-                }
+    public Object getObjectInstance(Object obj,
+                                    Name name,
+                                    Context nameCtx,
+                                    Hashtable<?, ?> environment) throws Exception {
 
-                return new Tuple<ServiceReference<ObjectFactory>, ObjectFactory>(serviceReference, factory);
-            }
-        });
+        return getObjectInstance(obj, name, nameCtx, environment, null);
     }
 
     public Object getObjectInstance(Object obj,
                                     Name name,
                                     Context nameCtx,
-                                    Hashtable<?, ?> environment) throws Exception {
+                                    Hashtable<?, ?> environment,
+                                    Attributes attrs) throws Exception {
 
-        // Step 1 ensure we have a reference rather than a referenceable
+        // Step 1
         if (obj instanceof Referenceable) {
             obj = ((Referenceable) obj).getReference();
         }
 
-        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "obj = " + obj);
-
         Object result = obj;
 
-        // Step 2 - if we have a reference process it as a reference
+        // Step 2
         if (obj instanceof Reference) {
             Reference ref = (Reference) obj;
             String className = ref.getFactoryClassName();
 
             if (className != null) {
-                // Step 3 - use the class name in the reference to get the factory class name
-                result = getObjectInstanceUsingClassName(obj, className, obj, name, nameCtx, environment);
+                // Step 3
+                result = getObjectInstanceUsingClassName(obj, className, obj, name, nameCtx, environment, attrs);
             } else {
                 // Step 4 - look, assuming url string ref addrs, for a url context object factory.
-                result = getObjectInstanceUsingRefAddress(ref.getAll(), obj, name, nameCtx, environment);
+                result = getObjectInstanceUsingRefAddress(ref.getAll(), obj, name, nameCtx, environment, attrs);
             }
         }
 
-        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "Step 4: result = " + result);
-
-        // Step 5 - if we still don't have a resolved object goto the object factory builds in the SR.
+        // Step 4
         if (result == null || result == obj) {
-            result = getObjectInstanceUsingObjectFactoryBuilders(obj, name, nameCtx, environment);
+            result = getObjectInstanceUsingObjectFactoryBuilders(obj, name, nameCtx, environment, attrs);
         }
 
-        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "Step 5: result = " + result);
-
-        // Step 6 - Attempt to use all the registered ObjectFactories in the SR.
+        // Step 5
         if (result == null || result == obj) {
             if (!(obj instanceof Reference) || ((Reference) obj).getFactoryClassName() == null) {
-                result = getObjectInstanceUsingObjectFactories(obj, name, nameCtx, environment);
+                result = getObjectInstanceUsingObjectFactories(obj, name, nameCtx, environment, attrs);
             }
         }
 
-        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "Step 6: result = " + result);
-
-        // Extra, non-standard, bonus step 7. If javax.naming.OBJECT_FACTORIES is set as
+        // Extra, non-standard, bonus step. If javax.naming.OBJECT_FACTORIES is set as
         // a property in the environment, use its value to construct additional object factories.
         // Added under Aries-822, with reference
         // to https://www.osgi.org/bugzilla/show_bug.cgi?id=138
         if (result == null || result == obj) {
-            result = getObjectInstanceViaContextDotObjectFactories(obj, name, nameCtx, environment);
+            result = getObjectInstanceViaContextDotObjectFactories(obj, name, nameCtx, environment, attrs);
         }
 
-        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "Step 7: result = " + result);
+        return (result == null) ? obj : result;
+    }
+
+    private Object getObjectInstanceUsingObjectFactories(Object obj,
+                                                         Name name,
+                                                         Context nameCtx,
+                                                         Hashtable<?, ?> environment,
+                                                         Attributes attrs) throws Exception {
+        for (ServiceReference<ObjectFactory> ref : Activator.getReferences(callerContext, ObjectFactory.class)) {
+            if (canCallObjectFactory(obj, ref)) {
+                ObjectFactory factory = Activator.getService(callerContext, ref);
+                if (factory != null) {
+                    Object result;
+                    if (factory instanceof DirObjectFactory) {
+                        result = ((DirObjectFactory) factory).getObjectInstance(obj, name, nameCtx, environment, attrs);
+                    } else {
+                        result = factory.getObjectInstance(obj, name, nameCtx, environment);
+                    }
+                    // if the result comes back and is not null and not the reference
+                    // object then we should return the result, so break out of the
+                    // loop we are in.
+                    if (result != null && result != obj) {
+                        return result;
+                    }
+                }
+            }
+        }
+        return obj;
+    }
+
+    private boolean canCallObjectFactory(Object obj, ServiceReference ref) {
+        if (obj instanceof Reference) return true;
+        Object prop = ref.getProperty("aries.object.factory.requires.reference");
+        return (prop == null) || !(prop instanceof Boolean) || !(Boolean) prop;
+    }
+
+    private Object getObjectInstanceUsingClassName(Object reference,
+                                                   String className,
+                                                   Object obj,
+                                                   Name name,
+                                                   Context nameCtx,
+                                                   Hashtable<?, ?> environment,
+                                                   Attributes attrs)
+            throws Exception {
+
+        Object result = null;
+
+        ObjectFactory factory = ObjectFactoryHelper.findObjectFactoryByClassName(defaultContext, className);
+        if (factory != null) {
+            if (factory instanceof DirObjectFactory) {
+                result = ((DirObjectFactory) factory).getObjectInstance(reference, name, nameCtx, environment, attrs);
+            } else {
+                result = factory.getObjectInstance(reference, name, nameCtx, environment);
+            }
+        }
 
         return (result == null) ? obj : result;
     }
 
-    /*
-     * Attempt to obtain an Object instance via the java.naming.factory.object property
-     */
-    protected Object getObjectInstanceViaContextDotObjectFactories(Object obj,
-                                                                   Name name,
-                                                                   Context nameCtx,
-                                                                   Hashtable<?, ?> environment) throws Exception {
-        return getObjectInstanceViaContextDotObjectFactories(obj, name, nameCtx, environment, null);
+    private Object getObjectInstanceUsingObjectFactoryBuilders(Object obj,
+                                                               Name name,
+                                                               Context nameCtx,
+                                                               Hashtable<?, ?> environment,
+                                                               Attributes attrs)
+            throws Exception {
+        ObjectFactory factory = null;
+        for (ObjectFactoryBuilder ofb : Activator.getServices(callerContext, ObjectFactoryBuilder.class)) {
+            try {
+                factory = ofb.createObjectFactory(obj, environment);
+            } catch (NamingException e) {
+                // TODO: log it
+            }
+            if (factory != null) {
+                break;
+            }
+        }
+
+        Object result = null;
+
+        if (factory != null) {
+            if (factory instanceof DirObjectFactory) {
+                result = ((DirObjectFactory) factory).getObjectInstance(obj, name, nameCtx, environment, attrs);
+            } else {
+                result = factory.getObjectInstance(obj, name, nameCtx, environment);
+            }
+        }
+
+        return (result == null) ? obj : result;
     }
 
     /*
      * Attempt to obtain an Object instance via the java.naming.factory.object property
      */
-    protected Object getObjectInstanceViaContextDotObjectFactories(Object obj,
-                                                                   Name name,
-                                                                   Context nameCtx,
-                                                                   Hashtable<?, ?> environment,
-                                                                   Attributes attrs) throws Exception {
+    private Object getObjectInstanceViaContextDotObjectFactories(Object obj,
+                                                                 Name name,
+                                                                 Context nameCtx,
+                                                                 Hashtable<?, ?> environment,
+                                                                 Attributes attrs) throws Exception {
         Object result = null;
         String factories = (String) environment.get(Context.OBJECT_FACTORIES);
         if (factories != null && factories.length() > 0) {
             String[] candidates = factories.split(":");
-            ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
-                public ClassLoader run() {
-                    return Thread.currentThread().getContextClassLoader();
-                }
-            });
+            ClassLoader cl = Utils.doPrivileged(Thread.currentThread()::getContextClassLoader);
             for (String cand : candidates) {
                 ObjectFactory factory;
                 try {
@@ -181,11 +217,8 @@ public class ObjectFactoryHelper impleme
                 if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "cand=" + cand + " factory=" + factory);
                 if (factory != null) {
                     if (factory instanceof DirObjectFactory) {
-                        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "its a DirObjectFactory");
-                        final DirObjectFactory dirFactory = (DirObjectFactory) factory;
-                        result = dirFactory.getObjectInstance(obj, name, nameCtx, environment, attrs);
+                        result = ((DirObjectFactory) factory).getObjectInstance(obj, name, nameCtx, environment, attrs);
                     } else {
-                        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "its an ObjectFactory");
                         result = factory.getObjectInstance(obj, name, nameCtx, environment);
                     }
                 }
@@ -196,56 +229,13 @@ public class ObjectFactoryHelper impleme
         return (result == null) ? obj : result;
     }
 
-    protected Object getObjectInstanceUsingObjectFactories(Object obj,
-                                                           Name name,
-                                                           Context nameCtx,
-                                                           Hashtable<?, ?> environment)
-            throws Exception {
-        Object result = null;
-        Collection<ServiceReference<ObjectFactory>> refs = Utils.getReferencesPrivileged(callerContext, ObjectFactory.class);
-        for (ServiceReference<ObjectFactory> ref : refs) {
-            if (canCallObjectFactory(obj, ref)) {
-                ObjectFactory factory = Utils.getServicePrivileged(callerContext, ref);
-
-                try {
-                    result = factory.getObjectInstance(obj, name, nameCtx, environment);
-                } catch (NamingException ne) {
-                    // Ignore this since we are doing last ditch finding, another OF might work.
-                } finally {
-                    callerContext.ungetService(ref);
-                }
-
-                // if the result comes back and is not null and not the reference
-                // object then we should return the result, so break out of the
-                // loop we are in.
-                if (result != null && result != obj) {
-                    break;
-                }
-            }
-        }
-
-        return (result == null) ? obj : result;
-    }
-
-    private boolean canCallObjectFactory(Object obj, ServiceReference ref) {
-        if (obj instanceof Reference) return true;
-
-        Object prop = ref.getProperty("aries.object.factory.requires.reference");
-
-        if (prop == null) return true;
-
-        if (prop instanceof Boolean) return !(Boolean) prop; // if set to true we don't call.
-
-        return true;
-    }
-
     private Object getObjectInstanceUsingRefAddress(Enumeration<RefAddr> addresses,
                                                     Object obj,
                                                     Name name,
                                                     Context nameCtx,
-                                                    Hashtable<?, ?> environment)
+                                                    Hashtable<?, ?> environment,
+                                                    Attributes attrs)
             throws Exception {
-        Object result = null;
         while (addresses.hasMoreElements()) {
             RefAddr address = addresses.nextElement();
             if (address instanceof StringRefAddr && "URL".equals(address.getType())) {
@@ -256,78 +246,45 @@ public class ObjectFactoryHelper impleme
                 if (factoryService != null) {
                     ObjectFactory factory = factoryService.get();
 
+                    Object result;
+
                     String value = (String) address.getContent();
-                    try {
+                    if (factory instanceof DirObjectFactory) {
+                        result = ((DirObjectFactory) factory).getObjectInstance(value, name, nameCtx, environment, attrs);
+                    } else {
                         result = factory.getObjectInstance(value, name, nameCtx, environment);
-                    } finally {
-                        factoryService.unget();
                     }
 
                     // if the result comes back and is not null and not the reference
                     // object then we should return the result, so break out of the
                     // loop we are in.
                     if (result != null && result != obj) {
-                        break;
+                        return result;
                     }
                 }
             }
         }
 
-        return (result == null) ? obj : result;
+        return obj;
     }
 
-    private Object getObjectInstanceUsingClassName(Object reference,
-                                                   String className,
-                                                   Object obj,
-                                                   Name name,
-                                                   Context nameCtx,
-                                                   Hashtable<?, ?> environment)
-            throws Exception {
-
-        Tuple<ServiceReference<ObjectFactory>, ObjectFactory> tuple = findObjectFactoryByClassName(defaultContext, className);
-        Object result = null;
-
-        if (tuple.second != null) {
-            try {
-                result = tuple.second.getObjectInstance(reference, name, nameCtx, environment);
-            } finally {
-                defaultContext.ungetService(tuple.first);
-            }
+    private static String getUrlScheme(String name) {
+        String scheme = name;
+        int index = name.indexOf(':');
+        if (index != -1) {
+            scheme = name.substring(0, index);
         }
-
-        return (result == null) ? obj : result;
+        return scheme;
     }
 
-    private Object getObjectInstanceUsingObjectFactoryBuilders(Object obj,
-                                                               Name name,
-                                                               Context nameCtx,
-                                                               Hashtable<?, ?> environment)
-            throws Exception {
-
-        ObjectFactory factory = null;
-
-        Collection<ServiceReference<ObjectFactoryBuilder>> refs = Utils.getReferencesPrivileged(callerContext, ObjectFactoryBuilder.class);
-        for (ServiceReference<ObjectFactoryBuilder> ref : refs) {
-            ObjectFactoryBuilder builder = Utils.getServicePrivileged(callerContext, ref);
-            try {
-                factory = builder.createObjectFactory(obj, environment);
-            } catch (NamingException e) {
-                // TODO: log it
-            } finally {
-                callerContext.ungetService(ref);
-            }
-            if (factory != null) {
-                break;
+    private static ObjectFactory findObjectFactoryByClassName(final BundleContext ctx, final String className) {
+        return AccessController.doPrivileged((PrivilegedAction<ObjectFactory>) () -> {
+            ServiceReference<?> ref = ctx.getServiceReference(className);
+            if (ref != null) {
+                return (ObjectFactory) Activator.getService(ctx, ref);
             }
-        }
-
-        Object result = null;
-
-        if (factory != null) {
-            result = factory.getObjectInstance(obj, name, nameCtx, environment);
-        }
-
-        return (result == null) ? obj : result;
+            return null;
+        });
     }
 
 }
\ No newline at end of file

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ProviderAdminServiceFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ProviderAdminServiceFactory.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ProviderAdminServiceFactory.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ProviderAdminServiceFactory.java Wed Feb 21 09:05:04 2018
@@ -23,7 +23,7 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceRegistration;
 
-public class ProviderAdminServiceFactory implements ServiceFactory {
+public class ProviderAdminServiceFactory implements ServiceFactory<ProviderAdminService> {
 
     private BundleContext defaultContext;
 
@@ -31,12 +31,12 @@ public class ProviderAdminServiceFactory
         this.defaultContext = defaultContext;
     }
 
-    public Object getService(Bundle bundle, ServiceRegistration registration) {
+    public ProviderAdminService getService(Bundle bundle, ServiceRegistration registration) {
         return new ProviderAdminService(defaultContext, bundle.getBundleContext());
     }
 
-    public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
-        ((ProviderAdminService) service).close();
+    public void ungetService(Bundle bundle, ServiceRegistration registration, ProviderAdminService service) {
+        service.close();
     }
 
 }

Copied: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ServicePair.java (from r1824943, aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextProvider.java)
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ServicePair.java?p2=aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ServicePair.java&p1=aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextProvider.java&r1=1824943&r2=1824944&rev=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ContextProvider.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/ServicePair.java Wed Feb 21 09:05:04 2018
@@ -18,28 +18,40 @@
  */
 package org.apache.aries.jndi;
 
+import org.apache.aries.jndi.startup.Activator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 
-import javax.naming.Context;
-import javax.naming.NamingException;
+import java.util.function.Supplier;
 
-public abstract class ContextProvider {
-    private final ServiceReference<?> reference;
-    private final BundleContext bc;
-
-    public ContextProvider(BundleContext ctx, ServiceReference<?> reference) {
-        bc = ctx;
-        this.reference = reference;
+public class ServicePair<T> implements Supplier<T> {
+
+    private BundleContext ctx;
+    private ServiceReference<?> ref;
+    private T svc;
+
+    public ServicePair(BundleContext context, ServiceReference<T> serviceRef) {
+        this.ctx = context;
+        this.ref = serviceRef;
+    }
+
+    public ServicePair(BundleContext context, ServiceReference<?> serviceRef, T service) {
+        this.ctx = context;
+        this.ref = serviceRef;
+        this.svc = service;
+    }
+
+    @SuppressWarnings("unchecked")
+    public T get() {
+        return svc != null ? svc : ref != null ? (T) Activator.getService(ctx, ref) : null;
     }
 
     public boolean isValid() {
-        return (reference.getBundle() != null);
+        return ref.getBundle() != null;
     }
 
-    public void close() throws NamingException {
-        if (bc != null) bc.ungetService(reference);
+    public ServiceReference<?> getReference() {
+        return ref;
     }
 
-    public abstract Context getContext() throws NamingException;
 }

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/URLContextProvider.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/URLContextProvider.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/URLContextProvider.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/URLContextProvider.java Wed Feb 21 09:05:04 2018
@@ -41,9 +41,7 @@ public class URLContextProvider extends
         try {
             return (Context) factory.getObjectInstance(null, null, null, environment);
         } catch (Exception e) {
-            NamingException ne = new NamingException();
-            ne.initCause(e);
-            throw ne;
+            throw (NamingException) new NamingException().initCause(e);
         }
     }
 }

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/Utils.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/Utils.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/Utils.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/Utils.java Wed Feb 21 09:05:04 2018
@@ -19,22 +19,26 @@
 package org.apache.aries.jndi;
 
 import org.apache.aries.util.nls.MessageUtil;
-import org.osgi.framework.*;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.BundleReference;
 import org.osgi.service.jndi.JNDIConstants;
 
 import javax.naming.NamingException;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.*;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.function.Function;
+import java.util.function.Supplier;
 
 /**
  */
 public final class Utils {
 
-    public static final Comparator<ServiceReference<?>> SERVICE_REFERENCE_COMPARATOR =
-            new ServiceReferenceComparator();
     public static final MessageUtil MESSAGES = MessageUtil.createMessageUtil(Utils.class, "org.apache.aries.jndi.nls.jndiMessages");
 
     /**
@@ -49,17 +53,12 @@ public final class Utils {
      * @return the bundle context for the caller.
      * @throws NamingException
      */
-    public static BundleContext getBundleContext(final Map<?, ?> env,
-                                                 final Class<?> namingClass) {
-        return AccessController.doPrivileged(new PrivilegedAction<BundleContext>() {
-            public BundleContext run() {
-                return doGetBundleContext(env, namingClass);
-            }
-        });
+    public static BundleContext getBundleContext(final Map<?, ?> env, final Class<?> namingClass) {
+        return doPrivileged(() -> doGetBundleContext(env, namingClass));
     }
 
     private static BundleContext doGetBundleContext(Map<?, ?> env, Class<?> namingClass) {
-        BundleContext result = null;
+        BundleContext result;
 
         Object bc = (env == null) ? null : env.get(JNDIConstants.BUNDLE_CONTEXT);
 
@@ -115,11 +114,7 @@ public final class Utils {
     }
 
     public static String getSystemProperty(final String key, final String defaultValue) {
-        return AccessController.doPrivileged(new PrivilegedAction<String>() {
-            public String run() {
-                return System.getProperty(key, defaultValue);
-            }
-        });
+        return doPrivileged(() -> System.getProperty(key, defaultValue));
     }
 
     public static Hashtable<?, ?> toHashtable(Map<?, ?> map) {
@@ -127,76 +122,65 @@ public final class Utils {
         if (map instanceof Hashtable<?, ?>) {
             env = (Hashtable<?, ?>) map;
         } else if (map == null) {
-            env = new Hashtable<Object, Object>();
+            env = new Hashtable<>();
         } else {
             env = new Hashtable<Object, Object>(map);
         }
         return env;
     }
 
-    public static <T> T doPrivileged(PrivilegedExceptionAction<T> action) throws Exception {
-        try {
-            return AccessController.doPrivileged(action);
-        } catch (PrivilegedActionException e) {
-            Exception cause = e.getException();
-            throw cause;
-        }
+    public static <T> T doPrivileged(Supplier<T> action) {
+        return AccessController.doPrivileged((PrivilegedAction<T>) action::get);
     }
 
-    public static <T> T doPrivilegedNaming(PrivilegedExceptionAction<T> action) throws NamingException {
-        try {
-            return AccessController.doPrivileged(action);
-        } catch (PrivilegedActionException e) {
-            Exception cause = e.getException();
-            if (cause instanceof NamingException) {
-                throw (NamingException) cause;
-            } else {
-                NamingException ex = new NamingException(cause.getMessage());
-                ex.initCause(cause);
-                throw ex;
-            }
+    private static class StackFinder extends SecurityManager {
+        public Class<?>[] getClassContext() {
+            return super.getClassContext();
         }
     }
 
-    public static <T> Collection<ServiceReference<T>> getReferencesPrivileged(final BundleContext ctx, final Class<T> clazz) {
-        return AccessController.doPrivileged(new PrivilegedAction<Collection<ServiceReference<T>>>() {
-            public Collection<ServiceReference<T>> run() {
-                try {
-                    ServiceReference<?>[] refs = ctx.getServiceReferences(clazz.getName(), null);
-                    List<ServiceReference<T>> list = new ArrayList<ServiceReference<T>>();
-                    if (refs != null) {
-                        for (ServiceReference<?> ref : refs) {
-                            list.add((ServiceReference<T>) ref);
-                        }
-                    }
-                    Collections.sort(list, Utils.SERVICE_REFERENCE_COMPARATOR);
-                    return list;
-                } catch (InvalidSyntaxException ise) {
-                    // should not happen
-                    throw new RuntimeException(MESSAGES.getMessage("null.is.invalid.filter"), ise);
-                }
-            }
-        });
+    public static <U, V> Iterator<V> map(Iterator<U> iterator, Function<U, V> mapper) {
+        return new MappedIterator<>(iterator, mapper);
     }
 
-    public static <T> T getServicePrivileged(final BundleContext ctx, final ServiceReference<T> ref) {
-        return AccessController.doPrivileged(new PrivilegedAction<T>() {
-            public T run() {
-                return ctx.getService(ref);
-            }
-        });
-    }
+    private static class MappedIterator<U, V> implements Iterator<V> {
 
-    private static class StackFinder extends SecurityManager {
-        public Class<?>[] getClassContext() {
-            return super.getClassContext();
+        private final Iterator<U> iterator;
+        private final Function<U, V> mapper;
+        private V nextElement;
+        private boolean hasNext;
+
+        public MappedIterator(Iterator<U> iterator, Function<U, V> mapper) {
+            this.iterator = iterator;
+            this.mapper = mapper;
+            nextMatch();
         }
-    }
 
-    private static class ServiceReferenceComparator implements Comparator<ServiceReference<?>> {
-        public int compare(ServiceReference<?> o1, ServiceReference<?> o2) {
-            return o2.compareTo(o1);
+        @Override
+        public boolean hasNext() {
+            return hasNext;
         }
-    }
 
+        @Override
+        public V next() {
+            if (!hasNext) {
+                throw new NoSuchElementException();
+            }
+            return nextMatch();
+        }
+
+        private V nextMatch() {
+            V oldMatch = nextElement;
+            while (iterator.hasNext()) {
+                V o = mapper.apply(iterator.next());
+                if (o != null) {
+                    hasNext = true;
+                    nextElement = o;
+                    return oldMatch;
+                }
+            }
+            hasNext = false;
+            return oldMatch;
+        }
+    }
 }

Modified: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/startup/Activator.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/startup/Activator.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/startup/Activator.java (original)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/startup/Activator.java Wed Feb 21 09:05:04 2018
@@ -20,25 +20,22 @@ package org.apache.aries.jndi.startup;
 
 import org.apache.aries.jndi.*;
 import org.apache.aries.jndi.spi.AugmenterInvoker;
-import org.apache.aries.jndi.spi.EnvironmentAugmentation;
-import org.apache.aries.jndi.spi.EnvironmentUnaugmentation;
-import org.apache.aries.jndi.tracker.ServiceTrackerCustomizers;
+import org.apache.aries.jndi.tracker.CachingServiceTracker;
 import org.apache.aries.jndi.urls.URLObjectFactoryFinder;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
+import org.osgi.framework.*;
 import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.service.jndi.JNDIConstants;
 import org.osgi.service.jndi.JNDIContextManager;
 import org.osgi.service.jndi.JNDIProviderAdmin;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.osgi.util.tracker.BundleTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.naming.NamingException;
 import javax.naming.spi.*;
 import java.lang.reflect.Field;
-import java.util.Arrays;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * The activator for this bundle makes sure the static classes in it are
@@ -48,90 +45,88 @@ public class Activator implements Bundle
 
     private static final Logger LOGGER = LoggerFactory.getLogger(Activator.class.getName());
 
-    private static String FORCE_BUILDER = "org.apache.aries.jndi.force.builder";
-    private static InitialContextFactoryBuilder originalICFBuilder;
-    private static ObjectFactoryBuilder originalOFBuilder;
-    private static volatile ServiceTracker<InitialContextFactoryBuilder, ServiceReference<InitialContextFactoryBuilder>> icfBuilders;
-    private static volatile ServiceTracker<URLObjectFactoryFinder, ServiceReference<URLObjectFactoryFinder>> urlObjectFactoryFinders;
-    private static volatile ServiceTracker<InitialContextFactory, ServiceReference<InitialContextFactory>> initialContextFactories;
-    private static volatile ServiceTracker<ObjectFactory, ServiceReference<ObjectFactory>> objectFactories;
-    private static volatile ServiceTracker<EnvironmentAugmentation, ServiceReference<EnvironmentAugmentation>> environmentAugmentors;
-    private static volatile ServiceTracker<EnvironmentUnaugmentation, ServiceReference<EnvironmentUnaugmentation>> environmentUnaugmentors;
-    private OSGiInitialContextFactoryBuilder icfBuilder;
-    private OSGiObjectFactoryBuilder ofBuilder;
+    private static final String FORCE_BUILDER = "org.apache.aries.jndi.force.builder";
 
-    /*
-     * There are no public API to reset the InitialContextFactoryBuilder or
-     * ObjectFactoryBuilder on the NamingManager so try to use reflection.
-     */
-    private static void setField(Class<?> expectedType, Object value, boolean saveOriginal) throws IllegalStateException {
-        try {
-            for (Field field : NamingManager.class.getDeclaredFields()) {
-                if (expectedType.equals(field.getType())) {
-                    field.setAccessible(true);
-                    if (saveOriginal) {
-                        if (expectedType.equals(InitialContextFactoryBuilder.class)) {
-                            originalICFBuilder = (InitialContextFactoryBuilder) field.get(null);
-                        } else {
-                            originalOFBuilder = (ObjectFactoryBuilder) field.get(null);
-                        }
-                    }
+    private static volatile Activator instance;
 
-                    field.set(null, value);
-                }
-            }
-        } catch (Throwable t) {
-            // Ignore
-            LOGGER.debug("Error setting field.", t);
-            throw new IllegalStateException(t);
-        }
-    }
+    private BundleTracker<ServiceCache> bundleServiceCaches;
 
-    public static ServiceReference<InitialContextFactoryBuilder>[] getInitialContextFactoryBuilderServices() {
-        ServiceReference<InitialContextFactoryBuilder>[] refs = icfBuilders.getServiceReferences();
+    private CachingServiceTracker<InitialContextFactoryBuilder> icfBuilders;
+    private CachingServiceTracker<URLObjectFactoryFinder> urlObjectFactoryFinders;
+    private CachingServiceTracker<InitialContextFactory> initialContextFactories;
+    private CachingServiceTracker<ObjectFactory> objectFactories;
 
-        if (refs != null) {
-            Arrays.sort(refs, Utils.SERVICE_REFERENCE_COMPARATOR);
-        }
+    private AugmenterInvoker augmenterInvoker;
 
-        return refs;
+    private InitialContextFactoryBuilder originalICFBuilder;
+    private OSGiInitialContextFactoryBuilder icfBuilder;
+
+    private ObjectFactoryBuilder originalOFBuilder;
+    private OSGiObjectFactoryBuilder ofBuilder;
+
+    public static Collection<ServiceReference<InitialContextFactoryBuilder>> getInitialContextFactoryBuilderServices() {
+        return instance.icfBuilders.getReferences();
     }
 
-    public static ServiceReference<InitialContextFactory>[] getInitialContextFactoryServices() {
-        ServiceReference<InitialContextFactory>[] refs = initialContextFactories.getServiceReferences();
+    public static Collection<ServiceReference<InitialContextFactory>> getInitialContextFactoryServices() {
+        return instance.initialContextFactories.getReferences();
+    }
 
-        if (refs != null) {
-            Arrays.sort(refs, Utils.SERVICE_REFERENCE_COMPARATOR);
-        }
+    public static Collection<ServiceReference<URLObjectFactoryFinder>> getURLObjectFactoryFinderServices() {
+        return instance.urlObjectFactoryFinders.getReferences();
+    }
 
-        return refs;
+    public static ServiceReference<ObjectFactory> getUrlFactory(String scheme) {
+        return instance.objectFactories.find(scheme);
     }
 
-    public static ServiceReference<URLObjectFactoryFinder>[] getURLObjectFactoryFinderServices() {
-        ServiceReference<URLObjectFactoryFinder>[] refs = urlObjectFactoryFinders.getServiceReferences();
+    public static ServiceReference<InitialContextFactory> getInitialContextFactory(String interfaceName) {
+        return instance.initialContextFactories.find(interfaceName);
+    }
 
-        if (refs != null) {
-            Arrays.sort(refs, Utils.SERVICE_REFERENCE_COMPARATOR);
-        }
-        return refs;
+    public static AugmenterInvoker getAugmenterInvoker() {
+        return instance.augmenterInvoker;
     }
 
-    public static Object[] getEnvironmentAugmentors() {
-        return environmentAugmentors.getServices();
+    public static <T> T getService(BundleContext context, ServiceReference<T> ref) {
+        ServiceCache cache = instance.bundleServiceCaches.getObject(context.getBundle());
+        return cache.getService(ref);
     }
 
-    public static Object[] getEnvironmentUnaugmentors() {
-        return environmentUnaugmentors.getServices();
+    public static <T> Collection<ServiceReference<T>> getReferences(BundleContext context, Class<T> clazz) {
+        ServiceCache cache = instance.bundleServiceCaches.getObject(context.getBundle());
+        return cache.getReferences(clazz);
     }
 
+    public static <T> Iterable<T> getServices(BundleContext context, Class<T> clazz) {
+        ServiceCache cache = instance.bundleServiceCaches.getObject(context.getBundle());
+        Collection<ServiceReference<T>> refs = cache.getReferences(clazz);
+        return () -> Utils.map(refs.iterator(), ref -> Activator.getService(context, ref));
+    }
+
+
     public void start(BundleContext context) {
+        instance = this;
 
-        initialContextFactories = initServiceTracker(context, InitialContextFactory.class, ServiceTrackerCustomizers.ICF_CACHE);
-        objectFactories = initServiceTracker(context, ObjectFactory.class, ServiceTrackerCustomizers.URL_FACTORY_CACHE);
-        icfBuilders = initServiceTracker(context, InitialContextFactoryBuilder.class, ServiceTrackerCustomizers.<InitialContextFactoryBuilder>LAZY());
-        urlObjectFactoryFinders = initServiceTracker(context, URLObjectFactoryFinder.class, ServiceTrackerCustomizers.<URLObjectFactoryFinder>LAZY());
-        environmentAugmentors = initServiceTracker(context, EnvironmentAugmentation.class, null);
-        environmentUnaugmentors = initServiceTracker(context, EnvironmentUnaugmentation.class, null);
+        bundleServiceCaches = new BundleTracker<ServiceCache>(context, Bundle.ACTIVE, null) {
+            @Override
+            public ServiceCache addingBundle(Bundle bundle, BundleEvent event) {
+                return new ServiceCache(bundle.getBundleContext());
+            }
+            @Override
+            public void modifiedBundle(Bundle bundle, BundleEvent event, ServiceCache object) {
+            }
+            @Override
+            public void removedBundle(Bundle bundle, BundleEvent event, ServiceCache object) {
+                object.close();
+            }
+        };
+        bundleServiceCaches.open();
+
+        initialContextFactories = new CachingServiceTracker<>(context, InitialContextFactory.class, Activator::getInitialContextFactoryInterfaces);
+        objectFactories = new CachingServiceTracker<>(context, ObjectFactory.class, Activator::getObjectFactorySchemes);
+        icfBuilders = new CachingServiceTracker<>(context, InitialContextFactoryBuilder.class);
+        urlObjectFactoryFinders = new CachingServiceTracker<>(context, URLObjectFactoryFinder.class);
 
         try {
             OSGiInitialContextFactoryBuilder builder = new OSGiInitialContextFactoryBuilder();
@@ -140,7 +135,7 @@ public class Activator implements Bundle
             } catch (IllegalStateException e) {
                 // use reflection to force the builder to be used
                 if (forceBuilder(context)) {
-                    setField(InitialContextFactoryBuilder.class, builder, true);
+                    originalICFBuilder = swapStaticField(InitialContextFactoryBuilder.class, builder);
                 }
             }
             icfBuilder = builder;
@@ -160,7 +155,7 @@ public class Activator implements Bundle
             } catch (IllegalStateException e) {
                 // use reflection to force the builder to be used
                 if (forceBuilder(context)) {
-                    setField(ObjectFactoryBuilder.class, builder, true);
+                    originalOFBuilder = swapStaticField(ObjectFactoryBuilder.class, builder);
                 }
             }
             ofBuilder = builder;
@@ -186,10 +181,32 @@ public class Activator implements Bundle
                 null);
 
         context.registerService(AugmenterInvoker.class.getName(),
-                AugmenterInvokerImpl.getInstance(),
+                augmenterInvoker = new AugmenterInvokerImpl(context),
                 null);
     }
 
+    public void stop(BundleContext context) {
+        bundleServiceCaches.close();
+
+        /*
+         * Try to reset the InitialContextFactoryBuilder and ObjectFactoryBuilder
+         * on the NamingManager.
+         */
+        if (icfBuilder != null) {
+            swapStaticField(InitialContextFactoryBuilder.class, originalICFBuilder);
+        }
+        if (ofBuilder != null) {
+            swapStaticField(ObjectFactoryBuilder.class, originalOFBuilder);
+        }
+
+        icfBuilders.close();
+        urlObjectFactoryFinders.close();
+        objectFactories.close();
+        initialContextFactories.close();
+
+        instance = null;
+    }
+
     private boolean forceBuilder(BundleContext context) {
         String forceBuilderProp = context.getProperty(FORCE_BUILDER);
         if (forceBuilderProp != null) {
@@ -214,30 +231,87 @@ public class Activator implements Bundle
         return "";
     }
 
-    private <S, T> ServiceTracker<S, T> initServiceTracker(BundleContext context,
-                                                           Class<S> type, ServiceTrackerCustomizer<S, T> custom) {
-        ServiceTracker<S, T> t = new ServiceTracker<S, T>(context, type, custom);
-        t.open();
-        return t;
+    /*
+     * There are no public API to reset the InitialContextFactoryBuilder or
+     * ObjectFactoryBuilder on the NamingManager so try to use reflection.
+     */
+    private static <T> T swapStaticField(Class<T> expectedType, Object value) throws IllegalStateException {
+        try {
+            for (Field field : NamingManager.class.getDeclaredFields()) {
+                if (expectedType.equals(field.getType())) {
+                    field.setAccessible(true);
+                    T original = expectedType.cast(field.get(null));
+                    field.set(null, value);
+                    return original;
+                }
+            }
+        } catch (Throwable t) {
+            // Ignore
+            LOGGER.debug("Error setting field.", t);
+            throw new IllegalStateException(t);
+        }
+        throw new IllegalStateException("Error setting field: no field found for type " + expectedType);
     }
 
-    public void stop(BundleContext context) {
-        /*
-         * Try to reset the InitialContextFactoryBuilder and ObjectFactoryBuilder
-         * on the NamingManager.
-         */
-        if (icfBuilder != null) {
-            setField(InitialContextFactoryBuilder.class, originalICFBuilder, false);
+    private static List<String> getInitialContextFactoryInterfaces(ServiceReference<InitialContextFactory> ref) {
+        String[] interfaces = (String[]) ref.getProperty(Constants.OBJECTCLASS);
+        List<String> resultList = new ArrayList<>();
+        for (String interfaceName : interfaces) {
+            if (!InitialContextFactory.class.getName().equals(interfaceName)) {
+                resultList.add(interfaceName);
+            }
         }
-        if (ofBuilder != null) {
-            setField(ObjectFactoryBuilder.class, originalOFBuilder, false);
+
+        return resultList;
+    }
+
+    private static List<String> getObjectFactorySchemes(ServiceReference<ObjectFactory> reference) {
+        Object scheme = reference.getProperty(JNDIConstants.JNDI_URLSCHEME);
+        List<String> result;
+
+        if (scheme instanceof String) {
+            result = new ArrayList<>();
+            result.add((String) scheme);
+        } else if (scheme instanceof String[]) {
+            result = Arrays.asList((String[]) scheme);
+        } else {
+            result = Collections.emptyList();
         }
 
-        icfBuilders.close();
-        urlObjectFactoryFinders.close();
-        objectFactories.close();
-        initialContextFactories.close();
-        environmentAugmentors.close();
-        environmentUnaugmentors.close();
+        return result;
     }
+
+    private static class ServiceCache {
+
+        private final BundleContext context;
+        private final Map<ServiceReference<?>, Object> cache = new ConcurrentHashMap<>();
+        private final Map<Class<?>, CachingServiceTracker<?>> trackers = new ConcurrentHashMap<>();
+
+        ServiceCache(BundleContext context) {
+            this.context = context;
+        }
+
+        @SuppressWarnings("unchecked")
+        <T> T getService(ServiceReference<T> ref) {
+            return (T) cache.computeIfAbsent(ref, this::doGetService);
+        }
+
+        @SuppressWarnings("unchecked")
+        <T> Collection<ServiceReference<T>> getReferences(Class<T> clazz) {
+            return (List) trackers.computeIfAbsent(clazz, c -> new CachingServiceTracker<>(context, c)).getReferences();
+        }
+
+        void close() {
+            cache.forEach(this::doUngetService);
+        }
+
+        Object doGetService(ServiceReference<?> ref) {
+            return Utils.doPrivileged(() -> context.getService(ref));
+        }
+
+        void doUngetService(ServiceReference<?> ref, Object svc) {
+            Utils.doPrivileged(() -> context.ungetService(ref));
+        }
+    }
+
 }

Added: aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/tracker/CachingServiceTracker.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/tracker/CachingServiceTracker.java?rev=1824944&view=auto
==============================================================================
--- aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/tracker/CachingServiceTracker.java (added)
+++ aries/trunk/jndi/jndi-core/src/main/java/org/apache/aries/jndi/tracker/CachingServiceTracker.java Wed Feb 21 09:05:04 2018
@@ -0,0 +1,86 @@
+/*
+ * 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.aries.jndi.tracker;
+
+import org.apache.aries.jndi.Utils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+import java.util.*;
+import java.util.function.Function;
+
+public class CachingServiceTracker<S> extends ServiceTracker<S, ServiceReference<S>> {
+
+    /** The cached references */
+    private volatile Map<String, ServiceReference<S>> cache;
+    /** The funtion to obtain the identifiers */
+    private final Function<ServiceReference<S>, Iterable<String>> properties;
+
+    public CachingServiceTracker(BundleContext context, Class<S> clazz) {
+        this(context, clazz, ref -> Collections.emptyList());
+    }
+
+    public CachingServiceTracker(BundleContext context, Class<S> clazz, Function<ServiceReference<S>, Iterable<String>> properties) {
+        super(context, clazz, null);
+        this.properties = properties;
+        open();
+    }
+
+    public ServiceReference<S> find(String identifier) {
+        Map<String, ServiceReference<S>> c = cache;
+        if (c == null) {
+            synchronized (this) {
+                if (cache == null) {
+                    cache = new HashMap<>();
+                    for (ServiceReference<S> ref : getReferences()) {
+                        for (String key : properties.apply(ref)) {
+                            cache.putIfAbsent(key, ref);
+                        }
+                    }
+                }
+                c = cache;
+            }
+        }
+        return c.get(identifier);
+    }
+
+    public List<ServiceReference<S>> getReferences() {
+        ServiceReference<S>[] refs = Utils.doPrivileged(this::getServiceReferences);
+        if (refs != null) {
+            Arrays.sort(refs, Comparator.reverseOrder());
+            return Arrays.asList(refs);
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    public synchronized ServiceReference<S> addingService(ServiceReference<S> reference) {
+        cache = null;
+        return reference;
+    }
+
+    public synchronized void removedService(ServiceReference<S> reference, ServiceReference<S> service) {
+        cache = null;
+    }
+
+    public void modifiedService(ServiceReference<S> reference, ServiceReference<S> service) {
+        cache = null;
+    }
+}

Modified: aries/trunk/jndi/jndi-core/src/test/java/org/apache/aries/jndi/InitialContextTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/jndi/jndi-core/src/test/java/org/apache/aries/jndi/InitialContextTest.java?rev=1824944&r1=1824943&r2=1824944&view=diff
==============================================================================
--- aries/trunk/jndi/jndi-core/src/test/java/org/apache/aries/jndi/InitialContextTest.java (original)
+++ aries/trunk/jndi/jndi-core/src/test/java/org/apache/aries/jndi/InitialContextTest.java Wed Feb 21 09:05:04 2018
@@ -58,7 +58,9 @@ public class InitialContextTest {
      */
     @Before
     public void setup() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
-        bc = Skeleton.newMock(new BundleContextMock(), BundleContext.class);
+        BundleContextMock mock = new BundleContextMock();
+        mock.addBundle(mock.getBundle());
+        bc = Skeleton.newMock(mock, BundleContext.class);
         activator = new Activator();
         activator.start(bc);
     }