felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pde...@apache.org
Subject svn commit: r1630561 - in /felix/sandbox/pderop/dependencymanager-prototype: org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/ org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/ o...
Date Thu, 09 Oct 2014 19:16:56 GMT
Author: pderop
Date: Thu Oct  9 19:16:56 2014
New Revision: 1630561

URL: http://svn.apache.org/r1630561
Log:
FELIX-4426: Improvevement: you can now inject dependencies in an Iterable<> field, and
the field may be final
instead of volatile (see org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/SpellChecker.java
as an example). 


Modified:
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AutoConfigTest.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/SpellChecker.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/annot/SpellChecker.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AutoConfigTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AutoConfigTest.java?rev=1630561&r1=1630560&r2=1630561&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AutoConfigTest.java
(original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/AutoConfigTest.java
Thu Oct  9 19:16:56 2014
@@ -2,6 +2,7 @@ package org.apache.felix.dm.itest;
 
 import java.util.Collection;
 import java.util.Dictionary;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
@@ -19,7 +20,7 @@ public class AutoConfigTest extends Test
     public void testField() throws Exception {
         final DependencyManager dm = getDM();
         // Create a consumer, depending on some providers (autoconfig field).
-        ConsumerField consumer = new ConsumerField();
+        ConsumeWithProviderField consumer = new ConsumeWithProviderField();
         Component c = createConsumer(dm, consumer);
         // Create two providers
         Component p1 = createProvider(dm, 10, new Provider() {
@@ -46,9 +47,9 @@ public class AutoConfigTest extends Test
         m_ensure.waitForStep(2, 5000);
     }
     
-    public void testCollectionField() throws Exception {
+    public void testIterableField() throws Exception {
         final DependencyManager dm = getDM();
-        ConsumerCollection consumer = new ConsumerCollection();
+        ConsumerWithIterableField consumer = new ConsumerWithIterableField();
         Component c = createConsumer(dm, consumer);
         Component p1 = createProvider(dm, 10, new Provider() {
             public void run() { m_ensure.step(); }
@@ -83,7 +84,7 @@ public class AutoConfigTest extends Test
     
     public void testMapField() throws Exception {
         final DependencyManager dm = getDM();
-        ConsumerMap consumer = new ConsumerMap();
+        ConsumerWithMapField consumer = new ConsumerWithMapField();
         Component c = createConsumer(dm, consumer);
         Component p1 = createProvider(dm, 10, new Provider() {
             public void run() { m_ensure.step(); }
@@ -133,7 +134,7 @@ public class AutoConfigTest extends Test
     public static interface Provider extends Runnable {      
     }
     
-    public class ConsumerField {
+    public class ConsumeWithProviderField {
         volatile Provider m_provider;
         
         void start() {
@@ -151,15 +152,17 @@ public class AutoConfigTest extends Test
         }
     }
     
-    public class ConsumerCollection {
-        volatile ConcurrentLinkedQueue<Provider> m_providers;
+    public class ConsumerWithIterableField {
+        final Iterable<Provider> m_providers = new ConcurrentLinkedQueue<>();
         
         void start() {
             Assert.assertNotNull(m_providers);
-            Assert.assertTrue(m_providers.size() == 2);
+            int found = 0;
             for (Provider provider : m_providers) {
                 provider.run();
+                found ++;
             }
+            Assert.assertTrue(found == 2);
             m_ensure.step(3);
         }
         
@@ -172,18 +175,14 @@ public class AutoConfigTest extends Test
             }
             return null;
         }
-
-        Collection<Provider> getProviders() {
-            return m_providers;
-        }
         
         void stop() {
             m_ensure.step(4);
         }
     }    
     
-    public class ConsumerMap {
-        volatile ConcurrentHashMap<Provider, Dictionary> m_providers;
+    public class ConsumerWithMapField {
+        final Map<Provider, Dictionary> m_providers = new ConcurrentHashMap<>();
         
         void start() {
             Assert.assertNotNull(m_providers);

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/SpellChecker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/SpellChecker.java?rev=1630561&r1=1630560&r2=1630561&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/SpellChecker.java
(original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/SpellChecker.java
Thu Oct  9 19:16:56 2014
@@ -18,7 +18,7 @@
  */
 package org.apache.felix.dependencymanager.samples.dictionary;
 
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 import org.apache.felix.service.command.Descriptor;
 import org.osgi.service.log.LogService;
@@ -41,7 +41,7 @@ public class SpellChecker {
      * We'll store all Dictionaries in a CopyOnWrite list, in order to avoid method synchronization.
      * (Auto-Injected from Activator, at any time).
      */
-    private volatile CopyOnWriteArrayList<DictionaryService> m_dictionaries;
+    private final Iterable<DictionaryService> m_dictionaries = new ConcurrentLinkedQueue<>();
 
     /**
      * Lifecycle method callback, used to check if our service has been activated.

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/annot/SpellChecker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/annot/SpellChecker.java?rev=1630561&r1=1630560&r2=1630561&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/annot/SpellChecker.java
(original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/dictionary/annot/SpellChecker.java
Thu Oct  9 19:16:56 2014
@@ -18,7 +18,7 @@
  */
 package org.apache.felix.dependencymanager.samples.dictionary.annot;
 
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 import org.apache.felix.dm.annotation.api.Component;
 import org.apache.felix.dm.annotation.api.Property;
@@ -51,7 +51,7 @@ public class SpellChecker {
      * We'll store all Dictionaries in a CopyOnWrite list, in order to avoid method synchronization.
      */
     @ServiceDependency(service=DictionaryService.class)
-    private volatile CopyOnWriteArrayList<DictionaryService> m_dictionaries;
+    private final Iterable<DictionaryService> m_dictionaries = new ConcurrentLinkedQueue<>();
 
     /**
      * Lifecycle method callback, used to check if our service has been activated.

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java?rev=1630561&r1=1630560&r2=1630561&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java
(original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FieldUtil.java
Thu Oct  9 19:16:56 2014
@@ -6,6 +6,8 @@ import java.lang.reflect.Proxy;
 import java.util.Collection;
 import java.util.Dictionary;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 import org.apache.felix.dm.context.DependencyContext;
 import org.apache.felix.dm.context.Event;
@@ -20,13 +22,13 @@ public class FieldUtil {
      * Callbacks for fields to be injected
      */
     private interface FieldFunction {
-        // Inject an updated service in the given field for the the given target component
instance.
+        // Inject an updated service in the given field for the the given target.
         void injectField(Field f, Object target);
 
-        // Inject a Collection field  in the given field for the the given target component
instance.
-        void injectCollectionField(Field f, Object target);
+        // Inject an Iterable Field in the given target 
+        void injectIterableField(Field f, Object target);
 
-        // Inject a Map field (key = dependency service, value = Dictionary with dependency
service properties).
+        // Inject a Map field in the given target (key = dependency service, value = Dictionary
with dependency service properties).
         void injectMapField(Field f, Object target);
     }
 
@@ -55,7 +57,7 @@ public class FieldUtil {
                 }
             }
 
-            public void injectCollectionField(Field f, Object target) { // never called
+            public void injectIterableField(Field f, Object target) { // never called
             }
 
             public void injectMapField(Field f, Object target) { // never called
@@ -91,14 +93,17 @@ public class FieldUtil {
                 }
             }
 
-            public void injectCollectionField(Field f, Object target) {
+            public void injectIterableField(Field f, Object target) {
                 f.setAccessible(true);
                 Class<?> type = f.getType();
 
                 try {
-                    Collection<Object> coll = (Collection) type.newInstance();
-                    dc.copyToCollection(coll);
-                    f.set(target, coll);
+                    Iterable<Object> iter = (Iterable<Object>) f.get(target);
+                    if (iter == null) {
+                        iter = new ConcurrentLinkedQueue<Object>();
+                        f.set(target, iter);
+                    }
+                    dc.copyToCollection((Collection<Object>) iter);
                 } catch (Throwable e) {
                     logger.log(Logger.LOG_ERROR, "Could not set field " + f + " in class
"
                         + target.getClass().getName(), e);
@@ -108,12 +113,13 @@ public class FieldUtil {
             @Override
             public void injectMapField(Field f, Object target) {
                 f.setAccessible(true);
-                Class<?> type = f.getType();
-
                 try {
-                    Map map = (Map) type.newInstance();
+                    Map<Object, Dictionary> map = (Map) f.get(target);
+                    if (map == null) {
+                        map = new ConcurrentHashMap<>();
+                        f.set(target, map);
+                    }
                     dc.copyToMap(map);
-                    f.set(target, map);
                 } catch (Throwable e) {
                     logger.log(Logger.LOG_ERROR, "Could not set field " + f + " in class
"
                         + target.getClass().getName(), e);
@@ -148,7 +154,7 @@ public class FieldUtil {
                 }
             }
 
-            public void injectCollectionField(Field f, Object target) {
+            public void injectIterableField(Field f, Object target) {
                 if (update) {
                     return;
                 }
@@ -223,8 +229,8 @@ public class FieldUtil {
                             // Field type class must match injected service type
                             if (fieldType.equals(clazz)) {
                                 func.injectField(field, target);
-                            } else if (!strict && mayInjectToCollection(clazz, field,
true)) {
-                                func.injectCollectionField(field, target);
+                            } else if (!strict && mayInjectToIterable(clazz, field,
true)) {
+                                func.injectIterableField(field, target);
                             } else if (!strict && mayInjectToMap(clazz, field, true))
{
                                 func.injectMapField(field, target);
                             }
@@ -232,8 +238,8 @@ public class FieldUtil {
                             // Field type may be a superclass of the service type
                             if (fieldType.isAssignableFrom(clazz)) {
                                 func.injectField(field, target);
-                            } else if (!strict && mayInjectToCollection(clazz, field,
false)) {
-                                func.injectCollectionField(field, target);
+                            } else if (!strict && mayInjectToIterable(clazz, field,
false)) {
+                                func.injectIterableField(field, target);
                             } else if (!strict && mayInjectToMap(clazz, field, false))
{
                                 func.injectMapField(field, target);
                             } else {
@@ -251,9 +257,9 @@ public class FieldUtil {
         }
     }
 
-    private static boolean mayInjectToCollection(Class<?> clazz, Field field, boolean
strictClassEquality) {
+    private static boolean mayInjectToIterable(Class<?> clazz, Field field, boolean
strictClassEquality) {
         Class<?> fieldType = field.getType();
-        if (Collection.class.isAssignableFrom(fieldType)) {
+        if (Iterable.class.isAssignableFrom(fieldType)) {
             ParameterizedType parameterType = (ParameterizedType) field.getGenericType();
             if (parameterType == null) {
                 return false;



Mime
View raw message