in core/src/main/java/org/apache/sling/testing/mock/osgi/OsgiServiceUtil.java [641:677]
private static void injectServiceReference(Reference reference, Object target, BundleContext bundleContext) {
Class<?> targetClass = target.getClass();
// get reference type
Class<?> type = reference.getInterfaceTypeAsClass();
// get matching service references
List<ServiceInfo<?>> matchingServices = getMatchingServices(type, bundleContext, reference.getTarget());
// no references found? check if reference was optional
if (matchingServices.isEmpty()) {
if (!reference.isCardinalityOptional()) {
throw new ReferenceViolationException("Unable to inject mandatory reference '" + reference.getName() + "' (" + type.getName() + ") for class " + targetClass.getName() + " : no matching services were found. bundleContext=" + bundleContext);
}
// make sure at least empty array or empty Optional is set
invokeBindUnbindMethod(reference, target, null, true);
}
// multiple references found? inject only first one with highest ranking
if (matchingServices.size() > 1 && !reference.isCardinalityMultiple()) {
matchingServices = matchingServices.subList(0, 1);
} else {
/*
* Please note that the OSGi spec does not seem to define a ordering for the list of service references/services
* https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-field.injection
* But the actual Felix framework implementation seems to return the list always sorted by rank in ascending order, so we do the same here.
*/
matchingServices.sort(Comparator.comparing(ServiceInfo::getServiceReference));
}
// try to invoke bind method
for (ServiceInfo<?> matchingService : matchingServices) {
invokeBindUnbindMethod(reference, target, matchingService, true);
}
}