FELIX-4405 Fix concurrency bug in determining bind method parameter types

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1618546 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
index 61af7c1..201b2ac 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
@@ -22,6 +22,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -66,12 +67,6 @@
     
     private final ReferenceMetadata.ReferenceScope m_referenceScope;
 
-//    private static final int SERVICE_REFERENCE = 1;
-//    private static final int SERVICE_OBJECT = 2;
-//    private static final int SERVICE_OBJECT_AND_MAP = 3;
-
-//    private int m_paramStyle;
-    
     private enum ParamType { 
         serviceReference,
         serviceObjects,
@@ -79,7 +74,8 @@
         map
     }
     
-    private List<ParamType> m_paramTypes = new ArrayList<ParamType>();
+    //initialized for cases where there is no method.
+    private volatile List<ParamType> m_paramTypes = Collections.emptyList();
 
 
     public BindMethod( final String methodName,
@@ -141,7 +137,7 @@
                 {
                     logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null );
                 }
-                m_paramTypes.add(ParamType.serviceReference);
+                m_paramTypes = Collections.singletonList(ParamType.serviceReference);
                 return method;
             }
         }
@@ -160,7 +156,7 @@
                 {
                     logger.log( LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null );
                 }
-                m_paramTypes.add(ParamType.serviceObjects);
+                m_paramTypes = Collections.singletonList(ParamType.serviceObjects);
                 return method;
             }
         }
@@ -188,7 +184,7 @@
                 method = getServiceObjectMethod( targetClass, parameterClass, acceptPrivate, acceptPackage, logger );
                 if ( method != null )
                 {
-                    m_paramTypes.add(ParamType.serviceType);
+                    m_paramTypes = Collections.singletonList(ParamType.serviceType);
                     return method;
                 }
             }
@@ -203,7 +199,7 @@
                 method = getServiceObjectAssignableMethod( targetClass, parameterClass, acceptPrivate, acceptPackage, logger );
                 if ( method != null )
                 {
-                    m_paramTypes.add(ParamType.serviceType);
+                    m_paramTypes = Collections.singletonList(ParamType.serviceType);
                     return method;
                 }
             }
@@ -222,8 +218,10 @@
                     method = getServiceObjectWithMapMethod( targetClass, parameterClass, acceptPrivate, acceptPackage, logger );
                     if ( method != null )
                     {
-                        m_paramTypes.add(ParamType.serviceType);
-                        m_paramTypes.add(ParamType.map);
+                        List<ParamType> paramTypes = new ArrayList<ParamType>(2);
+                        paramTypes.add(ParamType.serviceType);
+                        paramTypes.add(ParamType.map);
+                        m_paramTypes = paramTypes;
                         return method;
                     }
                 }
@@ -239,8 +237,10 @@
                         acceptPackage );
                     if ( method != null )
                     {
-                        m_paramTypes.add(ParamType.serviceType);
-                        m_paramTypes.add(ParamType.map);
+                        List<ParamType> paramTypes = new ArrayList<ParamType>(2);
+                        paramTypes.add(ParamType.serviceType);
+                        paramTypes.add(ParamType.map);
+                        m_paramTypes = paramTypes;
                         return method;
                     }
                 }
@@ -258,17 +258,18 @@
                         Class<?>[] parameterTypes = m.getParameterTypes();
                         boolean matches = true;
                         boolean specialMatch = true;
+                        List<ParamType> paramTypes = new ArrayList<ParamType>(parameterTypes.length);
                         for (Class<?> paramType: parameterTypes) {
                             if (paramType == SERVICE_REFERENCE_CLASS)
                             {
                                 if (specialMatch && parameterClass == SERVICE_REFERENCE_CLASS)
                                 {
                                     specialMatch = false;
-                                    m_paramTypes.add(ParamType.serviceType);
+                                    paramTypes.add(ParamType.serviceType);
                                 }
                                 else
                                 {
-                                    m_paramTypes.add(ParamType.serviceReference);
+                                    paramTypes.add(ParamType.serviceReference);
                                 }
                             }
                             else if (paramType == SERVICE_OBJECTS_CLASS)
@@ -276,11 +277,11 @@
                                 if (specialMatch && parameterClass == SERVICE_OBJECTS_CLASS)
                                 {
                                     specialMatch = false;
-                                    m_paramTypes.add(ParamType.serviceType);
+                                    paramTypes.add(ParamType.serviceType);
                                 }
                                 else
                                 {
-                                    m_paramTypes.add(ParamType.serviceObjects);
+                                    paramTypes.add(ParamType.serviceObjects);
                                 }
                             }
                             else if (paramType == Map.class)
@@ -288,21 +289,20 @@
                                 if (specialMatch && parameterClass == Map.class)
                                 {
                                     specialMatch = false;
-                                    m_paramTypes.add(ParamType.serviceType);
+                                    paramTypes.add(ParamType.serviceType);
                                 }
                                 else
                                 {
-                                    m_paramTypes.add(ParamType.map);
+                                    paramTypes.add(ParamType.map);
                                 }
                             }
                             else if (paramType.isAssignableFrom( parameterClass ) )
                             {
-                                m_paramTypes.add(ParamType.serviceType);
+                                paramTypes.add(ParamType.serviceType);
                             }
                             else
                             {
                                 matches = false;
-                                m_paramTypes.clear();
                                 break;
                             }
                         }
@@ -310,6 +310,7 @@
                         {
                             if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
                             {
+                                m_paramTypes = paramTypes;
                                 return m;
                             }
                             suitableMethodNotAccessible = true;
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index 0fd5224..6c5d9f3 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -1572,7 +1572,7 @@
         if ( !getServiceObject( componentContext, m_bindMethods.getBind(), refPair ))
         {
             m_componentManager.log( LogService.LOG_WARNING,
-                    "DependencyManager : invokeUpdatedMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
+                    "DependencyManager : invokeBindMethod : Service not available from service registry for ServiceReference {0} for reference {1}",
                     new Object[] {refPair.getRef(), getName()}, null );
             return false;