You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by "Tuomas Kiviaho (JIRA)" <ji...@apache.org> on 2014/12/09 17:39:12 UTC

[jira] [Commented] (FELIX-4598) BundleDependency can effectively track only one bundle

    [ https://issues.apache.org/jira/browse/FELIX-4598?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14239624#comment-14239624 ] 

Tuomas Kiviaho commented on FELIX-4598:
---------------------------------------

I noticed that {{ResourceDependencyImpl}} suffers from similar scenario. On top of this both seem not to call {{invokeAdded}} (as {{ServiceDependency}} does) when dependency is required but service has already been instantiated.

{code}
Index: src/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
===================================================================
--- src/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java	(revision 1488970)
+++ src/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java	(working copy)
@@ -35,6 +35,7 @@
 import org.apache.felix.dm.ResourceDependency;
 import org.apache.felix.dm.ResourceHandler;
 import org.apache.felix.dm.impl.Logger;
+import org.apache.felix.dm.impl.SerialExecutor;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.log.LogService;
@@ -56,16 +57,16 @@
     private URL m_trackedResource;
     private List m_resources = new ArrayList();
     private List m_resourceProperties = new ArrayList();
-    private URL m_resourceInstance;
-    private Dictionary m_resourcePropertiesInstance;
     private boolean m_propagate;
     private Object m_propagateCallbackInstance;
     private String m_propagateCallbackMethod;
+    private SerialExecutor m_executor;
     
     public ResourceDependencyImpl(BundleContext context, Logger logger) {
         super(logger);
         m_context = context;
         m_autoConfig = true;
+        m_executor = new SerialExecutor(logger);
     }
     
     public ResourceDependencyImpl(ResourceDependencyImpl prototype) {
@@ -80,6 +81,7 @@
         m_resourceFilter = prototype.m_resourceFilter;
         m_trackedResource = prototype.m_trackedResource;
         m_propagate = prototype.m_propagate;
+        m_executor = prototype.m_executor;
     }
     
     public Dependency createCopy() {
@@ -151,6 +153,9 @@
             for (int i = 0; i < services.length; i++) {
                 DependencyService ds = (DependencyService) services[i];
                 if (counter == 1) {
+                    if (ds.isInstantiated() && isInstanceBound() && isRequired()) {
+                        invokeAdded(ds, resource, resourceProperties);
+                    }
                     ds.dependencyAvailable(this);
                     if (!isRequired()) {
                         invokeAdded(ds, resource, resourceProperties);
@@ -438,17 +443,44 @@
         return URL.class;
     }
 
-    public void invokeAdded(DependencyService service) {
-        // we remember these for future reference, needed for required callbacks
-        m_resourceInstance = lookupResource();
-        m_resourcePropertiesInstance = lookupResourceProperties();
-        invokeAdded(service, m_resourceInstance, m_resourcePropertiesInstance);
+    public void invokeAdded(final DependencyService service) {
+        Runnable task = new Runnable() {
+
+            @Override
+            public void run() {
+                URL[] resourceInstances;
+                Dictionary[] resourcePropertiesInstances;
+                synchronized (this) {
+                    resourceInstances = (URL[]) m_resources.toArray(new URL[m_resources.size()]);
+                    resourcePropertiesInstances = (Dictionary[]) m_resourceProperties.toArray(new Dictionary[m_resourceProperties.size()]);
+                }
+                for (int i = 0; i < resourceInstances.length; i++) {
+                    invokeAdded(service, resourceInstances[i], resourcePropertiesInstances[i]);
+                }
+            }
+            
+        };
+        m_executor.execute(task);
     }
 
-    public void invokeRemoved(DependencyService service) {
-        invokeRemoved(service, m_resourceInstance, m_resourcePropertiesInstance);
-        m_resourceInstance = null;
-        m_resourcePropertiesInstance = null;
+    public void invokeRemoved(final DependencyService service) {
+        Runnable task = new Runnable() {
+
+            @Override
+            public void run() {
+                URL[] resourceInstances;
+                Dictionary[] resourcePropertiesInstances;
+                synchronized (this) {
+                    resourceInstances = (URL[]) m_resources.toArray(new URL[m_resources.size()]);
+                    resourcePropertiesInstances = (Dictionary[]) m_resourceProperties.toArray(new Dictionary[m_resourceProperties.size()]);
+                }
+                for (int i = 0; i < resourceInstances.length; i++) {
+                    invokeAdded(service, resourceInstances[i], resourcePropertiesInstances[i]);
+                }
+            }
+            
+        };
+        m_executor.execute(task);
     }
 
     public ResourceDependency setPropagate(boolean propagate) {
{code}

> BundleDependency can effectively track only one bundle
> ------------------------------------------------------
>
>                 Key: FELIX-4598
>                 URL: https://issues.apache.org/jira/browse/FELIX-4598
>             Project: Felix
>          Issue Type: Bug
>          Components: Dependency Manager
>    Affects Versions: dependencymanager.runtime-3.2.0
>            Reporter: Tuomas Kiviaho
>            Assignee: Pierre De Rop
>             Fix For: dependencymanager-4.0.0
>
>
> Bundles are delivered to callbacks after component is instantiated but prior to that they can't be. This is the case with ServiceDependencies as well but unlike them after component instantiation the tracker is not used as source of bundles but instead lookup method is used. {{ServiceDependencyImpl}} uses this approach only to gain properties and auto configuration instance.
> I suggest that {{BundleDependencyImpl#invokeAdded(DependencyService service)}} would be implemented in similar manner that {{ServiceDependencyImpl#invokeAdded(DependencyService service)}} has been (perhaps also utilizing the serial executor) .



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)