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);
+ }
+
+}