void ServiceListeners::RemoveAllListeners(const std::shared_ptr<BundleContextPrivate>& context)
{
  {
    auto l = this->Lock(); US_UNUSED(l);
    for (ServiceListenerEntries::iterator it = serviceSet.begin();
         it != serviceSet.end(); )
    {

      if (GetPrivate(it->GetBundleContext()) == context)
      {
        RemoveFromCache_unlocked(*it);
        serviceSet.erase(it++);
      }
      else
      {
        ++it;
      }
    }
  }

  {
    auto l = bundleListenerMap.Lock(); US_UNUSED(l);
    bundleListenerMap.value.erase(context);
  }

  {
    auto l = frameworkListenerMap.Lock(); US_UNUSED(l);
    frameworkListenerMap.value.erase(context);
  }
}
void ServiceListeners::SendFrameworkEvent(const FrameworkEvent& evt)
{
  // avoid deadlocks, race conditions and other undefined behavior
  // by using a local snapshot of all listeners.
  // A lock shouldn't be held while calling into user code (e.g. callbacks).
  FrameworkListenerMap listener_snapshot;
  {
    auto l = frameworkListenerMap.Lock(); US_UNUSED(l);
    listener_snapshot = frameworkListenerMap.value;
  }

  for (auto& listeners : listener_snapshot)
  {
    for (auto& listener : listeners.second)
    {
      try
      {
        std::get<0>(listener.second)(evt);
      }
      catch (...)
      {
        // do not send a FrameworkEvent as that could cause a deadlock or an infinite loop.
        // Instead, log to the internal logger
        // @todo send this to the LogService instead when its supported.
        DIAG_LOG(*coreCtx->sink) << "A Framework Listener threw an exception: " << util::GetLastExceptionStr() << "\n";
      }
    }
  }
}
예제 #3
0
void ServiceRegistry::RemoveServiceRegistration_unlocked(
  const ServiceRegistrationBase& sr)
{
  std::vector<std::string> classes;
  {
    auto l2 = sr.d->properties.Lock();
    US_UNUSED(l2);
    assert(sr.d->properties.Value_unlocked(Constants::OBJECTCLASS).Type() ==
           typeid(std::vector<std::string>));
    classes = ref_any_cast<std::vector<std::string>>(
      sr.d->properties.Value_unlocked(Constants::OBJECTCLASS));
  }
  services.erase(sr);
  serviceRegistrations.erase(
    std::remove(serviceRegistrations.begin(), serviceRegistrations.end(), sr),
    serviceRegistrations.end());
  for (auto& clazz : classes) {
    std::vector<ServiceRegistrationBase>& s = classServices[clazz];
    if (s.size() > 1) {
      s.erase(std::remove(s.begin(), s.end(), sr), s.end());
    } else {
      classServices.erase(clazz);
    }
  }
}
예제 #4
0
void ServiceRegistry::RemoveServiceRegistration(
  const ServiceRegistrationBase& sr)
{
  auto l = this->Lock();
  US_UNUSED(l);
  RemoveServiceRegistration_unlocked(sr);
}
예제 #5
0
void ServiceListeners::RemoveAllListeners(ModuleContext* mc)
{
  {
    US_UNUSED(Lock(this));
    for (ServiceListenerEntries::iterator it = serviceSet.begin();
         it != serviceSet.end(); )
    {

      if (it->GetModuleContext() == mc)
      {
        RemoveFromCache(*it);
        serviceSet.erase(it++);
      }
      else
      {
        ++it;
      }
    }
  }

  {
    MutexLock lock(moduleListenerMapMutex);
    moduleListenerMap.erase(mc);
  }
}
예제 #6
0
void ServiceRegistry::Clear()
{
  auto l = this->Lock();
  US_UNUSED(l);
  services.clear();
  classServices.clear();
  serviceRegistrations.clear();
}
예제 #7
0
void ServiceListeners::RemoveServiceListener(ModuleContext* mc, const ServiceListenerEntry::ServiceListener& listener,
                                             void* data)
{
  ServiceListenerEntry entryToRemove(mc, listener, data);

  US_UNUSED(Lock(this));
  RemoveServiceListener_unlocked(entryToRemove);
}
예제 #8
0
void ServiceHooks::Close()
{
  US_UNUSED(Lock(this));
  listenerHookTracker->Close();
  delete listenerHookTracker;
  listenerHookTracker = NULL;

  bOpen = false;
}
ListenerToken ServiceListeners::AddFrameworkListener(const std::shared_ptr<BundleContextPrivate>& context, const FrameworkListener& listener, void* data)
{
  auto token = MakeListenerToken();

  auto l = frameworkListenerMap.Lock(); US_UNUSED(l);
  auto& listeners = frameworkListenerMap.value[context];
  listeners[token.Id()] = std::make_tuple(listener, data);
  return token;
}
예제 #10
0
파일: usServiceHooks.cpp 프로젝트: 0r/MITK
void ServiceHooks::Open()
{
  US_UNUSED(Lock(this));

  listenerHookTracker = new ServiceTracker<ServiceListenerHook>(GetModuleContext(), this);
  listenerHookTracker->Open();

  bOpen = true;
}
예제 #11
0
void ModuleSettings::SetAutoLoadPaths(const PathList& paths)
{
  PathList normalizedPaths;
  normalizedPaths.resize(paths.size());
  std::transform(paths.begin(), paths.end(), normalizedPaths.begin(), RemoveTrailingPathSeparator);

  US_UNUSED(ModuleSettingsPrivate::Lock(moduleSettingsPrivate()));
  moduleSettingsPrivate()->autoLoadPaths.clear();
  moduleSettingsPrivate()->autoLoadPaths.insert(normalizedPaths.begin(), normalizedPaths.end());
}
예제 #12
0
bool ModuleSettings::IsAutoLoadingEnabled()
{
  US_UNUSED(ModuleSettingsPrivate::Lock(moduleSettingsPrivate()));
#ifdef US_ENABLE_AUTOLOADING_SUPPORT
  return !moduleSettingsPrivate()->autoLoadingDisabled &&
      moduleSettingsPrivate()->autoLoadingEnabled;
#else
  return false;
#endif
}
std::vector<ServiceListenerHook::ListenerInfo> ServiceListeners::GetListenerInfoCollection() const
{
  auto l = this->Lock(); US_UNUSED(l);
  std::vector<ServiceListenerHook::ListenerInfo> result;
  result.reserve(serviceSet.size());
  for (auto info : serviceSet)
  {
    result.push_back(info);
  }
  return result;
}
예제 #14
0
ServiceRegistrationBase ServiceRegistry::RegisterService(
  BundlePrivate* bundle,
  const InterfaceMapConstPtr& service,
  const ServiceProperties& properties)
{
  if (!service || service->empty()) {
    throw std::invalid_argument(
      "Can't register empty InterfaceMap as a service");
  }

  // Check if we got a service factory
  bool isFactory = service->count("org.cppmicroservices.factory") > 0;
  bool isPrototypeFactory =
    (isFactory
       ? static_cast<bool>(std::dynamic_pointer_cast<PrototypeServiceFactory>(
           std::static_pointer_cast<ServiceFactory>(
             service->find("org.cppmicroservices.factory")->second)))
       : false);

  std::vector<std::string> classes;
  // Check if service implements claimed classes and that they exist.
  for (auto i : *service) {
    if (i.first.empty() || (!isFactory && i.second == nullptr)) {
      throw std::invalid_argument("Can't register as null class");
    }
    classes.push_back(i.first);
  }

  ServiceRegistrationBase res(
    bundle,
    service,
    CreateServiceProperties(
      properties, classes, isFactory, isPrototypeFactory));
  {
    auto l = this->Lock();
    US_UNUSED(l);
    services.insert(std::make_pair(res, classes));
    serviceRegistrations.push_back(res);
    for (auto& clazz : classes) {
      std::vector<ServiceRegistrationBase>& s = classServices[clazz];
      std::vector<ServiceRegistrationBase>::iterator ip =
        std::lower_bound(s.begin(), s.end(), res);
      s.insert(ip, res);
    }
  }

  ServiceReferenceBase r = res.GetReference(std::string());
  ServiceListeners::ServiceListenerEntries listeners;
  ServiceEvent registeredEvent(ServiceEvent::SERVICE_REGISTERED, r);
  bundle->coreCtx->listeners.GetMatchingServiceListeners(registeredEvent,
                                                         listeners);
  bundle->coreCtx->listeners.ServiceChanged(listeners, registeredEvent);
  return res;
}
예제 #15
0
ModuleSettings::PathList ModuleSettings::GetAutoLoadPaths()
{
  US_UNUSED(ModuleSettingsPrivate::Lock(moduleSettingsPrivate()));
  ModuleSettings::PathList paths(moduleSettingsPrivate()->autoLoadPaths.begin(),
                                 moduleSettingsPrivate()->autoLoadPaths.end());
  paths.insert(paths.end(), moduleSettingsPrivate()->extraPaths.begin(),
               moduleSettingsPrivate()->extraPaths.end());
  std::sort(paths.begin(), paths.end());
  paths.erase(std::unique(paths.begin(), paths.end()), paths.end());
  return paths;
}
예제 #16
0
void ServiceListeners::AddServiceListener(ModuleContext* mc, const ServiceListenerEntry::ServiceListener& listener,
                                          void* data, const std::string& filter)
{
  US_UNUSED(Lock(this));

  ServiceListenerEntry sle(mc, listener, data, filter);
  RemoveServiceListener_unlocked(sle);

  serviceSet.insert(sle);
  coreCtx->serviceHooks.HandleServiceListenerReg(sle);
  CheckSimple(sle);
}
예제 #17
0
std::vector<ServiceListenerHook::ListenerInfo> ServiceListeners::GetListenerInfoCollection() const
{
  US_UNUSED(Lock(this));
  std::vector<ServiceListenerHook::ListenerInfo> result;
  result.reserve(serviceSet.size());
  for (ServiceListenerEntries::const_iterator iter = serviceSet.begin(),
       iterEnd = serviceSet.end(); iter != iterEnd; ++iter)
  {
    result.push_back(*iter);
  }
  return result;
}
예제 #18
0
void ServiceRegistry::UpdateServiceRegistrationOrder(
  const ServiceRegistrationBase& sr,
  const std::vector<std::string>& classes)
{
  auto l = this->Lock();
  US_UNUSED(l);
  for (auto& clazz : classes) {
    std::vector<ServiceRegistrationBase>& s = classServices[clazz];
    s.erase(std::remove(s.begin(), s.end(), sr), s.end());
    s.insert(std::lower_bound(s.begin(), s.end(), sr), sr);
  }
}
예제 #19
0
void ServiceRegistry::GetRegisteredByBundle(
  BundlePrivate* p,
  std::vector<ServiceRegistrationBase>& res) const
{
  auto l = this->Lock();
  US_UNUSED(l);

  for (auto& sr : serviceRegistrations) {
    if (sr.d->bundle == p) {
      res.push_back(sr);
    }
  }
}
void ServiceListeners::Clear()
{
  bundleListenerMap.Lock(), bundleListenerMap.value.clear();
  {
    auto l = this->Lock(); US_UNUSED(l);
    serviceSet.clear();
    hashedServiceKeys.clear();
    complicatedListeners.clear();
    cache[0].clear();
    cache[1].clear();
  }

  frameworkListenerMap.Lock(), frameworkListenerMap.value.clear();
}
예제 #21
0
void ServiceListeners::HooksModuleStopped(ModuleContext* mc)
{
  US_UNUSED(Lock(this));
  std::vector<ServiceListenerEntry> entries;
  for (ServiceListenerEntries::iterator it = serviceSet.begin();
       it != serviceSet.end(); )
  {
    if (it->GetModuleContext() == mc)
    {
      entries.push_back(*it);
    }
  }
  coreCtx->serviceHooks.HandleServiceListenerUnreg(entries);
}
void ServiceListeners::HooksBundleStopped(const std::shared_ptr<BundleContextPrivate>& context)
{
  std::vector<ServiceListenerEntry> entries;
  {
    auto l = this->Lock(); US_UNUSED(l);
    for (auto& sle : serviceSet)
    {
      if (sle.GetBundleContext() == MakeBundleContext(context))
      {
        entries.push_back(sle);
      }
    }
  }
  coreCtx->serviceHooks.HandleServiceListenerUnreg(entries);
}
예제 #23
0
void ServiceRegistry::GetUsedByBundle(
  BundlePrivate* bundle,
  std::vector<ServiceRegistrationBase>& res) const
{
  auto l = this->Lock();
  US_UNUSED(l);

  for (std::vector<ServiceRegistrationBase>::const_iterator i =
         serviceRegistrations.begin();
       i != serviceRegistrations.end();
       ++i) {
    if (i->d->IsUsedByBundle(bundle)) {
      res.push_back(*i);
    }
  }
}
ListenerToken ServiceListeners::AddServiceListener(const std::shared_ptr<BundleContextPrivate>& context, const ServiceListener& listener,
                                                   void* data, const std::string& filter)
{
  // The following condition is true only if the listener is a non-static member function.
  // If so, the existing listener is replaced with the new listener.
  if (data != nullptr)
  {
    RemoveServiceListener(context, ListenerTokenId(0), listener, data);
  }

  auto token = MakeListenerToken();
  ServiceListenerEntry sle(context, listener, data, token.Id(), filter);
  {
    auto l = this->Lock(); US_UNUSED(l);
    serviceSet.insert(sle);
    CheckSimple_unlocked(sle);
  }
  coreCtx->serviceHooks.HandleServiceListenerReg(sle);
  return token;
}
/**
 * Called by the deprecated RemoveFrameworkListener(name_of_callable)
 */
void ServiceListeners::RemoveFrameworkListener(const std::shared_ptr<BundleContextPrivate>& context, const FrameworkListener& listener, void* data)
{
  // Note: Only the "data" part is used to compare for sameness. The listener comparison
  // always returns "true", because std::function objects aren't equality comparable.
  auto FrameworkListenerCompareListenerData = [](const FrameworkListener& listener, void* data,
                                              const std::pair<ListenerTokenId,
                                              ServiceListeners::FrameworkListenerEntry>& pair)
  {
    return data == std::get<1>(pair.second) &&
      listener.target<void(const FrameworkEvent&)>() == std::get<0>(pair.second).target<void(const FrameworkEvent&)>();
  };

  auto l = frameworkListenerMap.Lock(); US_UNUSED(l);
  auto& listeners = frameworkListenerMap.value[context];
  auto it = std::find_if(listeners.begin(), listeners.end(), std::bind(FrameworkListenerCompareListenerData, listener, data, std::placeholders::_1));
  if (it != listeners.end())
  {
    listeners.erase(it);
  }
}
예제 #26
0
ServiceReferenceBase ServiceRegistry::Get(BundlePrivate* bundle,
                                          const std::string& clazz) const
{
  auto l = this->Lock();
  US_UNUSED(l);
  try {
    std::vector<ServiceReferenceBase> srs;
    Get_unlocked(clazz, "", bundle, srs);
    DIAG_LOG(*core->sink) << "get service ref " << clazz << " for bundle "
                          << bundle->symbolicName << " = " << srs.size()
                          << " refs";

    if (!srs.empty()) {
      return srs.back();
    }
  } catch (const std::invalid_argument&) {
  }

  return ServiceReferenceBase();
}
예제 #27
0
void ServiceListeners::GetMatchingServiceListeners(const ServiceEvent& evt, ServiceListenerEntries& set,
                                                   bool lockProps)
{
  US_UNUSED(Lock(this));

  // Filter the original set of listeners
  ServiceListenerEntries receivers = serviceSet;
  coreCtx->serviceHooks.FilterServiceEventReceivers(evt, receivers);

  // Check complicated or empty listener filters
  for (std::list<ServiceListenerEntry>::const_iterator sse = complicatedListeners.begin();
       sse != complicatedListeners.end(); ++sse)
  {
    if (receivers.count(*sse) == 0) continue;
    const LDAPExpr& ldapExpr = sse->GetLDAPExpr();
    if (ldapExpr.IsNull() ||
        ldapExpr.Evaluate(evt.GetServiceReference().d->GetProperties(), false))
    {
      set.insert(*sse);
    }
  }

  //US_DEBUG << "Added " << set.size() << " out of " << n
  //         << " listeners with complicated filters";

  // Check the cache
  const std::vector<std::string> c(any_cast<std::vector<std::string> >
                                 (evt.GetServiceReference().d->GetProperty(ServiceConstants::OBJECTCLASS(), lockProps)));
  for (std::vector<std::string>::const_iterator objClass = c.begin();
       objClass != c.end(); ++objClass)
  {
    AddToSet(set, receivers, OBJECTCLASS_IX, *objClass);
  }

  long service_id = any_cast<long>(evt.GetServiceReference().d->GetProperty(ServiceConstants::SERVICE_ID(), lockProps));
  std::stringstream ss;
  ss << service_id;
  AddToSet(set, receivers, SERVICE_ID_IX, ss.str());
}
void ServiceListeners::RemoveServiceListener(const std::shared_ptr<BundleContextPrivate>& context, ListenerTokenId tokenId,
                                             const ServiceListener& listener, void* data)
{
  ServiceListenerEntry sle;
  {
    auto l = this->Lock(); US_UNUSED(l);
    std::function<bool(const ServiceListenerEntry&)> entryExists;
    if (tokenId)
    {
      assert(!listener);
      assert(data == nullptr);
      entryExists = [&context, &tokenId](const ServiceListenerEntry& entry) -> bool
      {
        return entry.Contains(context, tokenId);
      };
    }
    else
    {
      entryExists = [&context, &listener, &data](const ServiceListenerEntry& entry) -> bool
      {
        return entry.Contains(context, listener, data);
      };
    }

    auto it = std::find_if(serviceSet.begin(), serviceSet.end(), entryExists);
    if (it != serviceSet.end())
    {
      sle = *it;
      it->SetRemoved(true);
      RemoveFromCache_unlocked(*it);
      serviceSet.erase(it);
    }
  }
  if (!sle.IsNull())
  {
    coreCtx->serviceHooks.HandleServiceListenerUnreg(sle);
  }
}
void ServiceListeners::GetMatchingServiceListeners(const ServiceEvent& evt, ServiceListenerEntries& set)
{
  // Filter the original set of listeners
  ServiceListenerEntries receivers = (this->Lock(), serviceSet);
  // This must not be called with any locks held
  coreCtx->serviceHooks.FilterServiceEventReceivers(evt, receivers);

  // Get a copy of the service reference and keep it until we are
  // done with its properties.
  auto ref = evt.GetServiceReference();
  auto props = ref.d.load()->GetProperties();

  {
    auto l = this->Lock(); US_UNUSED(l);
    // Check complicated or empty listener filters
    for (auto& sse : complicatedListeners)
    {
      if (receivers.count(sse) == 0) continue;
      const LDAPExpr& ldapExpr = sse.GetLDAPExpr();
      if (ldapExpr.IsNull() ||
          ldapExpr.Evaluate(props, false))
      {
        set.insert(sse);
      }
    }

  // Check the cache
    const auto c = any_cast<std::vector<std::string>>(props->Value_unlocked(Constants::OBJECTCLASS));
    for (auto& objClass : c)
    {
      AddToSet_unlocked(set, receivers, OBJECTCLASS_IX, objClass);
    }

    long service_id = any_cast<long>(props->Value_unlocked(Constants::SERVICE_ID));
    AddToSet_unlocked(set, receivers, SERVICE_ID_IX, cppmicroservices::util::ToString((service_id)));
  }
}
bool ServiceRegistrationBasePrivate::IsUsedByBundle(BundlePrivate* bundle) const
{
  auto l = this->Lock(); US_UNUSED(l);
  return (dependents.find(bundle) != dependents.end()) ||
      (prototypeServiceInstances.find(bundle) != prototypeServiceInstances.end());
}