Пример #1
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);
      }
    }
  }
Пример #2
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)!");
    }
  }
Пример #3
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()
              + "!");
    }
  }
Пример #4
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());
        }
      }
    }
  }
Пример #5
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!");
        }
      }
    }
  }
Пример #6
0
  /**
   * Called when this bundle is stopped so the Framework can perform the bundle-specific activities
   * necessary to stop the bundle. In general, this method should undo the work that the
   * `BundleActivator.start()` method started. There should be no active threads that were started
   * by this bundle when this bundle returns. A stopped bundle must not call any Framework objects.
   *
   * <p>This method must complete and return to its caller in a timely manner.
   *
   * @param context The execution context of the bundle being stopped.
   * @throws Exception If this method throws an exception, the bundle is still marked as stopped,
   *     and the Framework will remove the bundle's listeners, unregister all services registered by
   *     the bundle, and release all services used by the bundle.
   */
  @Override
  public void stop(BundleContext context) throws Exception {
    if (this.services == null) {
      System.err.println("ERROR: Stopping non started instance of APSActivator!");
      return; // Not started!
    }

    Exception failure = null;

    this.activatorLogger.info(
        "Stopping APSActivator for bundle '"
            + context.getBundle().getSymbolicName()
            + "' with activatorMode: "
            + this.activatorMode);

    for (ListenerWrapper listenerWrapper : this.listeners) {
      listenerWrapper.stop(context);
    }
    this.listeners = null;

    for (Tuple2<Method, Object> shutdownMethod : this.shutdownMethods) {
      try {
        shutdownMethod.t1.invoke(shutdownMethod.t2, null);

        this.activatorLogger.info(
            "Called bundle shutdown method '"
                + shutdownMethod.t2.getClass()
                + "."
                + shutdownMethod.t1.getName()
                + "() for bundle: "
                + context.getBundle().getSymbolicName()
                + "!");
      } catch (Exception e) {
        this.activatorLogger.error("Bundle stop problem!", e);
        failure = e;
      }
    }
    this.shutdownMethods = null;

    for (ServiceRegistration serviceRegistration : this.services) {
      try {
        serviceRegistration.unregister();
      } catch (Exception e) {
        this.activatorLogger.error("Bundle stop problem!", e);
        failure = e;
      }
    }
    this.services = null;

    for (String trackerKey : this.trackers.keySet()) {
      APSServiceTracker tracker = this.trackers.get(trackerKey);
      try {
        tracker.stop(context);
      } catch (Exception e) {
        this.activatorLogger.error("Bundle stop problem!", e);
        failure = e;
      }
    }
    this.trackers = null;

    for (String namedInstanceKey : this.namedInstances.keySet()) {
      Object namedInstance = this.namedInstances.get(namedInstanceKey);
      if (namedInstance instanceof APSLogger) {
        try {
          ((APSLogger) namedInstance).stop(context);
        } catch (Exception e) {
          this.activatorLogger.error("Bundle stop problem!", e);
          failure = e;
        }
      }
    }
    this.namedInstances = null;

    this.activatorLogger.stop(context);
    this.activatorLogger = null;

    if (failure != null) {
      throw new APSActivatorException("Bundle stop not entirely successful!", failure);
    }
  }
Пример #7
0
 public void stop(BundleContext context) {
   context.removeFrameworkListener(this);
 }
Пример #8
0
 public void start(BundleContext context) {
   context.addFrameworkListener(this);
 }
Пример #9
0
 public void stop(BundleContext context) {
   context.removeBundleListener(this);
 }
Пример #10
0
 public void start(BundleContext context) {
   context.addBundleListener(this);
 }