You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2014/11/10 00:05:28 UTC

svn commit: r1637759 - in /felix/trunk/scr/src/main/java/org/apache/felix/scr/impl: helper/ metadata/

Author: cziegeler
Date: Sun Nov  9 23:05:27 2014
New Revision: 1637759

URL: http://svn.apache.org/r1637759
Log:
FELIX-4631 : [DS][R6/RFC212] Implement field injection. Move common class handling in utility class

Added:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java   (with props)
Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java?rev=1637759&r1=1637758&r2=1637759&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java Sun Nov  9 23:05:27 2014
@@ -46,8 +46,8 @@ public class ActivateMethod extends Base
     public ActivateMethod( final String methodName,
             final boolean methodRequired,
             final Class<?> componentClass,
-            final DSVersion dsVersion, 
-            final boolean configurableServiceProperties, 
+            final DSVersion dsVersion,
+            final boolean configurableServiceProperties,
             boolean supportsInterfaces )
     {
         super( methodName, methodRequired, componentClass, dsVersion, configurableServiceProperties );
@@ -55,6 +55,7 @@ public class ActivateMethod extends Base
     }
 
 
+    @Override
     protected Method doFindMethod( Class<?> targetClass, boolean acceptPrivate, boolean acceptPackage, SimpleLogger logger )
         throws SuitableMethodNotAccessibleException, InvocationTargetException
     {
@@ -92,7 +93,7 @@ public class ActivateMethod extends Base
                         {
                             return m;
                         }
-                        suitableMethodNotAccessible = true;                   
+                        suitableMethodNotAccessible = true;
                     }
                     if (getDSVersion().isDS13() && isAnnotation(type))
                     {
@@ -100,15 +101,15 @@ public class ActivateMethod extends Base
                         {
                             return m;
                         }
-                        suitableMethodNotAccessible = true;                   
+                        suitableMethodNotAccessible = true;
                     }
-                    if (type == MAP_CLASS)
+                    if (type == ClassUtils.MAP_CLASS)
                     {
                         if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
                         {
                             return m;
                         }
-                        suitableMethodNotAccessible = true;                   
+                        suitableMethodNotAccessible = true;
                     }
                     if (type == int.class)
                     {
@@ -116,7 +117,7 @@ public class ActivateMethod extends Base
                         {
                             return m;
                         }
-                        suitableMethodNotAccessible = true;                   
+                        suitableMethodNotAccessible = true;
                     }
                     if (type == Integer.class)
                     {
@@ -124,9 +125,9 @@ public class ActivateMethod extends Base
                         {
                             return m;
                         }
-                        suitableMethodNotAccessible = true;                   
+                        suitableMethodNotAccessible = true;
                     }
-                    
+
                 }
                 else if (parameterTypes.length > 1)
                 {
@@ -135,14 +136,14 @@ public class ActivateMethod extends Base
                     {
                         accept = type == COMPONENT_CONTEXT_CLASS
                             || type == BUNDLE_CONTEXT_CLASS
-                            || type == MAP_CLASS
+                            || type == ClassUtils.MAP_CLASS
                             || ( isDeactivate() && ( type == int.class || type == Integer.class))
                             || ( getDSVersion().isDS13() && isAnnotation(type));
-                        if ( !accept ) 
+                        if ( !accept )
                         {
                             break;
                         }
-                            
+
                     }
                     if (accept)
                     {
@@ -150,9 +151,9 @@ public class ActivateMethod extends Base
                         {
                             return m;
                         }
-                        suitableMethodNotAccessible = true;                                           
+                        suitableMethodNotAccessible = true;
                     }
-                    
+
                 }
                 else //no parameters
                 {
@@ -160,12 +161,12 @@ public class ActivateMethod extends Base
                     {
                         return m;
                     }
-                    suitableMethodNotAccessible = true;                   
+                    suitableMethodNotAccessible = true;
                 }
-                
+
             }
         }
-        
+
         if ( suitableMethodNotAccessible )
         {
             throw new SuitableMethodNotAccessibleException();
@@ -222,8 +223,8 @@ public class ActivateMethod extends Base
                     if (t2 == BUNDLE_CONTEXT_CLASS) return 1;
                     if (isAnnotation(t1)) return isAnnotation(t2)? 0: -1;
                     if (isAnnotation(t2)) return 1;
-                    if (t1 == MAP_CLASS) return -1;
-                    if (t2 == MAP_CLASS) return 1;
+                    if (t1 == ClassUtils.MAP_CLASS) return -1;
+                    if (t2 == ClassUtils.MAP_CLASS) return 1;
                     if (t1 == int.class) return -1;
                     if (t2 == int.class) return 1;
                     if (t1 == Integer.class) return -1;
@@ -239,14 +240,15 @@ public class ActivateMethod extends Base
 
     private boolean isAnnotation(final Class<?> t1)
     {
-        return t1.isAnnotation() || (m_supportsInterfaces && t1.isInterface() && !(t1 == MAP_CLASS));
+        return t1.isAnnotation() || (m_supportsInterfaces && t1.isInterface() && !(t1 == ClassUtils.MAP_CLASS));
     }
-    
 
+
+    @Override
     protected Object[] getParameters( Method method, ActivatorParameter rawParameter )
     {
         final Class<?>[] parameterTypes = method.getParameterTypes();
-        final ActivatorParameter ap = ( ActivatorParameter ) rawParameter;
+        final ActivatorParameter ap = rawParameter;
         final Object[] param = new Object[parameterTypes.length];
         for ( int i = 0; i < param.length; i++ )
         {
@@ -258,7 +260,7 @@ public class ActivateMethod extends Base
             {
                 param[i] = ap.getComponentContext().getBundleContext();
             }
-            else if ( parameterTypes[i] == MAP_CLASS )
+            else if ( parameterTypes[i] == ClassUtils.MAP_CLASS )
             {
                 // note: getProperties() returns a ReadOnlyDictionary which is a Map
                 param[i] = ap.getComponentContext().getProperties();
@@ -266,10 +268,10 @@ public class ActivateMethod extends Base
             else if ( parameterTypes[i] == INTEGER_CLASS || parameterTypes[i] == Integer.TYPE )
             {
                 param[i] = ap.getReason();
-            } 
+            }
             else
             {
-                param[i] = Annotations.toObject(parameterTypes[i], 
+                param[i] = Annotations.toObject(parameterTypes[i],
                     (Map<String, Object>) ap.getComponentContext().getProperties(),
                     ap.getComponentContext().getBundleContext().getBundle(), m_supportsInterfaces);
             }
@@ -279,11 +281,13 @@ public class ActivateMethod extends Base
     }
 
 
+    @Override
     protected String getMethodNamePrefix()
     {
         return "activate";
     }
 
+    @Override
     public MethodResult invoke( Object componentInstance, ActivatorParameter rawParameter, final MethodResult methodCallFailureResult, SimpleLogger logger )
     {
         if (methodExists( logger ))

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java?rev=1637759&r1=1637758&r2=1637759&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java Sun Nov  9 23:05:27 2014
@@ -37,9 +37,6 @@ import org.osgi.service.log.LogService;
 public abstract class BaseMethod<P>
 {
 
-    // class references to simplify parameter checking
-    protected static final Class<?> MAP_CLASS = Map.class;
-
     private final DSVersion dsVersion;
     private final boolean configurableServiceProperties;
 
@@ -401,7 +398,7 @@ public abstract class BaseMethod<P>
      */
     protected static boolean accept( final Method method, boolean acceptPrivate, boolean acceptPackage, boolean allowReturnValue )
     {
-        if (!(Void.TYPE == method.getReturnType() || (MAP_CLASS == method.getReturnType() && allowReturnValue)))
+        if (!(Void.TYPE == method.getReturnType() || (ClassUtils.MAP_CLASS == method.getReturnType() && allowReturnValue)))
         {
             return false;
         }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java?rev=1637759&r1=1637758&r2=1637759&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java Sun Nov  9 23:05:27 2014
@@ -26,18 +26,13 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.felix.scr.impl.Activator;
 import org.apache.felix.scr.impl.manager.ComponentContextImpl;
 import org.apache.felix.scr.impl.manager.RefPair;
 import org.apache.felix.scr.impl.metadata.DSVersion;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata.ReferenceScope;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceObjects;
-import org.osgi.framework.ServiceReference;
 import org.osgi.service.log.LogService;
-import org.osgi.service.packageadmin.ExportedPackage;
-import org.osgi.service.packageadmin.PackageAdmin;
 
 
 /**
@@ -46,24 +41,6 @@ import org.osgi.service.packageadmin.Pac
 public class BindMethod extends BaseMethod<BindParameters>
 implements org.apache.felix.scr.impl.helper.ReferenceMethod
 {
-
-    private static final Class<?> OBJECT_CLASS = Object.class;
-
-    protected static final Class<?> SERVICE_REFERENCE_CLASS = ServiceReference.class;
-    private static final Class<?> SERVICE_OBJECTS_CLASS;
-
-    static {
-        Class<?> serviceObjectsClass = null;
-        try {
-            serviceObjectsClass = ServiceObjects.class;
-        }
-        catch (Throwable t)
-        {
-            //can't load class
-        }
-        SERVICE_OBJECTS_CLASS = serviceObjectsClass;
-    }
-
     private final String m_referenceClassName;
 
     private final ReferenceMetadata.ReferenceScope m_referenceScope;
@@ -168,7 +145,7 @@ implements org.apache.felix.scr.impl.hel
         }
 
         // for further methods we need the class of the service object
-        final Class<?> parameterClass = getParameterClass( targetClass, logger );
+        final Class<?> parameterClass = ClassUtils.getClassFromComponentClassLoader( targetClass, m_referenceClassName, logger );
         if ( parameterClass != null )
         {
 
@@ -262,9 +239,9 @@ implements org.apache.felix.scr.impl.hel
                         boolean specialMatch = true;
                         List<ParamType> paramTypes = new ArrayList<ParamType>(parameterTypes.length);
                         for (Class<?> paramType: parameterTypes) {
-                            if (paramType == SERVICE_REFERENCE_CLASS)
+                            if (paramType == ClassUtils.SERVICE_REFERENCE_CLASS)
                             {
-                                if (specialMatch && parameterClass == SERVICE_REFERENCE_CLASS)
+                                if (specialMatch && parameterClass == ClassUtils.SERVICE_REFERENCE_CLASS)
                                 {
                                     specialMatch = false;
                                     paramTypes.add(ParamType.serviceType);
@@ -274,9 +251,9 @@ implements org.apache.felix.scr.impl.hel
                                     paramTypes.add(ParamType.serviceReference);
                                 }
                             }
-                            else if (paramType == SERVICE_OBJECTS_CLASS)
+                            else if (paramType == ClassUtils.SERVICE_OBJECTS_CLASS)
                             {
-                                if (specialMatch && parameterClass == SERVICE_OBJECTS_CLASS)
+                                if (specialMatch && parameterClass == ClassUtils.SERVICE_OBJECTS_CLASS)
                                 {
                                     specialMatch = false;
                                     paramTypes.add(ParamType.serviceType);
@@ -343,118 +320,6 @@ implements org.apache.felix.scr.impl.hel
         return null;
     }
 
-
-    /**
-     * Returns the class object representing the class of the service reference
-     * named by the {@link #m_referenceClassName} field. The class loader of
-     * the <code>targetClass</code> is used to load the service class.
-     * <p>
-     * It may well be possible, that the classloader of the target class cannot
-     * see the service object class, for example if the service reference is
-     * inherited from a component class of another bundle.
-     *
-     * @return The class object for the referred to service or <code>null</code>
-     *      if the class loader of the <code>targetClass</code> cannot see that
-     *      class.
-     */
-    private Class<?> getParameterClass( final Class<?> targetClass, SimpleLogger logger )
-    {
-        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-        {
-            logger.log(
-                LogService.LOG_DEBUG,
-                "getParameterClass: Looking for interface class {0} through loader of {1}",
-                    new Object[] {m_referenceClassName, targetClass.getName()}, null );
-        }
-
-        try
-        {
-            // need the class loader of the target class, which may be the
-            // system classloader, which case getClassLoader may retur null
-            ClassLoader loader = targetClass.getClassLoader();
-            if ( loader == null )
-            {
-                loader = ClassLoader.getSystemClassLoader();
-            }
-
-            final Class<?> referenceClass = loader.loadClass( m_referenceClassName );
-            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-            {
-                logger.log( LogService.LOG_DEBUG,
-                    "getParameterClass: Found class {0}", new Object[] {referenceClass.getName()}, null );
-            }
-            return referenceClass;
-        }
-        catch ( ClassNotFoundException cnfe )
-        {
-            // if we can't load the class, perhaps the method is declared in a
-            // super class so we try this class next
-        }
-
-        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-        {
-            logger.log( LogService.LOG_DEBUG,
-                "getParameterClass: Not found through component class, using PackageAdmin service", null );
-        }
-
-        // try to load the class with the help of the PackageAdmin service
-        PackageAdmin pa = ( PackageAdmin ) Activator.getPackageAdmin();
-        if ( pa != null )
-        {
-            final String referenceClassPackage = m_referenceClassName.substring( 0, m_referenceClassName
-                .lastIndexOf( '.' ) );
-            ExportedPackage[] pkg = pa.getExportedPackages( referenceClassPackage );
-            if ( pkg != null )
-            {
-                for ( int i = 0; i < pkg.length; i++ )
-                {
-                    try
-                    {
-                        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-                        {
-                            logger.log(
-                                LogService.LOG_DEBUG,
-                                "getParameterClass: Checking Bundle {0}/{1}",
-                                    new Object[] {pkg[i].getExportingBundle().getSymbolicName(), pkg[i].getExportingBundle().getBundleId()}, null );
-                        }
-
-                        Class<?> referenceClass = pkg[i].getExportingBundle().loadClass( m_referenceClassName );
-                        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-                        {
-                            logger.log( LogService.LOG_DEBUG,
-                                    "getParameterClass: Found class {0}", new Object[] {referenceClass.getName()}, null );
-                        }
-                        return referenceClass;
-                    }
-                    catch ( ClassNotFoundException cnfe )
-                    {
-                        // exported package does not provide the interface !!!!
-                    }
-                }
-            }
-            else if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-            {
-                logger.log( LogService.LOG_DEBUG,
-                    "getParameterClass: No bundles exporting package {0} found", new Object[] {referenceClassPackage}, null );
-            }
-        }
-        else if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-        {
-            logger.log( LogService.LOG_DEBUG,
-                "getParameterClass: PackageAdmin service not available, cannot find class", null );
-        }
-
-        // class cannot be found, neither through the component nor from an
-        // export, so we fall back to assuming Object
-        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-        {
-            logger.log( LogService.LOG_DEBUG,
-                "getParameterClass: No class found, falling back to class Object", null );
-        }
-        return OBJECT_CLASS;
-    }
-
-
     /**
      * Returns a method taking a single <code>ServiceReference</code> object
      * as a parameter or <code>null</code> if no such method exists.
@@ -478,7 +343,7 @@ implements org.apache.felix.scr.impl.hel
         throws SuitableMethodNotAccessibleException, InvocationTargetException
     {
         return getMethod( targetClass, getMethodName(), new Class[]
-            { SERVICE_REFERENCE_CLASS }, acceptPrivate, acceptPackage, logger );
+            { ClassUtils.SERVICE_REFERENCE_CLASS }, acceptPrivate, acceptPackage, logger );
     }
 
     private Method getServiceObjectsMethod( final Class<?> targetClass, boolean acceptPrivate, boolean acceptPackage, SimpleLogger logger )
@@ -487,7 +352,7 @@ implements org.apache.felix.scr.impl.hel
         if ( m_referenceScope == ReferenceMetadata.ReferenceScope.prototype )
         {
             return getMethod(targetClass, getMethodName(),
-                new Class[] { SERVICE_OBJECTS_CLASS }, acceptPrivate, acceptPackage,
+                new Class[] { ClassUtils.SERVICE_OBJECTS_CLASS }, acceptPrivate, acceptPackage,
                 logger);
         }
         return null;
@@ -641,7 +506,7 @@ implements org.apache.felix.scr.impl.hel
         InvocationTargetException
     {
         return getMethod( targetClass, getMethodName(), new Class[]
-            { parameterClass, MAP_CLASS }, acceptPrivate, acceptPackage, logger );
+            { parameterClass, ClassUtils.MAP_CLASS }, acceptPrivate, acceptPackage, logger );
     }
 
 
@@ -678,7 +543,7 @@ implements org.apache.felix.scr.impl.hel
             {
 
                 // parameters must be refclass,map
-                if ( parameters[0].isAssignableFrom( parameterClass ) && parameters[1] == MAP_CLASS )
+                if ( parameters[0].isAssignableFrom( parameterClass ) && parameters[1] == ClassUtils.MAP_CLASS )
                 {
                     if ( accept( method, acceptPrivate, acceptPackage, false ) )
                     {

Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java?rev=1637759&view=auto
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java (added)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java Sun Nov  9 23:05:27 2014
@@ -0,0 +1,170 @@
+/*
+ * 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.scr.impl.helper;
+
+
+import java.util.Map;
+
+import org.apache.felix.scr.impl.Activator;
+import org.osgi.framework.ServiceObjects;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+
+/**
+ * Utility methods for class handling used by method and field references.
+ */
+public class ClassUtils
+{
+
+    private static final Class<?> OBJECT_CLASS = Object.class;
+
+    public static final Class<?> SERVICE_REFERENCE_CLASS = ServiceReference.class;
+    public static final Class<?> SERVICE_OBJECTS_CLASS;
+
+    public static final Class<?> MAP_CLASS = Map.class;
+    public static final Class<?> MAP_ENTRY_CLASS = Map.Entry.class;
+
+
+    static {
+        Class<?> serviceObjectsClass = null;
+        try {
+            serviceObjectsClass = ServiceObjects.class;
+        }
+        catch (Throwable t)
+        {
+            //can't load class
+        }
+        SERVICE_OBJECTS_CLASS = serviceObjectsClass;
+    }
+
+    /**
+     * Returns the class object representing the class of the field reference
+     * The class loader of the component class is used to load the service class.
+     * <p>
+     * It may well be possible, that the class loader of the target class cannot
+     * see the service object class, for example if the service reference is
+     * inherited from a component class of another bundle.
+     *
+     * @return The class object for the referred to service or <code>null</code>
+     *      if the class loader of the <code>targetClass</code> cannot see that
+     *      class.
+     */
+    public static Class<?> getClassFromComponentClassLoader(
+            final Class<?> componentClass,
+            final String className,
+            final SimpleLogger logger )
+    {
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log(
+                LogService.LOG_DEBUG,
+                "getReferenceClass: Looking for interface class {0} through loader of {1}",
+                    new Object[] {className, componentClass.getName()}, null );
+        }
+
+        try
+        {
+            // need the class loader of the target class, which may be the
+            // system classloader, which case getClassLoader may retur null
+            ClassLoader loader = componentClass.getClassLoader();
+            if ( loader == null )
+            {
+                loader = ClassLoader.getSystemClassLoader();
+            }
+
+            final Class<?> referenceClass = loader.loadClass( className );
+            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG,
+                    "getParameterClass: Found class {0}", new Object[] {referenceClass.getName()}, null );
+            }
+            return referenceClass;
+        }
+        catch ( final ClassNotFoundException cnfe )
+        {
+            // if we can't load the class, perhaps the method is declared in a
+            // super class so we try this class next
+        }
+
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "getParameterClass: Not found through component class, using PackageAdmin service", null );
+        }
+
+        // try to load the class with the help of the PackageAdmin service
+        PackageAdmin pa = ( PackageAdmin ) Activator.getPackageAdmin();
+        if ( pa != null )
+        {
+            final String referenceClassPackage = className.substring( 0, className
+                .lastIndexOf( '.' ) );
+            ExportedPackage[] pkg = pa.getExportedPackages( referenceClassPackage );
+            if ( pkg != null )
+            {
+                for ( int i = 0; i < pkg.length; i++ )
+                {
+                    try
+                    {
+                        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+                        {
+                            logger.log(
+                                LogService.LOG_DEBUG,
+                                "getParameterClass: Checking Bundle {0}/{1}",
+                                    new Object[] {pkg[i].getExportingBundle().getSymbolicName(), pkg[i].getExportingBundle().getBundleId()}, null );
+                        }
+
+                        Class<?> referenceClass = pkg[i].getExportingBundle().loadClass( className );
+                        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+                        {
+                            logger.log( LogService.LOG_DEBUG,
+                                    "getParameterClass: Found class {0}", new Object[] {referenceClass.getName()}, null );
+                        }
+                        return referenceClass;
+                    }
+                    catch ( ClassNotFoundException cnfe )
+                    {
+                        // exported package does not provide the interface !!!!
+                    }
+                }
+            }
+            else if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG,
+                    "getParameterClass: No bundles exporting package {0} found", new Object[] {referenceClassPackage}, null );
+            }
+        }
+        else if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "getParameterClass: PackageAdmin service not available, cannot find class", null );
+        }
+
+        // class cannot be found, neither through the component nor from an
+        // export, so we fall back to assuming Object
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "getParameterClass: No class found, falling back to class Object", null );
+        }
+        return OBJECT_CLASS;
+    }
+}

Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ClassUtils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java?rev=1637759&r1=1637758&r2=1637759&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java Sun Nov  9 23:05:27 2014
@@ -27,6 +27,7 @@ import java.security.PrivilegedAction;
 
 import org.apache.felix.scr.impl.manager.ComponentContextImpl;
 import org.apache.felix.scr.impl.manager.RefPair;
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.log.LogService;
 
@@ -35,8 +36,8 @@ import org.osgi.service.log.LogService;
  */
 public class FieldHandler
 {
-    /** The name of the field. */
-    private final String fieldName;
+    /** The reference metadata. */
+    private final ReferenceMetadata metadata;
 
     /** The component class. */
     private final Class<?> componentClass;
@@ -53,14 +54,21 @@ public class FieldHandler
      * @param componentClass component class
      * @param referenceClassName service class name
      */
-    public FieldHandler( final String fieldName, final Class<?> componentClass,
-            final String referenceClassName)
+    public FieldHandler( final ReferenceMetadata metadata,
+            final Class<?> componentClass)
     {
-        this.fieldName = fieldName;
+        this.metadata = metadata;
         this.componentClass = componentClass;
         this.state = NotResolved.INSTANCE;
     }
 
+    /**
+     * Set the field.
+     * If the field is found, the state transitions to resolved, if the field is
+     * {@code null} the state transitions to not found.
+     * @param f The field or {@code null}.
+     * @param logger The logger
+     */
     private void setField( final Field f, final SimpleLogger logger )
     {
         this.field = f;
@@ -75,7 +83,7 @@ public class FieldHandler
         {
             state = NotFound.INSTANCE;
             logger.log(LogService.LOG_ERROR, "Field [{0}] not found; Component will fail",
-                new Object[] { this.fieldName }, null);
+                new Object[] { this.metadata.getField() }, null);
         }
     }
 
@@ -91,7 +99,8 @@ public class FieldHandler
      *      trying to find the requested field.
      * @param logger
      */
-    private Field findField( final SimpleLogger logger ) throws InvocationTargetException
+    private Field findField( final SimpleLogger logger )
+    throws InvocationTargetException
     {
         final Class<?> targetClass = this.componentClass;
         final ClassLoader targetClasslLoader = targetClass.getClassLoader();
@@ -105,7 +114,7 @@ public class FieldHandler
             if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
             {
                 logger.log( LogService.LOG_DEBUG,
-                    "Locating field " + this.fieldName + " in class " + theClass.getName(), null );
+                    "Locating field " + this.metadata.getField() + " in class " + theClass.getName(), null );
             }
 
             try
@@ -121,7 +130,7 @@ public class FieldHandler
                 // log and return null
                 logger.log( LogService.LOG_ERROR,
                     "findField: Suitable but non-accessible field {0} found in class {1}, subclass of {2}", new Object[]
-                        { this.fieldName, theClass.getName(), targetClass.getName() }, null );
+                        { this.metadata.getField(), theClass.getName(), targetClass.getName() }, null );
                 break;
             }
 
@@ -164,14 +173,16 @@ public class FieldHandler
      * @throws InvocationTargetException If an unexpected Throwable is caught
      *      trying to find the requested field.
      */
-    private Field getField( final Class<?> clazz, final boolean acceptPrivate,
-            final boolean acceptPackage, final SimpleLogger logger )
+    private Field getField( final Class<?> clazz,
+            final boolean acceptPrivate,
+            final boolean acceptPackage,
+            final SimpleLogger logger )
     throws SuitableMethodNotAccessibleException, InvocationTargetException
     {
         try
         {
             // find the declared field in this class
-            final Field field = clazz.getDeclaredField( this.fieldName );
+            final Field field = clazz.getDeclaredField( this.metadata.getField() );
 
             // accept public and protected fields only and ensure accessibility
             if ( accept( field, acceptPrivate, acceptPackage ) )
@@ -189,7 +200,7 @@ public class FieldHandler
             if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
             {
                 logger.log( LogService.LOG_DEBUG, "Declared Field {0}.{1} not found", new Object[]
-                    { clazz.getName(), this.fieldName }, null );
+                    { clazz.getName(), this.metadata.getField() }, null );
             }
         }
         catch ( NoClassDefFoundError cdfe )
@@ -200,7 +211,7 @@ public class FieldHandler
             if ( logger.isLogEnabled( LogService.LOG_WARNING ) )
             {
                 StringBuffer buf = new StringBuffer();
-                buf.append( "Failure loooking up field " ).append( this.fieldName );
+                buf.append( "Failure loooking up field " ).append( this.metadata.getField() );
                 buf.append( " in class class " ).append( clazz.getName() ).append( ". Assuming no such field." );
                 logger.log( LogService.LOG_WARNING, buf.toString(), cdfe );
             }
@@ -213,13 +224,58 @@ public class FieldHandler
         {
             // unexpected problem accessing the field, don't let everything
             // blow up in this situation, just throw a declared exception
-            throw new InvocationTargetException( throwable, "Unexpected problem trying to get field " + this.fieldName );
+            throw new InvocationTargetException( throwable, "Unexpected problem trying to get field " + this.metadata.getField() );
         }
 
         // caught and ignored exception, assume no field and continue search
         return null;
     }
 
+    /**
+     * Validate the field, type etc.
+     * @param f The field
+     * @param logger The logger
+     * @return The field if it's valid, {@code null} otherwise.
+     */
+    private Field validateField( final Field f, final SimpleLogger logger )
+    {
+        final Class<?> fieldType = f.getType();
+        final Class<?> referenceType = ClassUtils.getClassFromComponentClassLoader(
+                this.componentClass, metadata.getInterface(), logger);
+
+        // unary reference
+        if ( !metadata.isMultiple() )
+        {
+            if ( fieldType.isAssignableFrom(referenceType) )
+            {
+                // service
+            }
+            else if ( fieldType == ClassUtils.SERVICE_REFERENCE_CLASS )
+            {
+                // service reference
+            }
+            else if ( fieldType == ClassUtils.SERVICE_OBJECTS_CLASS )
+            {
+                // service objects
+            }
+            else if ( fieldType == ClassUtils.MAP_CLASS )
+            {
+                // map
+            }
+            else if ( fieldType == ClassUtils.MAP_ENTRY_CLASS )
+            {
+                // map entry
+            }
+            else
+            {
+                logger.log( LogService.LOG_WARNING, "Field {0} in component {1} has unsupported type {2}", new Object[]
+                        {metadata.getField(), this.componentClass, fieldType.getName()}, null );
+                return null;
+            }
+        }
+        return f;
+    }
+
     private enum METHOD_TYPE {
         BIND,
         UNBIND,
@@ -244,11 +300,11 @@ public class FieldHandler
                 field.set(componentInstance, null);
             }
         } catch ( final IllegalArgumentException iae ) {
-            iae.printStackTrace();
+            throw new InvocationTargetException(iae);
         } catch ( final IllegalAccessException iae ) {
-            iae.printStackTrace();
-
+            throw new InvocationTargetException(iae);
         }
+
         return MethodResult.VOID;
     }
 
@@ -336,6 +392,9 @@ public class FieldHandler
         return ( dot > 0 ) ? name.substring( 0, dot ) : "";
     }
 
+    /**
+     * Internal state interface.
+     */
     private static interface State
     {
 
@@ -347,31 +406,34 @@ public class FieldHandler
         throws InvocationTargetException;
     }
 
+    /**
+     * Initial state.
+     */
     private static class NotResolved implements State
     {
         private static final State INSTANCE = new NotResolved();
 
-        private synchronized void resolve( final FieldHandler baseMethod, SimpleLogger logger )
+        private synchronized void resolve( final FieldHandler baseMethod, final SimpleLogger logger )
         {
             logger.log( LogService.LOG_DEBUG, "getting field: {0}", new Object[]
-                    {baseMethod.fieldName}, null );
+                    {baseMethod.metadata.getField()}, null );
 
             // resolve the field
             Field field = null;
             try
             {
                 field = baseMethod.findField( logger );
+                field = baseMethod.validateField( field, logger );
             }
-            catch ( InvocationTargetException ex )
+            catch ( final InvocationTargetException ex )
             {
                 logger.log( LogService.LOG_WARNING, "{0} cannot be found", new Object[]
-                        {baseMethod.fieldName}, ex.getTargetException() );
+                        {baseMethod.metadata.getField()}, ex.getTargetException() );
             }
 
             baseMethod.setField( field, logger );
         }
 
-
         public MethodResult invoke( final FieldHandler baseMethod,
                 final METHOD_TYPE mType,
                 final Object componentInstance,
@@ -384,6 +446,9 @@ public class FieldHandler
         }
     }
 
+    /**
+     * Final state of field couldn't be found or errors occured.
+     */
     private static class NotFound implements State
     {
         private static final State INSTANCE = new NotFound();
@@ -395,17 +460,19 @@ public class FieldHandler
                 final BindParameters rawParameter,
                 final SimpleLogger logger )
         {
-            logger.log( LogService.LOG_ERROR, "Field [{1}] not found", new Object[]
-                { baseMethod.fieldName }, null );
+            logger.log( LogService.LOG_ERROR, "Field [{0}] not found", new Object[]
+                { baseMethod.metadata.getField() }, null );
             return null;
         }
     }
 
+    /**
+     * Final state of field could be found and is valid.
+     */
     private static class Resolved implements State
     {
         private static final State INSTANCE = new Resolved();
 
-
         public MethodResult invoke( final FieldHandler baseMethod,
                 final METHOD_TYPE mType,
                 final Object componentInstance,
@@ -430,7 +497,7 @@ public class FieldHandler
                 catch ( InvocationTargetException ite )
                 {
                     logger.log( LogService.LOG_ERROR, "The {0} field has thrown an exception", new Object[]
-                        { fieldName }, ite.getCause() );
+                        { metadata.getField() }, ite.getCause() );
                 }
 
                 return methodCallFailureResult;
@@ -462,7 +529,7 @@ public class FieldHandler
                 catch ( InvocationTargetException ite )
                 {
                     logger.log( LogService.LOG_ERROR, "The {0} field has thrown an exception", new Object[]
-                        { fieldName }, ite.getCause() );
+                        { metadata.getField() }, ite.getCause() );
                 }
 
                 return methodCallFailureResult;
@@ -490,7 +557,7 @@ public class FieldHandler
                 catch ( InvocationTargetException ite )
                 {
                     logger.log( LogService.LOG_ERROR, "The {0} field has thrown an exception", new Object[]
-                        { fieldName }, ite.getCause() );
+                        { metadata.getField() }, ite.getCause() );
                 }
 
                 return methodCallFailureResult;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java?rev=1637759&r1=1637758&r2=1637759&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldMethods.java Sun Nov  9 23:05:27 2014
@@ -37,9 +37,8 @@ public class FieldMethods implements Ref
             final boolean configurableServiceProperties )
     {
         handler = new FieldHandler(
-                m_dependencyMetadata.getField(),
-                instanceClass,
-                m_dependencyMetadata.getInterface()
+                m_dependencyMetadata,
+                instanceClass
         );
     }
 

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java?rev=1637759&r1=1637758&r2=1637759&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java Sun Nov  9 23:05:27 2014
@@ -695,7 +695,7 @@ public class ReferenceMetadata
             {
                 throw componentMetadata.validationFailure( "Field strategy must be one of " + FIELD_STRATEGY_VALID );
             }
-            if ( m_cardinality.equals(CARDINALITY_1_1) || m_cardinality.equals(CARDINALITY_0_1) )
+            if ( !m_isMultiple )
             {
                 // update is not allowed for unary references
                 if ( m_field_strategy.equals(FIELD_STRATEGY_UPDATE) )
@@ -705,7 +705,7 @@ public class ReferenceMetadata
             }
 
             // field value type
-            if ( m_cardinality.equals(CARDINALITY_1_1) || m_cardinality.equals(CARDINALITY_0_1) )
+            if ( !m_isMultiple )
             {
                 // value type must not be specified for unary references
                 if ( m_field_value_type != null )