@SuppressWarnings("unchecked")
  private <T> T getService(Class<T> serviceType, String filter, long timeout)
      throws TestContainerException {
    assert m_framework != null : "Framework should be up";
    assert serviceType != null : "serviceType not be null";

    final Long start = System.currentTimeMillis();

    LOG.info("Aquiring Service " + serviceType.getName() + " " + (filter != null ? filter : ""));

    do {
      try {
        ServiceReference[] reference =
            m_framework.getBundleContext().getServiceReferences(serviceType.getName(), filter);
        if (reference != null && reference.length > 0) {
          return ((T) m_framework.getBundleContext().getService(reference[0]));
        }

        Thread.sleep(200);
      } catch (Exception e) {
        LOG.error("Some problem during looking up service from framework: " + m_framework, e);
      }
      // wait a bit
    } while ((System.currentTimeMillis()) < start + timeout);
    printAvailableAlternatives(serviceType);

    throw new TestContainerException(
        "Not found a matching Service "
            + serviceType.getName()
            + " for Filter:"
            + (filter != null ? filter : ""));
  }
예제 #2
0
  /**
   * Called when this bundle is started so the Framework can perform the bundle-specific activities
   * necessary to start this bundle. This method can be used to register services or to allocate any
   * resources that this bundle needs.
   *
   * <p>This method must complete and return to its caller in a timely manner.
   *
   * @param context The execution context of the bundle being started.
   * @throws Exception If this method throws an exception, this bundle is marked as stopped and the
   *     Framework will remove this bundle's listeners, unregister all services registered by this
   *     bundle, and release all services used by this bundle.
   */
  @Override
  public void start(BundleContext context) throws Exception {
    this.context = context;
    initMembers();
    this.activatorLogger.info(
        "Starting APSActivator for bundle '"
            + context.getBundle().getSymbolicName()
            + "' with activatorMode: "
            + this.activatorMode);
    Bundle bundle = context.getBundle();

    List<Class> classEntries = new LinkedList<>();
    if (!this.activatorMode) {
      classEntries.addAll(this.managedInstances.keySet());
    }
    collectClassEntries(bundle, classEntries, "/");

    for (Class entryClass : classEntries) {
      OSGiServiceProvider serviceProvider =
          (OSGiServiceProvider) entryClass.getAnnotation(OSGiServiceProvider.class);
      if (serviceProvider != null && serviceProvider.threadStart()) {
        new StartThread(entryClass, context).start();
      } else {
        handleServiceInstances(entryClass, context);
        handleFieldInjections(entryClass, context);
        handleServiceRegistrations(entryClass, context);
        handleMethods(entryClass, context);
      }
    }
  }
예제 #3
0
 /**
  * Handles annotated methods.
  *
  * @param managedClass Used to lookup or create an instance of this class containing the method to
  *     call.
  * @param context The bundle context.
  */
 protected void handleMethods(Class managedClass, BundleContext context) {
   for (Method method : managedClass.getDeclaredMethods()) {
     handleStartupMethods(method, managedClass, context);
     handleShutdownMethods(method, managedClass, context);
     handleListenerMethods(method, managedClass, context);
   }
 }
 public <S> ServiceRegistration<S> registerService(
     Class<S> clazz, S service, Dictionary<String, ?> properties) {
   @SuppressWarnings("unchecked")
   ServiceRegistration<S> registration =
       (ServiceRegistration<S>) registerService(clazz.getName(), service, properties);
   return registration;
 }
 /** Check for permission to get a service. */
 private <A> void checkAdaptPermission(Class<A> adapterType) {
   SecurityManager sm = System.getSecurityManager();
   if (sm == null) {
     return;
   }
   sm.checkPermission(new AdaptPermission(adapterType.getName(), this, AdaptPermission.ADAPT));
 }
예제 #6
0
 /**
  * This method loads a class from the bundle. The class is searched for in the same manner as it
  * would if it was being loaded from a bundle (i.e. all hosts, fragments, import, required bundles
  * and local resources are searched.
  *
  * @param name the name of the desired Class.
  * @return the resulting Class
  * @exception java.lang.ClassNotFoundException if the class definition was not found.
  */
 public final Class loadClass(String name) throws ClassNotFoundException {
   BundleClassLoader bcl = createClassLoader();
   // The instanceof check here is just to be safe.  The javadoc contract stated in
   // BundleClassLoader
   // mandate that BundleClassLoaders be an instance of ClassLoader.
   if (name.length() > 0 && name.charAt(0) == '[' && bcl instanceof ClassLoader)
     return Class.forName(name, false, (ClassLoader) bcl);
   return bcl.loadClass(name);
 }
예제 #7
0
 private static ClassLoader getClassLoader(final Class clazz) {
   if (System.getSecurityManager() == null) return clazz.getClassLoader();
   return (ClassLoader)
       AccessController.doPrivileged(
           new PrivilegedAction() {
             public Object run() {
               return clazz.getClassLoader();
             }
           });
 }
 private static Class<?> mapComponentType(Class<?> componentType) {
   if (componentType.isPrimitive()
       || componentType.isArray()
       || Object.class.equals(componentType)
       || Number.class.isAssignableFrom(componentType)
       || Boolean.class.isAssignableFrom(componentType)
       || Character.class.isAssignableFrom(componentType)
       || String.class.isAssignableFrom(componentType)
       || DTO.class.isAssignableFrom(componentType)) {
     return componentType;
   }
   if (Map.class.isAssignableFrom(componentType)) {
     return Map.class;
   }
   if (List.class.isAssignableFrom(componentType)) {
     return List.class;
   }
   if (Set.class.isAssignableFrom(componentType)) {
     return Set.class;
   }
   return String.class;
 }
예제 #9
0
  /**
   * This is used to start delayed service publishing. Each tracker of a required service will be
   * calling this method on first service becoming available. When all required services are
   * available the delayed service will be published.
   *
   * @param service The received service.
   * @param serviceReference The reference to the received service.
   * @throws Exception
   */
  @Override
  public void onServiceAvailable(Object service, ServiceReference serviceReference)
      throws Exception {
    this.activatorLogger.info("Received service: " + service.getClass().getName());
    List<Class> uniqueClasses = new LinkedList<>();
    for (Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService :
        this.requiredServices) {
      if (!uniqueClasses.contains(requiredService.t2)) {
        uniqueClasses.add(requiredService.t2);
      }
    }

    for (Class managedClass : uniqueClasses) {
      boolean allRequiredAvailable = true;
      for (Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService :
          this.requiredServices) {
        if (requiredService.t2.equals(managedClass) && !requiredService.t1.hasTrackedService()) {
          allRequiredAvailable = false;
          this.activatorLogger.info(
              "Not all required services are available yet for: " + managedClass.getName());
          break;
        }
      }

      if (allRequiredAvailable) {
        this.activatorLogger.info(
            "All required services are now available for: " + managedClass.getName());
        for (Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService :
            this.requiredServices) {
          if (requiredService.t2.equals(managedClass) && requiredService.t3 == false) {
            this.activatorLogger.info("Registering services for: " + managedClass.getName());
            registerServices(requiredService.t2, this.context, requiredService.t4);
            this.services.addAll(requiredService.t4);
            requiredService.t3 = true;
          }
        }
      }
    }
  }
예제 #10
0
  /**
   * Tracks and injects APSServiceTracker directly or as wrapped service instance using the tracker
   * to call the service depending on the field type.
   *
   * @param field The field to inject.
   * @param managedClass Used to lookup or create an instance of this class to inject into.
   * @param context The bundle context.
   */
  protected void handleServiceInjections(Field field, Class managedClass, BundleContext context) {
    OSGiService service = field.getAnnotation(OSGiService.class);
    if (service != null) {
      String trackerKey = field.getType().getName() + service.additionalSearchCriteria();
      APSServiceTracker tracker = this.trackers.get(trackerKey);

      if (tracker == null) {
        tracker =
            new APSServiceTracker<>(
                context, field.getType(), service.additionalSearchCriteria(), service.timeout());
        this.trackers.put(trackerKey, tracker);
      }
      tracker.start();

      List<Object> managedInstances = getManagedInstances(managedClass);
      for (Object managedInstance : managedInstances) {
        if (field.getType().equals(APSServiceTracker.class)) {
          injectObject(managedInstance, tracker, field);
        } else {
          injectObject(managedInstance, tracker.getWrappedService(), field);
        }
      }

      if (service.required() && this.supportsRequired) {
        Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService =
            new Tuple4<>(
                tracker,
                managedClass,
                false,
                (List<ServiceRegistration>) new LinkedList<ServiceRegistration>());
        this.requiredServices.add(requiredService);
      }

      this.activatorLogger.info(
          "Injected tracked service '"
              + field.getType().getName()
              + (service.additionalSearchCriteria().length() > 0
                  ? " " + service.additionalSearchCriteria()
                  : "")
              + "' "
              + "into '"
              + managedClass.getName()
              + "."
              + field.getName()
              + "' for bundle: "
              + context.getBundle().getSymbolicName()
              + " for "
              + managedInstances.size()
              + " instance(s)!");
    }
  }
예제 #11
0
  /**
   * Returns a managed instance of a class.
   *
   * @param managedClass The managed class to get instance for.
   * @param size The number of instances.
   */
  protected List<Object> getManagedInstances(Class managedClass, int size) {
    List<Object> managedInstances = this.managedInstances.get(managedClass);
    if (managedInstances == null) {
      managedInstances = new LinkedList<>();
    }

    if (managedInstances.isEmpty()) {
      if (size == -1) throw new IllegalStateException("Expected instances are not available!");
      try {
        for (int i = 0; i < size; i++) {
          Object managedInstance = managedClass.newInstance();
          managedInstances.add(managedInstance);
          this.managedInstances.put(managedClass, managedInstances);
          this.activatorLogger.info(
              "Instantiated '" + managedClass.getName() + "': " + managedInstance);
        }
      } catch (InstantiationException | IllegalAccessException e) {
        throw new APSActivatorException("Failed to instantiate activator managed class!", e);
      }
    }

    return managedInstances;
  }
예제 #12
0
  /**
   * Handles publishing of bundle services. If a published service has any dependencies to other
   * services that are marked as required then the publishing is delayed until all required services
   * are available. In this case the service will be unpublished if any of the required services
   * times out.
   *
   * @param managedClass The managed service class to instantiate and register as a service.
   * @param context The bundles context.
   * @throws Exception
   */
  protected void handleServiceRegistrations(final Class managedClass, final BundleContext context)
      throws Exception {
    OSGiServiceProvider serviceProvider =
        (OSGiServiceProvider) managedClass.getAnnotation(OSGiServiceProvider.class);

    if (serviceProvider != null) {
      if (this.requiredServices.isEmpty()) {
        registerServices(managedClass, context, this.services);
      } else {
        for (Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService :
            this.requiredServices) {
          this.activatorLogger.info(
              "Registering for delayed start of '"
                  + managedClass.getName()
                  + "' "
                  + "due to service '"
                  + requiredService.t1.getServiceClass().getName()
                  + "'!");
          requiredService.t1.onActiveServiceAvailable(this);
          requiredService.t1.setOnTimeout(this);
        }
      }
    }
  }
 public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter)
     throws InvalidSyntaxException {
   @SuppressWarnings("unchecked")
   ServiceReference<S>[] refs =
       (ServiceReference<S>[]) getServiceReferences(clazz.getName(), filter);
   if (refs == null) {
     @SuppressWarnings("unchecked")
     Collection<ServiceReference<S>> empty = Collections.EMPTY_LIST;
     return empty;
   }
   List<ServiceReference<S>> result = new ArrayList<ServiceReference<S>>(refs.length);
   for (ServiceReference<S> b : refs) {
     result.add(b);
   }
   return result;
 }
  private <T> void printAvailableAlternatives(Class<T> serviceType) {
    try {
      ServiceReference[] reference =
          m_framework.getBundleContext().getAllServiceReferences(serviceType.getName(), null);
      if (reference != null) {
        LOG.warn("Test Endpoints: " + reference.length);

        for (ServiceReference ref : reference) {
          LOG.warn("Endpoint: " + ref);
        }
      }

    } catch (Exception e) {
      LOG.error("Some problem during looking up alternative service. ", e);
    }
  }
예제 #15
0
  /**
   * Handles injections of APSLogger, BundleContext, or other class types with default constructor.
   *
   * @param field The field to inject into.
   * @param managedClass Used to lookup or create an instance of this class to inject into.
   * @param context The bundle context.
   */
  protected void handleInstanceInjections(Field field, Class managedClass, BundleContext context) {
    Managed managed = field.getAnnotation(Managed.class);
    if (managed != null) {
      String namedInstanceKey = managed.name() + field.getType().getName();
      Object namedInstance = this.namedInstances.get(namedInstanceKey);
      if (namedInstance == null) {
        if (field.getType().equals(APSLogger.class)) {
          namedInstance = new APSLogger(System.out);
          if (managed.loggingFor().length() > 0) {
            ((APSLogger) namedInstance).setLoggingFor(managed.loggingFor());
          }
          ((APSLogger) namedInstance).start(context);
        } else if (field.getType().equals(BundleContext.class)) {
          namedInstance = context;
        } else {
          namedInstance = getManagedInstance(field.getType());
        }
        this.namedInstances.put(namedInstanceKey, namedInstance);
      } else {
        this.activatorLogger.info(
            "Got named instance for key '"
                + namedInstanceKey
                + "': "
                + namedInstance.getClass().getName());
      }

      List<Object> managedInstances = getManagedInstances(managedClass);
      for (Object managedInstance : managedInstances) {
        injectObject(managedInstance, namedInstance, field);
      }

      this.activatorLogger.info(
          "Injected '"
              + namedInstance.getClass().getName()
              + "' instance for name '"
              + managed.name()
              + "' "
              + "into '"
              + managedClass.getName()
              + "."
              + field.getName()
              + "' for bundle: "
              + context.getBundle().getSymbolicName()
              + "!");
    }
  }
예제 #16
0
  /**
   * This is the first thing done to instantiate all service instances needed, so that they all can
   * be injected later.
   *
   * @param managedClass The manages class to create instances of.
   * @param context The bundles context.
   * @throws Exception
   */
  protected void handleServiceInstances(Class managedClass, BundleContext context)
      throws Exception {
    OSGiServiceProvider serviceProvider =
        (OSGiServiceProvider) managedClass.getAnnotation(OSGiServiceProvider.class);
    if (serviceProvider != null) {
      int noInstances = 1;

      if (serviceProvider.instances().length > 0) {
        noInstances = serviceProvider.instances().length;
      } else if (!serviceProvider.instanceFactoryClass().equals(InstanceFactory.class)) {
        InstanceFactory instanceFactory =
            (InstanceFactory) getManagedInstance(serviceProvider.instanceFactoryClass());
        if (instanceFactory == null) {
          instanceFactory = serviceProvider.instanceFactoryClass().newInstance();
        }
        noInstances = instanceFactory.getPropertiesPerInstance().size();
      }

      // This will just instantiate and cache the number of instances. Right now we don't care
      // about the instances themselves.
      getManagedInstances(managedClass, noInstances);
    }
  }
 @Override
 public Class<?> loadClass(String name) throws ClassNotFoundException {
   try {
     equinoxContainer.checkAdminPermission(this, AdminPermission.CLASS);
   } catch (SecurityException e) {
     throw new ClassNotFoundException(name, e);
   }
   checkValid();
   if (isFragment()) {
     throw new ClassNotFoundException(
         "Can not load a class from a fragment bundle: " + this); // $NON-NLS-1$
   }
   try {
     ModuleClassLoader classLoader = getModuleClassLoader(true);
     if (classLoader != null) {
       if (name.length() > 0 && name.charAt(0) == '[')
         return Class.forName(name, false, classLoader);
       return classLoader.loadClass(name);
     }
   } catch (ClassNotFoundException e) {
     // This is an equinox-ism.  Not sure it is worth it to offer an option to disable ...
     // On failure attempt to activate lazy activating bundles.
     if (State.LAZY_STARTING.equals(module.getState())) {
       try {
         module.start(StartOptions.LAZY_TRIGGER);
       } catch (BundleException e1) {
         equinoxContainer
             .getLogServices()
             .log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, e.getMessage(), e);
       }
     }
     throw e;
   }
   throw new ClassNotFoundException(
       "No class loader available for the bundle: " + this); // $NON-NLS-1$
 }
 protected void registerService(Class<?> clazz, Object service) {
   serviceRegistrations.add(
       getSystemBundleContext().registerService(clazz.getName(), service, null));
 }
 /**
  * Returns the operation set corresponding to the specified class or null if this operation set is
  * not supported by the provider implementation.
  *
  * @param opsetClass the <tt>Class</tt> of the operation set that we're looking for.
  * @return returns an OperationSet of the specified <tt>Class</tt> if the undelying implementation
  *     supports it or null otherwise.
  */
 public OperationSet getOperationSet(Class opsetClass) {
   return (OperationSet) getSupportedOperationSets().get(opsetClass.getName());
 }
예제 #20
0
 public Class<?> loadClass(String name) throws ClassNotFoundException {
   return Class.forName(name);
 }
 public <S> ServiceReference<S> getServiceReference(Class<S> clazz) {
   @SuppressWarnings("unchecked")
   ServiceReference<S> reference = (ServiceReference<S>) getServiceReference(clazz.getName());
   return reference;
 }
예제 #22
0
  /**
   * Handles methods annotated with @APSBundleStartup.
   *
   * @param method The annotated method to call.
   * @param managedClass Used to lookup or create an instance of this class containing the method to
   *     call.
   * @param context The bundle context.
   */
  protected void handleStartupMethods(
      final Method method, final Class managedClass, final BundleContext context) {
    BundleStart bundleStart = method.getAnnotation(BundleStart.class);
    if (bundleStart != null) {
      if (method.getParameterTypes().length > 0) {
        throw new APSActivatorException(
            "An @BundleStart method must take no parameters! ["
                + managedClass.getName()
                + "."
                + method.getName()
                + "(?)]");
      }

      if (bundleStart.thread()) {
        new Thread(
                new Runnable() {
                  @Override
                  public void run() {
                    try {
                      Object managedInstance = null;
                      if (!Modifier.isStatic(method.getModifiers())) {
                        managedInstance = getManagedInstance(managedClass);
                      }
                      method.invoke(managedInstance, null);

                      APSActivator.this.activatorLogger.info(
                          "Called bundle start method '"
                              + managedClass.getName()
                              + "."
                              + method.getName()
                              + "()' for bundle: "
                              + context.getBundle().getSymbolicName()
                              + "!");
                    } catch (IllegalAccessException iae) {
                      APSActivator.this.activatorLogger.error(
                          "Failed to call start method! ["
                              + managedClass.getName()
                              + "."
                              + method.getName()
                              + "()]",
                          iae);
                    } catch (InvocationTargetException ite) {
                      APSActivator.this.activatorLogger.error(
                          "Failed to call start method! ["
                              + managedClass.getName()
                              + "."
                              + method.getName()
                              + "()]",
                          ite.getCause());
                    } catch (Exception e) {
                      APSActivator.this.activatorLogger.error(
                          "Failed to call start method! ["
                              + managedClass.getName()
                              + "."
                              + method.getName()
                              + "()]",
                          e);
                    }
                  }
                })
            .start();
      } else {
        try {
          Object managedInstance = null;
          if (!Modifier.isStatic(method.getModifiers())) {
            managedInstance = getManagedInstance(managedClass);
          }
          method.invoke(managedInstance, null);

          this.activatorLogger.info(
              "Called bundle start method '"
                  + managedClass.getName()
                  + "."
                  + method.getName()
                  + "()' for bundle: "
                  + context.getBundle().getSymbolicName()
                  + "!");
        } catch (IllegalAccessException iae) {
          throw new APSActivatorException(
              "Failed to call start method! ["
                  + managedClass.getName()
                  + "."
                  + method.getName()
                  + "()]",
              iae);
        } catch (InvocationTargetException ite) {
          throw new APSActivatorException(
              "Failed to call start method! ["
                  + managedClass.getName()
                  + "."
                  + method.getName()
                  + "()]",
              ite.getCause());
        }
      }
    }
  }
예제 #23
0
 /**
  * This handles all field injections by delegating to handlers of specific types of field
  * injections.
  *
  * @param managedClass The managed class to inject into.
  * @param context The bundles context.
  */
 protected void handleFieldInjections(Class managedClass, BundleContext context) {
   for (Field field : managedClass.getDeclaredFields()) {
     handleServiceInjections(field, managedClass, context);
     handleInstanceInjections(field, managedClass, context);
   }
 }
예제 #24
0
  /**
   * Registers/publishes services annotated with @OSGiServiceProvider.
   *
   * @param managedClass The managed class to instantiate and register as an OSGi service.
   * @param context The bundle context.
   * @param serviceRegs The list to save all service registrations to for later unregistration.
   * @throws Exception
   */
  protected void registerServices(
      Class managedClass, BundleContext context, List<ServiceRegistration> serviceRegs)
      throws Exception {
    OSGiServiceProvider serviceProvider =
        (OSGiServiceProvider) managedClass.getAnnotation(OSGiServiceProvider.class);
    if (serviceProvider != null) {
      List<Tuple3<Properties, Object, List<String>>> serviceInstData = new LinkedList<>();

      if (serviceProvider.properties().length > 0) {
        Tuple3<Properties, Object, List<String>> sd = new Tuple3<>();
        sd.t1 = osgiPropertiesToProperties(serviceProvider.properties());
        serviceInstData.add(sd);
      } else if (serviceProvider.instances().length > 0) {
        for (OSGiServiceInstance serviceInst : serviceProvider.instances()) {
          Tuple3<Properties, Object, List<String>> sd = new Tuple3<>();
          sd.t1 = osgiPropertiesToProperties(serviceInst.properties());
          serviceInstData.add(sd);
        }
      } else if (!serviceProvider.instanceFactoryClass().equals(InstanceFactory.class)) {
        InstanceFactory instanceFactory =
            (InstanceFactory) getManagedInstance(serviceProvider.instanceFactoryClass());
        if (instanceFactory == null) {
          instanceFactory = serviceProvider.instanceFactoryClass().newInstance();
        }
        for (Properties props : instanceFactory.getPropertiesPerInstance()) {
          Tuple3<Properties, Object, List<String>> sd = new Tuple3<>();
          sd.t1 = props;
          serviceInstData.add(sd);
        }
      } else {
        Tuple3<Properties, Object, List<String>> sd = new Tuple3<>();
        sd.t1 = new Properties();
        serviceInstData.add(sd);
      }

      // The number of managedInstances and serviceInstData will always be the same. They both
      // originate
      // from the same information.
      List<Object> managedInstances = getManagedInstances(managedClass);
      for (int i = 0; i < serviceInstData.size(); i++) {

        List<String> serviceAPIs = new LinkedList<>();

        if (serviceProvider.serviceAPIs().length > 0) {
          for (Class svcAPI : serviceProvider.serviceAPIs()) {
            serviceAPIs.add(svcAPI.getName());
          }
        } else if (serviceProvider.instances().length > 0) {
          OSGiServiceInstance svsInstAnn = serviceProvider.instances()[i];
          for (Class svcAPI : svsInstAnn.serviceAPIs()) {
            serviceAPIs.add(svcAPI.getName());
          }
        } else if (!serviceProvider.instanceFactoryClass().equals(InstanceFactory.class)) {
          String svcAPIList =
              serviceInstData.get(i).t1.getProperty(InstanceFactory.SERVICE_API_CLASSES_PROPERTY);
          if (svcAPIList != null) {
            for (String svcAPI : svcAPIList.split(":")) {
              serviceAPIs.add(svcAPI);
            }
          } else {
            Class[] interfaces = managedClass.getInterfaces();
            if (interfaces != null && interfaces.length > 0) {
              serviceAPIs.add(interfaces[0].getName());
            }
          }
        } else {
          Class[] interfaces = managedClass.getInterfaces();
          if (interfaces != null && interfaces.length > 0) {
            serviceAPIs.add(interfaces[0].getName());
          }
        }

        Tuple3<Properties, Object, List<String>> sd = serviceInstData.get(i);
        sd.t3 = serviceAPIs;
        sd.t2 = managedInstances.get(i);
      }

      for (Tuple3<Properties, Object, List<String>> sd : serviceInstData) {
        sd.t1.put(Constants.SERVICE_PID, managedClass.getName());
        if (!sd.t3.isEmpty()) {
          injectInstanceProps(sd.t2, sd.t1);
          for (String svcAPI : sd.t3) {
            ServiceRegistration serviceReg = context.registerService(svcAPI, sd.t2, sd.t1);

            serviceRegs.add(serviceReg);
            this.activatorLogger.info(
                "Registered '"
                    + managedClass.getName()
                    + "' as a service provider of '"
                    + svcAPI
                    + "' for bundle: "
                    + context.getBundle().getSymbolicName()
                    + "!");
          }
        } else {
          throw new IllegalArgumentException(
              "The @OSGiServiceProvider annotated service of class '"
                  + managedClass.getName()
                  + "' does not implement a service interface!");
        }
      }
    }
  }