diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.cpp b/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.cpp index 3d58e4de79..f3337fdca9 100644 --- a/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.cpp +++ b/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.cpp @@ -1,718 +1,718 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "berryApplicationContainer.h" #include #include #include #include #include #include #include #include "berryApplicationHandle.h" #include "berryApplicationDescriptor.h" #include "berryCoreException.h" #include "berryErrorApplication.h" #include "berryMainApplicationLauncher.h" #include "berryProductExtensionBranding.h" #include "berryProviderExtensionBranding.h" #include #include "berryCTKPluginActivator.h" #include #include namespace berry { static const QString PI_OSGI = "org.blueberry.osgi"; const QString ApplicationContainer::PI_RUNTIME = "org.blueberry.core.runtime"; const QString ApplicationContainer::PT_APPLICATIONS = "applications"; const QString ApplicationContainer::PT_APP_VISIBLE = "visible"; const QString ApplicationContainer::PT_APP_THREAD = "thread"; const QString ApplicationContainer::PT_APP_THREAD_ANY = "any"; const QString ApplicationContainer::PT_APP_CARDINALITY = "cardinality"; const QString ApplicationContainer::PT_APP_CARDINALITY_SINGLETON_GLOBAL = "singleton-global"; const QString ApplicationContainer::PT_APP_CARDINALITY_SINGLETON_SCOPED = "singleton-scoped"; const QString ApplicationContainer::PT_APP_CARDINALITY_UNLIMITED = "*"; const QString ApplicationContainer::PT_APP_ICON = "icon"; const QString ApplicationContainer::PT_PRODUCTS = "products"; const QString ApplicationContainer::EXT_ERROR_APP = "org.blueberry.core.runtime.app.error"; const QString ApplicationContainer::PROP_PRODUCT = "blueberry.product"; const QString ApplicationContainer::PROP_BLUEBERRY_APPLICATION = "blueberry.application"; const QString ApplicationContainer::PROP_BLUEBERRY_APPLICATION_LAUNCH_DEFAULT = "blueberry.application.launchDefault"; const int ApplicationContainer::NOT_LOCKED = 0; const int ApplicationContainer::LOCKED_SINGLETON_GLOBAL_RUNNING = 1; const int ApplicationContainer::LOCKED_SINGLETON_GLOBAL_APPS_RUNNING = 2; const int ApplicationContainer::LOCKED_SINGLETON_SCOPED_RUNNING = 3; const int ApplicationContainer::LOCKED_SINGLETON_LIMITED_RUNNING = 4; const int ApplicationContainer::LOCKED_MAIN_THREAD_RUNNING = 5; ApplicationContainer::ApplicationContainer(ctkPluginContext* context, IExtensionRegistry* extensionRegistry) : context(context) , extensionRegistry(extensionRegistry) , launcherTracker(new ctkServiceTracker(context, this)) , branding(nullptr) , missingProductReported(false) , defaultMainThreadAppHandle(nullptr) , missingApp(false) { } ApplicationContainer::~ApplicationContainer() { } void ApplicationContainer::Start() { launcherTracker->open(); extensionRegistry->AddListener(this, PI_OSGI + '.' + PT_APPLICATIONS); // need to listen for system bundle stopping context->connectPluginListener(this, SLOT(PluginChanged(ctkPluginEvent)), Qt::DirectConnection); // register all the descriptors RegisterAppDescriptors(); QVariant startDefaultProp = context->getProperty(ApplicationContainer::PROP_BLUEBERRY_APPLICATION_LAUNCH_DEFAULT); if (startDefaultProp.isNull() || startDefaultProp.toBool()) { // Start the default application try { StartDefaultApp(true); } catch (const ctkApplicationException& e) { BERRY_ERROR << "An error occurred while starting the application:" << e.message(); } } } void ApplicationContainer::Stop() { // stop all applications StopAllApps(); context->disconnectPluginListener(this); extensionRegistry->RemoveListener(this); // flush the apps apps.clear(); branding.reset(); missingProductReported = false; launcherTracker->close(); } IBranding* ApplicationContainer::GetBranding() const { if (branding) { return branding.data(); } // try pluginContext properties if (context == nullptr) return nullptr; QString productId = context->getProperty(PROP_PRODUCT).toString(); if (productId.isEmpty()) return nullptr; QList entries = extensionRegistry->GetConfigurationElementsFor(PI_RUNTIME, PT_PRODUCTS, productId); if (!entries.isEmpty()) { // There should only be one product with the given id so just take the first element branding.reset(new ProductExtensionBranding(productId, entries[0])); return branding.data(); } QList elements = extensionRegistry->GetConfigurationElementsFor(PI_RUNTIME, PT_PRODUCTS); for (const auto &element : qAsConst(elements)) { if (element->GetName().compare("provider", Qt::CaseInsensitive) == 0) { try { IProductProvider* provider = element->CreateExecutableExtension("run"); QList products = provider->GetProducts(); for (const auto &product : qAsConst(products)) { if (productId.compare(product->GetId(), Qt::CaseInsensitive) == 0) { branding.reset(new ProviderExtensionBranding(product)); return branding.data(); } } } catch (const CoreException&) { BERRY_WARN << "Problem creating the provider registered by " << element->GetParent()->ToString() << "."; } } } if (!missingProductReported) { BERRY_WARN << "Product " << productId << " could not be found."; missingProductReported = true; } return nullptr; } ctkPluginContext* ApplicationContainer::GetContext() const { return context; } ApplicationDescriptor* ApplicationContainer::GetAppDescriptor(const QString& applicationId) { ApplicationDescriptor* result = nullptr; { - QMutexLocker l(&lock); + QMutexLocker l(&appDescLock); auto iter = apps.find(applicationId); result = iter == apps.end() ? nullptr : iter.value(); } if (result == nullptr) { RegisterAppDescriptor(applicationId); // try again just in case we are waiting for an event { - QMutexLocker l(&lock); + QMutexLocker l(&appDescLock); auto iter = apps.find(applicationId); result = iter == apps.end() ? nullptr : iter.value(); } } return result; } ApplicationDescriptor* ApplicationContainer::CreateAppDescriptor(const SmartPointer& appExtension) { if (org_blueberry_core_runtime_Activator::DEBUG) { BERRY_INFO << "Creating application descriptor: " << appExtension->GetUniqueIdentifier(); } QString iconPath; { - QMutexLocker l(&lock); + QMutexLocker l(&appDescLock); auto iter = apps.find(appExtension->GetUniqueIdentifier()); ApplicationDescriptor* appDescriptor = iter == apps.end() ? nullptr : iter.value(); if (appDescriptor != nullptr) { return appDescriptor; } // the appDescriptor does not exist for the app ID; create it QList configs = appExtension->GetConfigurationElements(); ApplicationDescriptor::Flags flags = ApplicationDescriptor::FLAG_CARD_SINGLETON_GLOGAL | ApplicationDescriptor::FLAG_VISIBLE | ApplicationDescriptor::FLAG_TYPE_MAIN_THREAD; int cardinality = 0; if (!configs.isEmpty()) { QString sVisible = configs[0]->GetAttribute(PT_APP_VISIBLE); if (!sVisible.isEmpty() && sVisible.compare("true", Qt::CaseInsensitive) != 0) { flags &= ~(ApplicationDescriptor::FLAG_VISIBLE); } QString sThread = configs[0]->GetAttribute(PT_APP_THREAD); if (PT_APP_THREAD_ANY == sThread) { flags |= ApplicationDescriptor::FLAG_TYPE_ANY_THREAD; flags &= ~(ApplicationDescriptor::FLAG_TYPE_MAIN_THREAD); } QString sCardinality = configs[0]->GetAttribute(PT_APP_CARDINALITY); if (!sCardinality.isEmpty()) { flags &= ~(ApplicationDescriptor::FLAG_CARD_SINGLETON_GLOGAL); // clear the global bit if (PT_APP_CARDINALITY_SINGLETON_SCOPED == sCardinality) { flags |= ApplicationDescriptor::FLAG_CARD_SINGLETON_SCOPED; } else if (PT_APP_CARDINALITY_UNLIMITED == sCardinality) { flags |= ApplicationDescriptor::FLAG_CARD_UNLIMITED; } else if (PT_APP_CARDINALITY_SINGLETON_GLOBAL == sCardinality) { flags |= ApplicationDescriptor::FLAG_CARD_SINGLETON_GLOGAL; } else { bool okay = false; cardinality = sCardinality.toInt(&okay); if (okay) { flags |= ApplicationDescriptor::FLAG_CARD_LIMITED; } else { // TODO should we log this? // just fall back to the default flags |= ApplicationDescriptor::FLAG_CARD_SINGLETON_GLOGAL; } } } QString defaultApp = GetDefaultAppId(); QString appId = appExtension->GetUniqueIdentifier(); if (defaultApp == appId) { flags |= ApplicationDescriptor::FLAG_DEFAULT_APP; } iconPath = configs[0]->GetAttribute(PT_APP_ICON); } appDescriptor = new ApplicationDescriptor(org_blueberry_core_runtime_Activator::GetPlugin(appExtension->GetContributor()), appExtension->GetUniqueIdentifier(), appExtension->GetLabel(), iconPath, flags, cardinality, this); // register the appDescriptor as a service ctkServiceRegistration sr = context->registerService(appDescriptor, appDescriptor->GetServiceProperties()); appDescriptor->SetServiceRegistration(sr); // save the app descriptor in the cache apps.insert(appExtension->GetUniqueIdentifier(), appDescriptor); return appDescriptor; } } ApplicationDescriptor*ApplicationContainer::RemoveAppDescriptor(const QString& applicationId) { if (org_blueberry_core_runtime_Activator::DEBUG) { BERRY_INFO << "Removing application descriptor: " << applicationId; } { - QMutexLocker l(&lock); + QMutexLocker l(&appDescLock); ApplicationDescriptor* appDescriptor = apps.take(applicationId); if (appDescriptor == nullptr) { return nullptr; } appDescriptor->Unregister(); return appDescriptor; } } void ApplicationContainer::StartDefaultApp(bool delayError) { // find the default application QString applicationId = GetDefaultAppId(); ApplicationDescriptor* defaultDesc = nullptr; QHash args; args.insert(ApplicationDescriptor::APP_DEFAULT, true); if (applicationId.isEmpty() && !delayError) { // the application id is not set; use a descriptor that will throw an exception args.insert(ErrorApplication::ERROR_EXCEPTION, QString("No application id has been found.")); defaultDesc = GetAppDescriptor(EXT_ERROR_APP); } else { defaultDesc = GetAppDescriptor(applicationId); if (defaultDesc == nullptr && !delayError) { // the application id is not available in the registry; use a descriptor that will throw an exception args.insert(ErrorApplication::ERROR_EXCEPTION, QString("Application \"%1\" could not be found in the registry. The applications available are: %2.") .arg(applicationId) .arg(GetAvailableAppsMsg())); defaultDesc = GetAppDescriptor(EXT_ERROR_APP); } } if (delayError && defaultDesc == nullptr) { // could not find the application; but we want to delay the error. // another bundle may get installed that provides the application // before we actually try to launch it. missingApp = true; return; } if (defaultDesc != nullptr) { defaultDesc->launch(args); } else { throw ctkApplicationException(ctkApplicationException::APPLICATION_INTERNAL_ERROR, "No application id has been found."); } } void ApplicationContainer::RegisterAppDescriptors() { QList availableApps = GetAvailableAppExtensions(); for (int i = 0; i < availableApps.size(); i++) { CreateAppDescriptor(availableApps[i]); } } void ApplicationContainer::RegisterAppDescriptor(const QString& applicationId) { IExtension::Pointer appExtension = GetAppExtension(applicationId); if (appExtension.IsNotNull()) { CreateAppDescriptor(appExtension); } } QList > ApplicationContainer::GetAvailableAppExtensions() const { IExtensionPoint::Pointer point = extensionRegistry->GetExtensionPoint(PI_OSGI + '.' + PT_APPLICATIONS); if (point.IsNull()) { return QList(); } return point->GetExtensions(); } QString ApplicationContainer::GetAvailableAppsMsg() const { QList availableApps = GetAvailableAppExtensions(); QString availableAppsMsg = ""; if (!availableApps.isEmpty()) { availableAppsMsg = availableApps.front()->GetUniqueIdentifier(); for (const auto &availableApp : qAsConst(availableApps)) { availableAppsMsg = availableAppsMsg + ", " + availableApp->GetUniqueIdentifier(); } } return availableAppsMsg; } SmartPointer ApplicationContainer::GetAppExtension(const QString& applicationId) const { return extensionRegistry->GetExtension(PI_OSGI, PT_APPLICATIONS, applicationId); } void ApplicationContainer::Launch(ApplicationHandle* appHandle) { bool isDefault = appHandle->IsDefault(); if (appHandle->getApplicationDescriptor()->GetThreadType() == ApplicationDescriptor::FLAG_TYPE_MAIN_THREAD) { // use the ApplicationLauncher provided by the framework to ensure it is launched on the main thread //DefaultApplicationListener curDefaultApplicationListener = null; MainApplicationLauncher* curMissingAppLauncher = nullptr; ctkApplicationLauncher* appLauncher = nullptr; { QMutexLocker l(this); appLauncher = launcherTracker->getService(); if (appLauncher == nullptr) { if (isDefault) { // we need to wait to allow the ApplicationLauncher to get registered; // save the handle to be launched as soon as the ApplicationLauncher is available defaultMainThreadAppHandle = appHandle; return; } throw ctkApplicationException(ctkApplicationException::APPLICATION_INTERNAL_ERROR, QString("The main thread is not available to launch the application: %1").arg(appHandle->getInstanceId())); } //curDefaultApplicationListener = defaultAppListener; curMissingAppLauncher = missingAppLauncher.data(); } //if (curDefaultApplicationListener != nullptr) //{ // curDefaultApplicationListener->launch(appHandle); //} //else if (curMissingAppLauncher != nullptr) { curMissingAppLauncher->Launch(appHandle); } else { appLauncher->launch(appHandle, appHandle->GetArguments()[IApplicationContext::APPLICATION_ARGS]); } } else { if (isDefault) { //DefaultApplicationListener curDefaultApplicationListener = null; MainApplicationLauncher* curMissingAppLauncher = nullptr; ctkApplicationLauncher* appLauncher = nullptr; { QMutexLocker l(this); appLauncher = launcherTracker->getService(); //if (defaultAppListener == nullptr) //{ // defaultAppListener = new DefaultApplicationListener(appHandle); //} //curDefaultApplicationListener = defaultAppListener; if (appLauncher == nullptr) { // we need to wait to allow the ApplicationLauncher to get registered; // save the default app listener to be launched as soon as the ApplicationLauncher is available //defaultMainThreadAppHandle = curDefaultApplicationListener; return; } curMissingAppLauncher = missingAppLauncher.data(); } if (curMissingAppLauncher != nullptr) { //curMissingAppLauncher->Launch(curDefaultApplicationListener); } else { //appLauncher->Launch(curDefaultApplicationListener, QVariant()); } } else { //AnyThreadAppLauncher.launchEclipseApplication(appHandle); } } } void ApplicationContainer::PluginChanged(const ctkPluginEvent& event) { // if this is not the system bundle stopping then ignore the event if ((ctkPluginEvent::STOPPING & event.getType()) == 0 || event.getPlugin()->getPluginId() != 0) { return; } // The system bundle is stopping; better stop all applications and containers now StopAllApps(); } void ApplicationContainer::StopAllApps() { // get a stapshot of running applications QList runningRefs = context->getServiceReferences("(!(application.state=STOPPING))"); for (const auto &runningRef : qAsConst(runningRefs)) { ctkApplicationHandle* handle = context->getService(runningRef); try { if (handle != nullptr) { handle->destroy(); } } catch (const std::exception&) { BERRY_WARN << QString("An error occurred while stopping the application: %1").arg(handle->getInstanceId()); } if (handle != nullptr) { context->ungetService(runningRef); } } } QString ApplicationContainer::GetDefaultAppId() const { if (!defaultAppId.isNull()) { return defaultAppId; } // try plugin context properties defaultAppId = context->getProperty(ApplicationContainer::PROP_BLUEBERRY_APPLICATION).toString(); if (!defaultAppId.isEmpty()) { return defaultAppId; } //Derive the application from the product information defaultAppId = GetBranding() == nullptr ? QString("") : GetBranding()->GetApplication(); return defaultAppId; } void ApplicationContainer::Lock(ApplicationHandle* /*appHandle*/) { /* ApplicationDescriptor eclipseApp = (ApplicationDescriptor) appHandle.getApplicationDescriptor(); { - QMutexLocker l(&lock); + QMutexLocker l(&appDescLock); switch (isLocked(eclipseApp)) { case NOT_LOCKED : break; case LOCKED_SINGLETON_GLOBAL_RUNNING : throw new ApplicationException(ApplicationException.APPLICATION_NOT_LAUNCHABLE, NLS.bind(Messages.singleton_running, activeGlobalSingleton.getInstanceId())); case LOCKED_SINGLETON_GLOBAL_APPS_RUNNING : throw new ApplicationException(ApplicationException.APPLICATION_NOT_LAUNCHABLE, Messages.apps_running); case LOCKED_SINGLETON_SCOPED_RUNNING : throw new ApplicationException(ApplicationException.APPLICATION_NOT_LAUNCHABLE, NLS.bind(Messages.singleton_running, activeScopedSingleton.getInstanceId())); case LOCKED_SINGLETON_LIMITED_RUNNING : throw new ApplicationException(ApplicationException.APPLICATION_NOT_LAUNCHABLE, NLS.bind(Messages.max_running, eclipseApp.getApplicationId())); case LOCKED_MAIN_THREAD_RUNNING : throw new ApplicationException(ApplicationException.APPLICATION_NOT_LAUNCHABLE, NLS.bind(Messages.main_running, activeMain.getInstanceId())); default : break; } // ok we can now successfully lock the container switch (eclipseApp.getCardinalityType()) { case ApplicationDescriptor::FLAG_CARD_SINGLETON_GLOGAL : activeGlobalSingleton = appHandle; break; case ApplicationDescriptor::FLAG_CARD_SINGLETON_SCOPED : activeScopedSingleton = appHandle; break; case ApplicationDescriptor::FLAG_CARD_LIMITED : if (activeLimited == null) activeLimited = new HashMap(3); ArrayList limited = (ArrayList) activeLimited.get(eclipseApp.getApplicationId()); if (limited == null) { limited = new ArrayList(eclipseApp.getCardinality()); activeLimited.put(eclipseApp.getApplicationId(), limited); } limited.add(appHandle); break; case ApplicationDescriptor::FLAG_CARD_UNLIMITED : break; default : break; } if (eclipseApp.getThreadType() == ApplicationDescriptor::FLAG_TYPE_MAIN_THREAD) { activeMain = appHandle; } activeHandles.add(appHandle); refreshAppDescriptors(); } */ } void ApplicationContainer::Unlock(ApplicationHandle* /*appHandle*/) { /* - QMutexLocker l(&lock); + QMutexLocker l(&appDescLock); if (activeGlobalSingleton == appHandle) activeGlobalSingleton = null; else if (activeScopedSingleton == appHandle) activeScopedSingleton = null; else if (((ApplicationDescriptor) appHandle.getApplicationDescriptor()).getCardinalityType() == ApplicationDescriptor::FLAG_CARD_LIMITED) { if (activeLimited != null) { ArrayList limited = (ArrayList) activeLimited.get(((ApplicationDescriptor) appHandle.getApplicationDescriptor()).getApplicationId()); if (limited != null) limited.remove(appHandle); } } if (activeMain == appHandle) activeMain = null; if (activeHandles.remove(appHandle)) refreshAppDescriptors(); // only refresh descriptors if we really unlocked something */ } int ApplicationContainer::IsLocked(const ApplicationDescriptor* /*eclipseApp*/) const { /* { - QMutexLocker l(&lock); + QMutexLocker l(&appDescLock); if (activeGlobalSingleton != null) return LOCKED_SINGLETON_GLOBAL_RUNNING; switch (eclipseApp.getCardinalityType()) { case ApplicationDescriptor::FLAG_CARD_SINGLETON_GLOGAL : if (activeHandles.size() > 0) return LOCKED_SINGLETON_GLOBAL_APPS_RUNNING; break; case ApplicationDescriptor::FLAG_CARD_SINGLETON_SCOPED : if (activeScopedSingleton != null) return LOCKED_SINGLETON_SCOPED_RUNNING; break; case ApplicationDescriptor::FLAG_CARD_LIMITED : if (activeLimited != null) { ArrayList limited = (ArrayList) activeLimited.get(eclipseApp.getApplicationId()); if (limited != null && limited.size() >= eclipseApp.getCardinality()) return LOCKED_SINGLETON_LIMITED_RUNNING; } break; case ApplicationDescriptor::FLAG_CARD_UNLIMITED : break; default : break; } if (eclipseApp.getThreadType() == ApplicationDescriptor::FLAG_TYPE_MAIN_THREAD && activeMain != null) return LOCKED_MAIN_THREAD_RUNNING; return NOT_LOCKED; } */ return NOT_LOCKED; } ctkApplicationLauncher* ApplicationContainer::addingService(const ctkServiceReference& reference) { ctkApplicationLauncher* appLauncher = nullptr; ctkApplicationRunnable* appRunnable = nullptr; { QMutexLocker l(this); appLauncher = context->getService(reference); // see if there is a default main threaded application waiting to run appRunnable = defaultMainThreadAppHandle; // null out so we do not attempt to start this handle again defaultMainThreadAppHandle = nullptr; if (appRunnable == nullptr && missingApp) { missingAppLauncher.reset(new MainApplicationLauncher(this)); appRunnable = missingAppLauncher.data(); missingApp = false; } } if (appRunnable != nullptr) { // found a main threaded app; start it now that the app launcher is available ApplicationHandle* handle = dynamic_cast(appRunnable); appLauncher->launch(appRunnable, handle ? handle->GetArguments()[IApplicationContext::APPLICATION_ARGS] : QVariant()); } return appLauncher; } void ApplicationContainer::modifiedService(const ctkServiceReference& /*reference*/, ctkApplicationLauncher* /*service*/) { // Do nothing } void ApplicationContainer::removedService(const ctkServiceReference& /*reference*/, ctkApplicationLauncher* /*service*/) { // Do nothing } void ApplicationContainer::Added(const QList >& extensions) { for (const IExtension::Pointer &extension : extensions) { CreateAppDescriptor(extension); } } void ApplicationContainer::Added(const QList >& /*extensionPoints*/) { // nothing } void ApplicationContainer::Removed(const QList >& extensions) { for (const IExtension::Pointer &extension : extensions) { RemoveAppDescriptor(extension->GetUniqueIdentifier()); } } void ApplicationContainer::Removed(const QList >& /*extensionPoints*/) { // nothing } void ApplicationContainer::RefreshAppDescriptors() { - QMutexLocker l(&lock); + QMutexLocker l(&appDescLock); for (ApplicationDescriptor* app : apps.values()) { app->RefreshProperties(); } } } diff --git a/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.h b/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.h index 778bce9295..6cda616af8 100644 --- a/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.h +++ b/Plugins/org.blueberry.core.runtime/src/internal/berryApplicationContainer.h @@ -1,180 +1,180 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef BERRYAPPLICATIONCONTAINER_H #define BERRYAPPLICATIONCONTAINER_H #include #include #include #include #include struct ctkApplicationLauncher; struct ctkApplicationRunnable; namespace berry { struct IBranding; struct IExtensionRegistry; class ApplicationDescriptor; class ApplicationHandle; class MainApplicationLauncher; /* * This container will discover installed BlueBerry applications and register the * appropriate ctkApplicationDescriptor service with the service registry. */ class ApplicationContainer : public QObject, public QMutex, private IRegistryEventListener, private ctkServiceTrackerCustomizer { Q_OBJECT private: static const QString PI_RUNTIME; // = "org.blueberry.core.runtime"; static const QString PT_APPLICATIONS; // = "applications"; static const QString PT_APP_VISIBLE; // = "visible"; static const QString PT_APP_THREAD; // = "thread"; static const QString PT_APP_THREAD_ANY; // = "any"; static const QString PT_APP_CARDINALITY; // = "cardinality"; static const QString PT_APP_CARDINALITY_SINGLETON_GLOBAL; // = "singleton-global"; static const QString PT_APP_CARDINALITY_SINGLETON_SCOPED; // = "singleton-scoped"; static const QString PT_APP_CARDINALITY_UNLIMITED; // = "*"; static const QString PT_APP_ICON; // = "icon"; static const QString PT_PRODUCTS; // = "products"; static const QString EXT_ERROR_APP; // = "org.blueberry.core.runtime.app.error"; static const QString PROP_PRODUCT; // = "blueberry.product"; static const QString PROP_BLUEBERRY_APPLICATION; // = "blueberry.application"; static const QString PROP_BLUEBERRY_APPLICATION_LAUNCH_DEFAULT; // = "blueberry.application.launchDefault"; static const int NOT_LOCKED; // = 0; static const int LOCKED_SINGLETON_GLOBAL_RUNNING; // = 1; static const int LOCKED_SINGLETON_GLOBAL_APPS_RUNNING; // = 2; static const int LOCKED_SINGLETON_SCOPED_RUNNING; // = 3; static const int LOCKED_SINGLETON_LIMITED_RUNNING; // = 4; static const int LOCKED_MAIN_THREAD_RUNNING; // = 5; ctkPluginContext* context; - QMutex lock; + QMutex appDescLock; // A map of ApplicationDescriptors keyed by application ID /* @GuardedBy(lock) */ QHash apps; IExtensionRegistry* extensionRegistry; QScopedPointer> launcherTracker; mutable QScopedPointer branding; mutable bool missingProductReported; /* @GuardedBy(lock) */ QList activeHandles; // the currently active application handles /* @GuardedBy(lock) */ ApplicationHandle* activeMain; // the handle currently running on the main thread /* @GuardedBy(lock) */ ApplicationHandle* activeGlobalSingleton; // the current global singleton handle /* @GuardedBy(lock) */ ApplicationHandle* activeScopedSingleton; // the current scoped singleton handle /* @GuardedBy(lock) */ QHash > activeLimited; // Map of handles that have cardinality limits mutable QString defaultAppId; //DefaultApplicationListener defaultAppListener; ctkApplicationRunnable* defaultMainThreadAppHandle; // holds the default app handle to be run on the main thread volatile bool missingApp; QScopedPointer missingAppLauncher; public: ApplicationContainer(ctkPluginContext* context, IExtensionRegistry* extensionRegistry); ~ApplicationContainer() override; void Start(); void Stop(); IBranding* GetBranding() const; ctkPluginContext* GetContext() const; void Launch(ApplicationHandle* appHandle); void Lock(ApplicationHandle* appHandle); void Unlock(ApplicationHandle* appHandle); int IsLocked(const ApplicationDescriptor* eclipseApp) const; void StartDefaultApp(bool delayError); private: Q_DISABLE_COPY(ApplicationContainer) friend class ApplicationHandle; /* * Only used to find the default application */ ApplicationDescriptor* GetAppDescriptor(const QString& applicationId); ApplicationDescriptor* CreateAppDescriptor(const SmartPointer& appExtension); ApplicationDescriptor* RemoveAppDescriptor(const QString& applicationId); /* * Registers an ApplicationDescriptor service for each eclipse application * available in the extension registry. */ void RegisterAppDescriptors(); void RegisterAppDescriptor(const QString& applicationId); /* * Returns a list of all the available application IDs which are available * in the extension registry. */ QList > GetAvailableAppExtensions() const; QString GetAvailableAppsMsg() const; /* * Returns the application extension for the specified application ID. * A RuntimeException is thrown if the extension does not exist for the * given application ID. */ SmartPointer GetAppExtension(const QString& applicationId) const; Q_SLOT void PluginChanged(const ctkPluginEvent& event); void StopAllApps(); QString GetDefaultAppId() const; ctkApplicationLauncher* addingService(const ctkServiceReference& reference) override; void modifiedService(const ctkServiceReference& reference, ctkApplicationLauncher* service) override; void removedService(const ctkServiceReference& reference, ctkApplicationLauncher* service) override; void Added(const QList >& extensions) override; void Added(const QList >& extensionPoints) override; void Removed(const QList >& extensions) override; void Removed(const QList >& extensionPoints) override; void RefreshAppDescriptors(); }; } #endif // BERRYAPPLICATIONCONTAINER_H