[FELIX-3761] When a bundle registers a service, the bundle lock is obtained without any real purpose

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1421958 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
index d7bbfa0..bbdd980 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
@@ -343,7 +343,7 @@
             }
         }
 
-        return m_felix.registerService(m_bundle, clazzes, svcObj, dict);
+        return m_felix.registerService(this, clazzes, svcObj, dict);
     }
 
     public <S> ServiceRegistration<S> registerService(
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index b360a61..b72d606 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -763,6 +763,10 @@
                 // so create a gate for that purpose.
                 m_shutdownGate = new ThreadGate();
 
+                // Start services
+                m_fwkWiring.start();
+                m_fwkStartLevel.start();
+
                 try
                 {
                     Felix.m_secureAction.startActivator(
@@ -3258,7 +3262,7 @@
      * @return A <code>ServiceRegistration</code> object or null.
     **/
     ServiceRegistration registerService(
-        BundleImpl bundle, String[] classNames, Object svcObj, Dictionary dict)
+        BundleContextImpl context, String[] classNames, Object svcObj, Dictionary dict)
     {
         if (classNames == null)
         {
@@ -3269,50 +3273,31 @@
             throw new IllegalArgumentException("Service object cannot be null.");
         }
 
-        // Acquire bundle lock.
-        try
-        {
-            acquireBundleLock(bundle, Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING);
-        }
-        catch (IllegalStateException ex)
-        {
-            throw new IllegalStateException(
-                "Can only register services while bundle is active or activating.");
-        }
-
         ServiceRegistration reg = null;
 
-        try
+        // Check to make sure that the service object is
+        // an instance of all service classes; ignore if
+        // service object is a service factory.
+        if (!(svcObj instanceof ServiceFactory))
         {
-            // Check to make sure that the service object is
-            // an instance of all service classes; ignore if
-            // service object is a service factory.
-            if (!(svcObj instanceof ServiceFactory))
+            for (int i = 0; i < classNames.length; i++)
             {
-                for (int i = 0; i < classNames.length; i++)
+                Class clazz = Util.loadClassUsingClass(svcObj.getClass(), classNames[i], m_secureAction);
+                if (clazz == null)
                 {
-                    Class clazz = Util.loadClassUsingClass(svcObj.getClass(), classNames[i], m_secureAction);
-                    if (clazz == null)
-                    {
-                        throw new IllegalArgumentException(
-                            "Cannot cast service: " + classNames[i]);
-                    }
-                    else if (!clazz.isAssignableFrom(svcObj.getClass()))
-                    {
-                        throw new IllegalArgumentException(
-                            "Service object is not an instance of \""
-                            + classNames[i] + "\".");
-                    }
+                    throw new IllegalArgumentException(
+                        "Cannot cast service: " + classNames[i]);
+                }
+                else if (!clazz.isAssignableFrom(svcObj.getClass()))
+                {
+                    throw new IllegalArgumentException(
+                        "Service object is not an instance of \""
+                        + classNames[i] + "\".");
                 }
             }
+        }
 
-            reg = m_registry.registerService(bundle, classNames, svcObj, dict);
-        }
-        finally
-        {
-            // Always release bundle lock.
-            releaseBundleLock(bundle);
-        }
+        reg = m_registry.registerService(context, classNames, svcObj, dict);
 
         // Check to see if this a listener hook; if so, then we need
         // to invoke the callback with all existing service listeners.
diff --git a/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java b/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
index d6e7e79..e6509ce 100644
--- a/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
@@ -37,19 +37,25 @@
     private static final int STARTLEVEL_IDX = 1;
 
     private final Felix m_felix;
+    private final ServiceRegistry m_registry;
     private final List m_requests = new ArrayList();
     private final List<FrameworkListener[]> m_requestListeners
         = new ArrayList<FrameworkListener[]>();
-    private final ServiceRegistration<StartLevel> m_slReg;
+    private ServiceRegistration<StartLevel> m_slReg;
     private Thread m_thread = null;
 
     FrameworkStartLevelImpl(Felix felix, ServiceRegistry registry)
     {
         m_felix = felix;
-        m_slReg = registry.registerService(felix,
-            new String[] { StartLevel.class.getName() },
-            new StartLevelImpl(felix),
-            null);
+        m_registry = registry;
+    }
+
+    void start()
+    {
+        m_slReg = m_registry.registerService(m_felix._getBundleContext(),
+                new String[] { StartLevel.class.getName() },
+                new StartLevelImpl(m_felix),
+                null);
     }
 
     // Should only be called hold requestList lock.
diff --git a/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
index da7bfee..8ad803c 100644
--- a/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
@@ -31,20 +31,26 @@
 class FrameworkWiringImpl implements FrameworkWiring, Runnable
 {
     private final Felix m_felix;
+    private final ServiceRegistry m_registry;
     private final List<Collection<Bundle>> m_requests = new ArrayList();
     private final List<FrameworkListener[]> m_requestListeners
         = new ArrayList<FrameworkListener[]>();
-    private final ServiceRegistration<PackageAdmin> m_paReg;
+    private ServiceRegistration<PackageAdmin> m_paReg;
     private Thread m_thread = null;
 
 
     public FrameworkWiringImpl(Felix felix, ServiceRegistry registry)
     {
         m_felix = felix;
-        m_paReg = registry.registerService(felix,
-            new String[] { PackageAdmin.class.getName() },
-            new PackageAdminImpl(felix),
-            null);
+        m_registry = registry;
+    }
+
+    void start()
+    {
+        m_paReg = m_registry.registerService(m_felix._getBundleContext(),
+                new String[] { PackageAdmin.class.getName() },
+                new PackageAdminImpl(m_felix),
+                null);
     }
 
     /**
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
index b604de2..9bf5d31 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
@@ -23,6 +23,7 @@
 import org.apache.felix.framework.capabilityset.SimpleFilter;
 import org.apache.felix.framework.wiring.BundleCapabilityImpl;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceException;
@@ -101,12 +102,14 @@
 
     // Caller is expected to fire REGISTERED event.
     public ServiceRegistration registerService(
-        Bundle bundle, String[] classNames, Object svcObj, Dictionary dict)
+        BundleContext context, String[] classNames, Object svcObj, Dictionary dict)
     {
         ServiceRegistrationImpl reg = null;
 
         synchronized (this)
         {
+            Bundle bundle = context.getBundle();
+
             // Create the service registration.
             reg = new ServiceRegistrationImpl(
                 this, bundle, classNames, new Long(m_currentServiceId++), svcObj, dict);
diff --git a/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java b/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
index c8c8a9e..6f3b92f 100644
--- a/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
@@ -42,6 +42,11 @@
         Bundle b = (Bundle) control.getMock();
         control.replay();
 
+        MockControl controlContext = MockControl.createNiceControl(BundleContext.class);
+        BundleContext c = (BundleContext) controlContext.getMock();
+        controlContext.expectAndReturn(c.getBundle(), b);
+        controlContext.replay();
+
         ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
         EventHook hook = new EventHook()
         {
@@ -53,7 +58,7 @@
         assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size());
-        ServiceRegistration reg = sr.registerService(b, new String [] {EventHook.class.getName()}, hook, new Hashtable());
+        ServiceRegistration reg = sr.registerService(c, new String [] {EventHook.class.getName()}, hook, new Hashtable());
         assertEquals(1, sr.getHooks(EventHook.class).size());
         assertTrue(sr.getHooks(EventHook.class).iterator().next() instanceof ServiceReference);
         assertSame(reg.getReference(), sr.getHooks(EventHook.class).iterator().next());
@@ -73,6 +78,11 @@
         Bundle b = (Bundle) control.getMock();
         control.replay();
 
+        MockControl controlContext = MockControl.createNiceControl(BundleContext.class);
+        BundleContext c = (BundleContext) controlContext.getMock();
+        controlContext.expectAndReturn(c.getBundle(), b);
+        controlContext.replay();
+
         ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
         MockControl sfControl = MockControl.createNiceControl(ServiceFactory.class);
         sfControl.replay();
@@ -81,7 +91,7 @@
         assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size());
-        ServiceRegistration reg = sr.registerService(b, new String [] {EventHook.class.getName()}, sf, new Hashtable());
+        ServiceRegistration reg = sr.registerService(c, new String [] {EventHook.class.getName()}, sf, new Hashtable());
         assertEquals(1, sr.getHooks(EventHook.class).size());
         assertSame(reg.getReference(), sr.getHooks(EventHook.class).iterator().next());
         assertSame(sf, ((ServiceRegistrationImpl) reg).getService());
@@ -100,6 +110,11 @@
         Bundle b = (Bundle) control.getMock();
         control.replay();
 
+        MockControl controlContext = MockControl.createNiceControl(BundleContext.class);
+        BundleContext c = (BundleContext) controlContext.getMock();
+        controlContext.expectAndReturn(c.getBundle(), b);
+        controlContext.replay();
+
         ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
         FindHook hook = new FindHook()
         {
@@ -112,7 +127,7 @@
         assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size());
-        ServiceRegistration reg = sr.registerService(b, new String [] {FindHook.class.getName()}, hook, new Hashtable());
+        ServiceRegistration reg = sr.registerService(c, new String [] {FindHook.class.getName()}, hook, new Hashtable());
         assertEquals(1, sr.getHooks(FindHook.class).size());
         assertSame(reg.getReference(), sr.getHooks(FindHook.class).iterator().next());
         assertSame(hook, ((ServiceRegistrationImpl) reg).getService());
@@ -131,6 +146,11 @@
         Bundle b = (Bundle) control.getMock();
         control.replay();
 
+        MockControl controlContext = MockControl.createNiceControl(BundleContext.class);
+        BundleContext c = (BundleContext) controlContext.getMock();
+        controlContext.expectAndReturn(c.getBundle(), b);
+        controlContext.replay();
+
         ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
         MockControl sfControl = MockControl.createNiceControl(ServiceFactory.class);
         sfControl.replay();
@@ -139,7 +159,7 @@
         assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size());
-        ServiceRegistration reg = sr.registerService(b, new String [] {FindHook.class.getName()}, sf, new Hashtable());
+        ServiceRegistration reg = sr.registerService(c, new String [] {FindHook.class.getName()}, sf, new Hashtable());
         assertEquals(1, sr.getHooks(FindHook.class).size());
         assertSame(reg.getReference(), sr.getHooks(FindHook.class).iterator().next());
         assertSame(sf, ((ServiceRegistrationImpl) reg).getService());
@@ -158,6 +178,11 @@
         Bundle b = (Bundle) control.getMock();
         control.replay();
 
+        MockControl controlContext = MockControl.createNiceControl(BundleContext.class);
+        BundleContext c = (BundleContext) controlContext.getMock();
+        controlContext.expectAndReturn(c.getBundle(), b);
+        controlContext.replay();
+
         ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
         ListenerHook hook = new ListenerHook()
         {
@@ -173,7 +198,7 @@
         assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size());
-        ServiceRegistration reg = sr.registerService(b, new String [] {ListenerHook.class.getName()}, hook, new Hashtable());
+        ServiceRegistration reg = sr.registerService(c, new String [] {ListenerHook.class.getName()}, hook, new Hashtable());
         assertEquals(1, sr.getHooks(ListenerHook.class).size());
         assertSame(reg.getReference(), sr.getHooks(ListenerHook.class).iterator().next());
         assertSame(hook, ((ServiceRegistrationImpl) reg).getService());
@@ -192,6 +217,11 @@
         Bundle b = (Bundle) control.getMock();
         control.replay();
 
+        MockControl controlContext = MockControl.createNiceControl(BundleContext.class);
+        BundleContext c = (BundleContext) controlContext.getMock();
+        controlContext.expectAndReturn(c.getBundle(), b);
+        controlContext.replay();
+
         ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
         MockControl sfControl = MockControl.createNiceControl(ServiceFactory.class);
         sfControl.replay();
@@ -200,7 +230,7 @@
         assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size());
-        ServiceRegistration reg = sr.registerService(b, new String [] {ListenerHook.class.getName()}, sf, new Hashtable());
+        ServiceRegistration reg = sr.registerService(c, new String [] {ListenerHook.class.getName()}, sf, new Hashtable());
         assertEquals(1, sr.getHooks(ListenerHook.class).size());
         assertSame(reg.getReference(), sr.getHooks(ListenerHook.class).iterator().next());
         assertSame(sf, ((ServiceRegistrationImpl) reg).getService());
@@ -219,6 +249,11 @@
         Bundle b = (Bundle) control.getMock();
         control.replay();
 
+        MockControl controlContext = MockControl.createNiceControl(BundleContext.class);
+        BundleContext c = (BundleContext) controlContext.getMock();
+        controlContext.expectAndReturn(c.getBundle(), b);
+        controlContext.replay();
+
         ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
         class CombinedService implements ListenerHook, FindHook, EventHook, Runnable
         {
@@ -249,7 +284,7 @@
         assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size());
-        ServiceRegistration reg = sr.registerService(b, new String [] {
+        ServiceRegistration reg = sr.registerService(c, new String [] {
             Runnable.class.getName(),
             ListenerHook.class.getName(),
             FindHook.class.getName(),
@@ -276,12 +311,17 @@
         Bundle b = (Bundle) control.getMock();
         control.replay();
 
+        MockControl controlContext = MockControl.createNiceControl(BundleContext.class);
+        BundleContext c = (BundleContext) controlContext.getMock();
+        controlContext.expectAndReturn(c.getBundle(), b);
+        controlContext.replay();
+
         ServiceRegistry sr = new ServiceRegistry(new Logger(), null);
         String svcObj = "hello";
         assertEquals("Precondition failed", 0, sr.getHooks(EventHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(FindHook.class).size());
         assertEquals("Precondition failed", 0, sr.getHooks(ListenerHook.class).size());
-        ServiceRegistration reg = sr.registerService(b, new String [] {String.class.getName()}, svcObj, new Hashtable());
+        ServiceRegistration reg = sr.registerService(c, new String [] {String.class.getName()}, svcObj, new Hashtable());
         assertEquals("Postcondition failed", 0, sr.getHooks(EventHook.class).size());
         assertEquals("Postcondition failed", 0, sr.getHooks(FindHook.class).size());
         assertEquals("Postcondition failed", 0, sr.getHooks(ListenerHook.class).size());
diff --git a/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java b/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java
index c4622a7..837167d 100644
--- a/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/util/EventDispatcherTest.java
@@ -48,6 +48,7 @@
         final Bundle b1 = getMockBundle();
         final Bundle b2 = getMockBundle();
         final Bundle b3 = getMockBundle();
+        final Bundle b4 = getMockBundle();
 
         final Set calledHooks = new HashSet();
         final EventHook eh1 = new EventHook()
@@ -79,8 +80,8 @@
 
         Logger logger = new Logger();
         ServiceRegistry registry = new ServiceRegistry(logger, null);
-        registry.registerService(null, new String [] {EventHook.class.getName()}, eh1, new Hashtable());
-        registry.registerService(null, new String [] {EventHook.class.getName()}, eh2, new Hashtable());
+        registry.registerService(b4.getBundleContext(), new String [] {EventHook.class.getName()}, eh1, new Hashtable());
+        registry.registerService(b4.getBundleContext(), new String [] {EventHook.class.getName()}, eh2, new Hashtable());
 
         // -- Set up event dispatcher
         EventDispatcher ed = new EventDispatcher(logger, registry);