From b9c44e03a630b272cf1f7c8337ef7204c48ec5ff Mon Sep 17 00:00:00 2001 From: Artem Zhidkov Date: Tue, 13 Apr 2021 09:33:11 +0300 Subject: [PATCH] Possibility to load proprietary plugins on startup and check the license validity --- src/Config/Config_Keywords.h | 1 + src/Config/Config_ModuleReader.cpp | 40 ++++++++++++++++++++++++++- src/Config/Config_ModuleReader.h | 14 ++++++++++ src/Model/Model_Session.cpp | 5 ++++ src/Model/Model_Session.h | 3 ++ src/ModelAPI/ModelAPI_Events.cpp | 20 ++++++++++++++ src/ModelAPI/ModelAPI_Events.h | 28 ++++++++++++++++++- src/ModelAPI/ModelAPI_Session.h | 3 ++ src/ModuleBase/ModuleBase_IModule.cpp | 28 +++++++++++++++++++ src/ModuleBase/ModuleBase_IModule.h | 12 ++++++++ src/PartSet/PartSet_Module.cpp | 8 ++++++ 11 files changed, 160 insertions(+), 2 deletions(-) diff --git a/src/Config/Config_Keywords.h b/src/Config/Config_Keywords.h index cfbbcc2a1..4149e3816 100644 --- a/src/Config/Config_Keywords.h +++ b/src/Config/Config_Keywords.h @@ -146,6 +146,7 @@ MAYBE_UNUSED const static char* PLUGIN_SCRIPT = "script"; MAYBE_UNUSED const static char* PLUGIN_DEPENDENCY = "dependency"; MAYBE_UNUSED const static char* PLUGIN_USES = "uses"; MAYBE_UNUSED const static char* PLUGIN_DOCSECTION = "docsection"; +MAYBE_UNUSED const static char* PLUGIN_LICENSE = "license"; /* * Hardcoded xml entities of dataModel.xml diff --git a/src/Config/Config_ModuleReader.cpp b/src/Config/Config_ModuleReader.cpp index afbd79c85..83ea39d23 100644 --- a/src/Config/Config_ModuleReader.cpp +++ b/src/Config/Config_ModuleReader.cpp @@ -62,6 +62,16 @@ const std::map& Config_ModuleReader::featuresInFiles() return myFeaturesInFiles; } +const std::map& Config_ModuleReader::proprietaryFeatures() const +{ + return myProprietaryFeatures; +} + +const std::set& Config_ModuleReader::proprietaryPlugins() const +{ + return myProprietaryPlugins; +} + const std::set& Config_ModuleReader::modulePluginFiles() const { return myPluginFiles; @@ -81,6 +91,10 @@ std::string Config_ModuleReader::getModuleName() void Config_ModuleReader::addFeature(const std::string& theFeatureName, const std::string& thePluginConfig) { + if (myProprietaryFeatures.count(theFeatureName)) { + myProprietaryFeatures.erase(theFeatureName); + } + if (myFeaturesInFiles.count(theFeatureName)) { std::string anErrorMsg = "Can not register feature '%1' in plugin '%2'." " There is a feature with the same ID."; @@ -92,6 +106,21 @@ void Config_ModuleReader::addFeature(const std::string& theFeatureName, myFeaturesInFiles[theFeatureName] = thePluginConfig; } +void Config_ModuleReader::addFeatureRequireLicense(const std::string& theFeatureName, + const std::string& thePluginConfig) +{ + if (myFeaturesInFiles.count(theFeatureName) || + myProprietaryFeatures.count(theFeatureName)) { + std::string anErrorMsg = "Can not register feature '%1' in plugin '%2'." + " There is a feature with the same ID."; + Events_InfoMessage("Config_ModuleReader", anErrorMsg) + .arg(theFeatureName).arg(thePluginConfig).send(); + return; + } + + myProprietaryFeatures[theFeatureName] = thePluginConfig; +} + void Config_ModuleReader::processNode(xmlNodePtr theNode) { if (isNode(theNode, NODE_PLUGIN, NULL)) { @@ -112,10 +141,19 @@ void Config_ModuleReader::processNode(xmlNodePtr theNode) Events_Loop::loop()->send(aMess); } + std::string aLicense = getProperty(theNode, PLUGIN_LICENSE); + std::transform(aLicense.begin(), aLicense.end(), aLicense.begin(), ::tolower); + bool isLicensed = aLicense == "true"; + if (isLicensed) + myProprietaryPlugins.insert(aPluginName); + std::list aFeatures = importPlugin(aPluginName, aPluginConf, aPluginDocSection); std::list::iterator it = aFeatures.begin(); for (; it != aFeatures.end(); it++) { - addFeature(*it, aPluginConf); + if (isLicensed) + addFeatureRequireLicense(*it, aPluginConf); + else + addFeature(*it, aPluginConf); } } } diff --git a/src/Config/Config_ModuleReader.h b/src/Config/Config_ModuleReader.h index ce6198edb..24ae9a3b1 100644 --- a/src/Config/Config_ModuleReader.h +++ b/src/Config/Config_ModuleReader.h @@ -49,6 +49,12 @@ class Config_ModuleReader : public Config_XMLReader /// Returns map that describes which file contains a feature /// (the feature is key, the file is value) CONFIG_EXPORT const std::map& featuresInFiles() const; + /// Returns map containing features, which have licensed. + /// The valid license should be confirmed first + /// (the feature is key, the file is value) + CONFIG_EXPORT const std::map& proprietaryFeatures() const; + /// Returns proprietary plugins + CONFIG_EXPORT const std::set& proprietaryPlugins() const; /// Returns list of module's xml files CONFIG_EXPORT const std::set& modulePluginFiles() const; /// Returns module name: an xml attribute from the root of the plugins.xml: @@ -86,14 +92,22 @@ class Config_ModuleReader : public Config_XMLReader /// Save feature in myFeaturesInFiles. /// Generates an error if the feature name is already registered. void addFeature(const std::string& theFeatureName, const std::string& thePluginConfig); + /// Save feature in myFeaturesRequireLicense. + /// Generates an error if the feature name is already registered. + void addFeatureRequireLicense(const std::string& theFeatureName, + const std::string& thePluginConfig); private: std::map myFeaturesInFiles; ///< a feature name is key, a file is value + /// list of features, which need a license, and their config files + std::map myProprietaryFeatures; std::set myPluginFiles; ///< a feature name is key, a file is value /// a plugin name is key, a plugin type is value static std::map myPluginTypes; static std::set myDependencyModules; ///< set of loaded modules const char* myEventGenerated; ///< gives ability to send Feature_Messages to various listeners + + std::set myProprietaryPlugins; ///< list of plugins protected by license }; #endif /* CONFIG_XMLMODULEREADER_H_ */ diff --git a/src/Model/Model_Session.cpp b/src/Model/Model_Session.cpp index eb4ab5ff9..38ed84cfc 100644 --- a/src/Model/Model_Session.cpp +++ b/src/Model/Model_Session.cpp @@ -179,6 +179,11 @@ std::list Model_Session::redoList() return ROOT_DOC->redoList(); } +bool Model_Session::checkLicense(const std::string& thePluginName) +{ + return getPlugin(thePluginName); +} + ModelAPI_Plugin* Model_Session::getPlugin(const std::string& thePluginName) { if (myPluginObjs.find(thePluginName) == myPluginObjs.end()) { diff --git a/src/Model/Model_Session.h b/src/Model/Model_Session.h index 218659d5a..88397ec4c 100644 --- a/src/Model/Model_Session.h +++ b/src/Model/Model_Session.h @@ -127,6 +127,9 @@ class Model_Session : public ModelAPI_Session, public Events_Listener /// the plugin manager on call of the feature) MODEL_EXPORT virtual void registerPlugin(ModelAPI_Plugin* thePlugin); + /// Verifies the license for the plugin is valid + MODEL_EXPORT virtual bool checkLicense(const std::string& thePluginName); + /// Processes the configuration file reading MODEL_EXPORT virtual void processEvent(const std::shared_ptr& theMessage); diff --git a/src/ModelAPI/ModelAPI_Events.cpp b/src/ModelAPI/ModelAPI_Events.cpp index 506b26189..a34073894 100644 --- a/src/ModelAPI/ModelAPI_Events.cpp +++ b/src/ModelAPI/ModelAPI_Events.cpp @@ -469,3 +469,23 @@ const ListOfShape& ModelAPI_ShapesFailedMessage::shapes() const { return myShapes; } + + +// ===== ModelAPI_FeaturesLicenseValidMessage ===== +ModelAPI_FeaturesLicenseValidMessage::ModelAPI_FeaturesLicenseValidMessage( + const Events_ID theID, const void* theSender) + : Events_Message(theID, theSender) +{} + +ModelAPI_FeaturesLicenseValidMessage::~ModelAPI_FeaturesLicenseValidMessage() +{} + +void ModelAPI_FeaturesLicenseValidMessage::setFeatures(const std::set& theFeatures) +{ + myFeatures = theFeatures; +} + +const std::set& ModelAPI_FeaturesLicenseValidMessage::features() const +{ + return myFeatures; +} diff --git a/src/ModelAPI/ModelAPI_Events.h b/src/ModelAPI/ModelAPI_Events.h index 2ebd25b0f..b32ef747f 100644 --- a/src/ModelAPI/ModelAPI_Events.h +++ b/src/ModelAPI/ModelAPI_Events.h @@ -119,10 +119,12 @@ MAYBE_UNUSED static const char * EVENT_DOF_OBJECTS = "DoFObjects"; /// Event ID that requests updates visual attributes for presentations MAYBE_UNUSED static const char * EVENT_VISUAL_ATTRIBUTES = "UpdateVisualAttributes"; - /// Event ID that 1D-fillet failed (comes with ModelAPI_ShapesFailedMessage) MAYBE_UNUSED static const char * EVENT_OPERATION_SHAPES_FAILED = "OperationShapesFailed"; +/// Event ID that license of specified features is checked and valid +MAYBE_UNUSED static const char * EVENT_FEATURE_LICENSE_VALID = "FeaturesLicenseValid"; + /// Message that feature was changed (used for Object Browser update): moved, updated and deleted class MODELAPI_EXPORT ModelAPI_ObjectUpdatedMessage : public Events_MessageGroup { @@ -656,4 +658,28 @@ private: std::list< std::shared_ptr > myShapes; }; +/// Message that sends the features which license is checked and valid +class ModelAPI_FeaturesLicenseValidMessage : public Events_Message +{ +public: + /// Creates an message + MODELAPI_EXPORT + ModelAPI_FeaturesLicenseValidMessage(const Events_ID theID, const void* theSender = 0); + /// Default destructor + MODELAPI_EXPORT virtual ~ModelAPI_FeaturesLicenseValidMessage(); + /// Static. Returns EventID of the message. + MODELAPI_EXPORT static Events_ID eventId() + { + return Events_Loop::eventByName(EVENT_FEATURE_LICENSE_VALID); + } + + /// Sets list of features with valid license + MODELAPI_EXPORT void setFeatures(const std::set& theFeatures); + /// Returns list of features with valid license + MODELAPI_EXPORT const std::set& features() const; + +private: + std::set myFeatures; +}; + #endif diff --git a/src/ModelAPI/ModelAPI_Session.h b/src/ModelAPI/ModelAPI_Session.h index 339263fb0..7a1b2f40d 100644 --- a/src/ModelAPI/ModelAPI_Session.h +++ b/src/ModelAPI/ModelAPI_Session.h @@ -97,6 +97,9 @@ class MODELAPI_EXPORT ModelAPI_Session /// the plugin manager on call of the feature) virtual void registerPlugin(ModelAPI_Plugin* thePlugin) = 0; + /// Verifies the license for the plugin is valid + virtual bool checkLicense(const std::string& thePluginName) = 0; + /// Returns the root document of the application (that may contains sub-documents) virtual std::shared_ptr moduleDocument() = 0; diff --git a/src/ModuleBase/ModuleBase_IModule.cpp b/src/ModuleBase/ModuleBase_IModule.cpp index 678837a4d..90124f8d9 100644 --- a/src/ModuleBase/ModuleBase_IModule.cpp +++ b/src/ModuleBase/ModuleBase_IModule.cpp @@ -34,6 +34,7 @@ #include "ModuleBase_Dialog.h" #include "ModuleBase_IErrorMgr.h" +#include #include #include @@ -219,6 +220,33 @@ void ModuleBase_IModule::createFeatures() Config_ModuleReader aXMLReader = Config_ModuleReader(); aXMLReader.readAll(); myFeaturesInFiles = aXMLReader.featuresInFiles(); + myProprietaryFeatures = aXMLReader.proprietaryFeatures(); + myProprietaryPlugins = aXMLReader.proprietaryPlugins(); +} + +void ModuleBase_IModule::processProprietaryFeatures() +{ + std::set::iterator it = myFeaturesValidLicense.begin(); + while (it != myFeaturesValidLicense.end()) { + std::map::iterator aFound = myProprietaryFeatures.find(*it); + if (aFound == myProprietaryFeatures.end()) + ++it; + else { + myFeaturesInFiles[aFound->first] = aFound->second; + myProprietaryFeatures.erase(aFound); + std::set::iterator aRemoveIt = it++; + myFeaturesValidLicense.erase(aRemoveIt); + } + } +} + +void ModuleBase_IModule::loadProprietaryPlugins() +{ + for (std::set::const_iterator itP = myProprietaryPlugins.begin(); + itP != myProprietaryPlugins.end(); ++itP) { + if (!ModelAPI_Session::get()->checkLicense(*itP)) + Events_InfoMessage(*itP, "License of %1 plugin is not valid or not exist!").arg(*itP).send(); + } } diff --git a/src/ModuleBase/ModuleBase_IModule.h b/src/ModuleBase/ModuleBase_IModule.h index 3c3544e11..6ab1badf2 100644 --- a/src/ModuleBase/ModuleBase_IModule.h +++ b/src/ModuleBase/ModuleBase_IModule.h @@ -443,12 +443,24 @@ protected: /// Returns new instance of operation object (used in createOperation for customization) virtual ModuleBase_Operation* getNewOperation(const std::string& theFeatureId); + /// Load plugins required license + void loadProprietaryPlugins(); + + /// Collect features, which have valid license + void processProprietaryFeatures(); + protected: /// Reference to workshop ModuleBase_IWorkshop* myWorkshop; /// Map of features in XML std::map myFeaturesInFiles; + /// Map of features in XML, which require license but not confirmed yet + std::map myProprietaryFeatures; + /// Proprietary plugins + std::set myProprietaryPlugins; + /// Features, which have valid license + std::set myFeaturesValidLicense; std::map mySelectionFilters; diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 7c66e1748..8a703fa0f 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -188,6 +188,7 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop) Events_Loop* aLoop = Events_Loop::loop(); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_DOCUMENT_CHANGED)); aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); + aLoop->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_LICENSE_VALID)); registerSelectionFilter(SF_GlobalFilter, new PartSet_GlobalFilter(myWorkshop)); registerSelectionFilter(SF_FilterInfinite, new PartSet_FilterInfinite(myWorkshop)); @@ -287,6 +288,7 @@ void PartSet_Module::createFeatures() ModuleBase_IModule::createFeatures(); myRoot = new PartSet_RootNode(); myRoot->setWorkshop(workshop()); + ModuleBase_IModule::loadProprietaryPlugins(); } @@ -1711,6 +1713,12 @@ void PartSet_Module::processEvent(const std::shared_ptr& theMess mySketchMgr->previewSketchPlane()->createSketchPlane(aSketch, myWorkshop); } } + else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_LICENSE_VALID)) { + std::shared_ptr aMsg = + std::dynamic_pointer_cast(theMessage); + myFeaturesValidLicense.insert(aMsg->features().begin(), aMsg->features().end()); + processProprietaryFeatures(); + } } //****************************************************** -- 2.39.2