FELIX-4113 Factories not disposed when the extension provider is leaving

* ServiceTracker.addingService() is expecting a non-null value if interested in the service
 * I was returning null (missed that in refactor), so serviceRemoval() was never called

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1491436 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java
index ff1d540..f737505 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java
@@ -19,6 +19,8 @@
 
 package org.apache.felix.ipojo.extender.internal.linker;
 
+import static java.lang.String.format;
+
 import org.apache.felix.ipojo.*;
 import org.apache.felix.ipojo.extender.ExtensionDeclaration;
 import org.apache.felix.ipojo.extender.InstanceDeclaration;
@@ -102,7 +104,7 @@
      * @throws InvalidSyntaxException cannot happen
      */
     private void initExtensionTracker() throws InvalidSyntaxException {
-        String filter = String.format(
+        String filter = format(
                 "(&(objectclass=%s)(%s=%s))",
                 ExtensionDeclaration.class.getName(),
                 ExtensionDeclaration.EXTENSION_NAME_PROPERTY,
@@ -124,7 +126,7 @@
             // Track instance for:
             // * this component AND
             // * this component's version OR no version
-            filter = String.format(
+            filter = format(
                     "(&(objectClass=%s)(%s=%s)(|(%s=%s)(!(%s=*))))",
                     InstanceDeclaration.class.getName(),
                     InstanceDeclaration.COMPONENT_NAME_PROPERTY,
@@ -136,7 +138,7 @@
         } else {
             // Track instance for:
             // * this component AND no version
-            filter = String.format(
+            filter = format(
                     "(&(objectClass=%s)(%s=%s)(!(%s=*)))",
                     InstanceDeclaration.class.getName(),
                     InstanceDeclaration.COMPONENT_NAME_PROPERTY,
@@ -161,15 +163,6 @@
      * Stopping the management.
      */
     public void stop() {
-        try {
-            IPojoFactory factory = m_future.get();
-            if (factory != null) {
-                factory.dispose();
-            }
-        } catch (Exception e) {
-            // Ignored.
-        }
-
         m_instanceTracker.close();
         m_extensionTracker.close();
     }
@@ -218,14 +211,17 @@
 
                             return factory;
                         } catch (FactoryBuilderException e) {
-                            m_declaration.unbind(String.format("Cannot build '%s' factory instance", m_declaration.getExtension()), e);
+                            m_declaration.unbind(format("Cannot build '%s' factory instance", m_declaration.getExtension()), e);
                         } catch (Throwable t) {
-                            m_declaration.unbind(String.format("Error during '%s' factory instance creation", m_declaration.getExtension()), t);
+                            m_declaration.unbind(format("Error during '%s' factory instance creation", m_declaration.getExtension()), t);
                         }
 
                         return null;
                     }
                 });
+                // Return something, otherwise, ServiceTracker think that we're not interested
+                // in this service and never call us back on disposal.
+                return service;
             }
 
             return null;
@@ -236,6 +232,7 @@
 
         public void removedService(ServiceReference reference, Object o) {
 
+            ExtensionDeclaration extensionDeclaration = (ExtensionDeclaration) o;
             // Then stop the factory
             try {
                 IPojoFactory factory = m_future.get();
@@ -243,7 +240,8 @@
                 if (factory != null) {
                     factory.removeFactoryStateListener(ManagedType.this);
                     factory.dispose();
-                    m_declaration.unbind("Extension '%s' is missing");
+                    m_declaration.unbind(format("Extension '%s' is missing",
+                                                extensionDeclaration.getExtensionName()));
                 }
             } catch (InterruptedException e) {
                 m_declaration.unbind("Could not create Factory", e);
@@ -270,14 +268,14 @@
                     if (!reference.getBundle().equals(m_bundleContext.getBundle())) {
                         Bundle origin = m_bundleContext.getBundle();
                         instanceDeclaration.unbind(
-                                String.format("Component '%s/%s' is private. It only accept instances " +
-                                        "from bundle %s/%s [%d] (instance bundle origin: %d)",
-                                        m_declaration.getComponentName(),
-                                        m_declaration.getComponentVersion(),
-                                        origin.getSymbolicName(),
-                                        origin.getVersion(),
-                                        origin.getBundleId(),
-                                        reference.getBundle().getBundleId())
+                                format("Component '%s/%s' is private. It only accept instances " +
+                                               "from bundle %s/%s [%d] (instance bundle origin: %d)",
+                                       m_declaration.getComponentName(),
+                                       m_declaration.getComponentVersion(),
+                                       origin.getSymbolicName(),
+                                       origin.getVersion(),
+                                       origin.getBundleId(),
+                                       reference.getBundle().getBundleId())
                         );
                         return null;
                     }
@@ -296,14 +294,14 @@
 
                             return instance;
                         } catch (UnacceptableConfiguration c) {
-                            instanceDeclaration.unbind(String.format("Instance configuration is invalid (component:%s/%s, bundle:%d)",
-                                    m_declaration.getComponentName(),
-                                    m_declaration.getComponentVersion(),
-                                    reference.getBundle().getBundleId()),
+                            instanceDeclaration.unbind(format("Instance configuration is invalid (component:%s/%s, bundle:%d)",
+                                                              m_declaration.getComponentName(),
+                                                              m_declaration.getComponentVersion(),
+                                                              reference.getBundle().getBundleId()),
                                     c);
                         } catch (MissingHandlerException e) {
                             instanceDeclaration.unbind(
-                                    String.format(
+                                    format(
                                             "Component '%s/%s' (required for instance creation) is missing some handlers",
                                             m_declaration.getComponentName(),
                                             m_declaration.getComponentVersion()
@@ -311,7 +309,7 @@
                                     e);
                         } catch (ConfigurationException e) {
                             instanceDeclaration.unbind(
-                                    String.format(
+                                    format(
                                             "Instance configuration is incorrect for component '%s/%s'",
                                             m_declaration.getComponentName(),
                                             m_declaration.getComponentVersion()),
@@ -337,9 +335,9 @@
                 instance = future.get();
                 // It is possible that the instance couldn't be created
                 if (instance != null) {
-                    String message = String.format("Factory for Component '%s/%s' is missing",
-                            instance.getFactory().getName(),
-                            m_declaration.getComponentVersion());
+                    String message = format("Factory for Component '%s/%s' is missing",
+                                            instance.getFactory().getName(),
+                                            m_declaration.getComponentVersion());
                     instanceDeclaration.unbind(message);
 
                     instance.stop();
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/linker/ManagedTypeTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/linker/ManagedTypeTestCase.java
new file mode 100644
index 0000000..6762b2e
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/linker/ManagedTypeTestCase.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.linker;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.apache.felix.ipojo.extender.ExtensionDeclaration;
+import org.apache.felix.ipojo.extender.TypeDeclaration;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+
+import junit.framework.TestCase;
+
+/**
+ * User: guillaume
+ * Date: 10/06/13
+ * Time: 13:32
+ */
+public class ManagedTypeTestCase extends TestCase {
+
+    @Mock
+    private BundleContext bundleContext;
+    @Mock
+    private QueueService queueService;
+    @Mock
+    private TypeDeclaration declaration;
+    @Mock
+    private Filter filter;
+
+
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(bundleContext.createFilter(anyString())).thenReturn(filter);
+    }
+
+    public void testStartingManagedType() throws Exception {
+
+        String filterStr = String.format(
+                "(&(objectclass=%s)(%s=%s))",
+                ExtensionDeclaration.class.getName(),
+                ExtensionDeclaration.EXTENSION_NAME_PROPERTY,
+                "test"
+        );
+
+        when(declaration.getExtension()).thenReturn("test");
+        when(filter.toString()).thenReturn(filterStr);
+
+        ManagedType managedType = new ManagedType(bundleContext, queueService, declaration);
+        managedType.start();
+
+        verify(bundleContext).getAllServiceReferences(null, filterStr);
+    }
+
+}