Search in sources :

Example 1 with ParamType

use of org.apache.felix.scr.impl.inject.BindMethod.ParamType in project felix by apache.

the class BindMethod method getParameters.

@Override
protected Object[] getParameters(Method method, BindParameters bp) {
    ComponentContextImpl key = bp.getComponentContext();
    Object[] result = new Object[m_paramTypes.size()];
    RefPair<?, ?> refPair = bp.getRefPair();
    int i = 0;
    for (ParamType pt : m_paramTypes) {
        switch(pt) {
            case serviceReference:
                result[i++] = refPair.getRef();
                break;
            case serviceObjects:
                result[i++] = bp.getComponentContext().getComponentServiceObjectsHelper().getServiceObjects(refPair.getRef());
                break;
            case map:
                result[i++] = new ReadOnlyDictionary(refPair.getRef());
                break;
            case serviceType:
                result[i++] = refPair.getServiceObject(key);
                break;
            default:
                throw new IllegalStateException("unexpected ParamType: " + pt);
        }
    }
    return result;
}
Also used : ReadOnlyDictionary(org.apache.felix.scr.impl.helper.ReadOnlyDictionary) ComponentContextImpl(org.apache.felix.scr.impl.manager.ComponentContextImpl) ParamType(org.apache.felix.scr.impl.inject.BindMethod.ParamType)

Example 2 with ParamType

use of org.apache.felix.scr.impl.inject.BindMethod.ParamType in project felix by apache.

the class BindMethod method doFindMethod.

/**
 * Finds the method named in the {@link #m_methodName} field in the given
 * <code>targetClass</code>. If the target class has no acceptable method
 * the class hierarchy is traversed until a method is found or the root
 * of the class hierarchy is reached without finding a method.
 *
 * @param targetClass The class in which to look for the method
 * @param acceptPrivate <code>true</code> if private methods should be
 *      considered.
 * @param acceptPackage <code>true</code> if package private methods should
 *      be considered.
 * @param logger
 * @return The requested method or <code>null</code> if no acceptable method
 *      can be found in the target class or any super class.
 * @throws InvocationTargetException If an unexpected Throwable is caught
 *      trying to find the requested method.
 */
@Override
protected MethodInfo<List<ParamType>> doFindMethod(final Class<?> targetClass, final boolean acceptPrivate, final boolean acceptPackage, final SimpleLogger logger) throws SuitableMethodNotAccessibleException, InvocationTargetException {
    // 112.3.1 The method is searched for using the following priority
    // 1 - ServiceReference single parameter
    // 2 - DS 1.3+ : ComponentServiceObjects single parameter
    // 3 - Service object single parameter
    // 4 - Service interface assignment compatible single parameter
    // 5 - DS 1.3+ : Single argument with Map
    // 6 - DS 1.1/DS 1.2 : two parameters, first the type of or assignment compatible with the service, the second Map
    // 7 - DS 1.3+ : one or more parameters of types ServiceReference, ServiceObjects, interface type,
    // or assignment compatible to interface type, in any order.
    // flag indicating a suitable but inaccessible method has been found
    boolean suitableMethodNotAccessible = false;
    if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
        logger.log(LogService.LOG_DEBUG, "doFindMethod: Looking for method " + targetClass.getName() + "." + getMethodName(), null);
    }
    // Case 1 - Service reference parameter
    Method method;
    try {
        method = getServiceReferenceMethod(targetClass, acceptPrivate, acceptPackage, logger);
        if (method != null) {
            if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
                logger.log(LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null);
            }
            return new MethodInfo<List<ParamType>>(method, Collections.singletonList(ParamType.serviceReference));
        }
    } catch (SuitableMethodNotAccessibleException ex) {
        suitableMethodNotAccessible = true;
    }
    // Case 2 - ComponentServiceObjects parameter
    if (getDSVersion().isDS13()) {
        try {
            method = getComponentObjectsMethod(targetClass, acceptPrivate, acceptPackage, logger);
            if (method != null) {
                if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
                    logger.log(LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null);
                }
                return new MethodInfo<List<ParamType>>(method, Collections.singletonList(ParamType.serviceObjects));
            }
        } catch (SuitableMethodNotAccessibleException ex) {
            suitableMethodNotAccessible = true;
        }
    }
    // for further methods we need the class of the service object
    final Class<?> parameterClass = ClassUtils.getClassFromComponentClassLoader(targetClass, m_referenceClassName, logger);
    if (parameterClass != null) {
        if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
            logger.log(LogService.LOG_DEBUG, "doFindMethod: No method taking ServiceReference found, checking method taking " + parameterClass.getName(), null);
        }
        // Case 3 - Service object parameter
        try {
            method = getServiceObjectMethod(targetClass, parameterClass, acceptPrivate, acceptPackage, logger);
            if (method != null) {
                if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
                    logger.log(LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null);
                }
                return new MethodInfo<List<ParamType>>(method, Collections.singletonList(ParamType.serviceType));
            }
        } catch (SuitableMethodNotAccessibleException ex) {
            suitableMethodNotAccessible = true;
        }
        // Case 4 - Service interface assignment compatible methods
        try {
            method = getServiceObjectAssignableMethod(targetClass, parameterClass, acceptPrivate, acceptPackage, logger);
            if (method != null) {
                if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
                    logger.log(LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null);
                }
                return new MethodInfo<List<ParamType>>(method, Collections.singletonList(ParamType.serviceType));
            }
        } catch (SuitableMethodNotAccessibleException ex) {
            suitableMethodNotAccessible = true;
        }
        // Case 5 - DS 1.3+ : Single argument with Map
        if (getDSVersion().isDS13()) {
            try {
                method = getMapMethod(targetClass, parameterClass, acceptPrivate, acceptPackage, logger);
                if (method != null) {
                    if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
                        logger.log(LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null);
                    }
                    return new MethodInfo<List<ParamType>>(method, Collections.singletonList(ParamType.map));
                }
            } catch (SuitableMethodNotAccessibleException ex) {
                suitableMethodNotAccessible = true;
            }
        }
        // signatures taking a map are only supported starting with DS 1.1
        if (getDSVersion().isDS11() && !getDSVersion().isDS13()) {
            // Case 6 - same as case 3, but + Map param (DS 1.1 only)
            try {
                method = getServiceObjectWithMapMethod(targetClass, parameterClass, acceptPrivate, acceptPackage, logger);
                if (method != null) {
                    if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
                        logger.log(LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null);
                    }
                    List<ParamType> paramTypes = new ArrayList<ParamType>(2);
                    paramTypes.add(ParamType.serviceType);
                    paramTypes.add(ParamType.map);
                    return new MethodInfo<List<ParamType>>(method, paramTypes);
                }
            } catch (SuitableMethodNotAccessibleException ex) {
                suitableMethodNotAccessible = true;
            }
            // Case 6 - same as case 4, but + Map param (DS 1.1 only)
            try {
                method = getServiceObjectAssignableWithMapMethod(targetClass, parameterClass, acceptPrivate, acceptPackage);
                if (method != null) {
                    if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
                        logger.log(LogService.LOG_DEBUG, "doFindMethod: Found Method " + method, null);
                    }
                    List<ParamType> paramTypes = new ArrayList<ParamType>(2);
                    paramTypes.add(ParamType.serviceType);
                    paramTypes.add(ParamType.map);
                    return new MethodInfo<List<ParamType>>(method, paramTypes);
                }
            } catch (SuitableMethodNotAccessibleException ex) {
                suitableMethodNotAccessible = true;
            }
        }
        // Case 7 - Multiple parameters
        if (getDSVersion().isDS13()) {
            for (Method m : targetClass.getDeclaredMethods()) {
                if (getMethodName().equals(m.getName())) {
                    Class<?>[] parameterTypes = m.getParameterTypes();
                    boolean matches = true;
                    boolean specialMatch = true;
                    List<ParamType> paramTypes = new ArrayList<ParamType>(parameterTypes.length);
                    for (Class<?> paramType : parameterTypes) {
                        if (paramType == ClassUtils.SERVICE_REFERENCE_CLASS) {
                            if (specialMatch && parameterClass == ClassUtils.SERVICE_REFERENCE_CLASS) {
                                specialMatch = false;
                                paramTypes.add(ParamType.serviceType);
                            } else {
                                paramTypes.add(ParamType.serviceReference);
                            }
                        } else if (paramType == ClassUtils.COMPONENTS_SERVICE_OBJECTS_CLASS) {
                            if (specialMatch && parameterClass == ClassUtils.COMPONENTS_SERVICE_OBJECTS_CLASS) {
                                specialMatch = false;
                                paramTypes.add(ParamType.serviceType);
                            } else {
                                paramTypes.add(ParamType.serviceObjects);
                            }
                        } else if (paramType == Map.class) {
                            if (specialMatch && parameterClass == Map.class) {
                                specialMatch = false;
                                paramTypes.add(ParamType.serviceType);
                            } else {
                                paramTypes.add(ParamType.map);
                            }
                        } else if (paramType.isAssignableFrom(parameterClass)) {
                            paramTypes.add(ParamType.serviceType);
                        } else {
                            matches = false;
                            break;
                        }
                    }
                    if (matches) {
                        if (accept(m, acceptPrivate, acceptPackage, returnValue())) {
                            if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
                                logger.log(LogService.LOG_DEBUG, "doFindMethod: Found Method " + m, null);
                            }
                            return new MethodInfo<List<ParamType>>(m, paramTypes);
                        }
                        suitableMethodNotAccessible = true;
                    }
                }
            }
        }
    } else if (logger.isLogEnabled(LogService.LOG_WARNING)) {
        logger.log(LogService.LOG_WARNING, "doFindMethod: Cannot check for methods taking parameter class " + m_referenceClassName + ": " + targetClass.getName() + " does not see it", null);
    }
    // the suitable methods are accessible, we have to terminate
    if (suitableMethodNotAccessible) {
        logger.log(LogService.LOG_ERROR, "doFindMethod: Suitable but non-accessible method found in class {0}", new Object[] { targetClass.getName() }, null);
        throw new SuitableMethodNotAccessibleException();
    }
    // no method found
    return null;
}
Also used : ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) Map(java.util.Map) ParamType(org.apache.felix.scr.impl.inject.BindMethod.ParamType)

Aggregations

ParamType (org.apache.felix.scr.impl.inject.BindMethod.ParamType)2 Method (java.lang.reflect.Method)1 ArrayList (java.util.ArrayList)1 Map (java.util.Map)1 ReadOnlyDictionary (org.apache.felix.scr.impl.helper.ReadOnlyDictionary)1 ComponentContextImpl (org.apache.felix.scr.impl.manager.ComponentContextImpl)1