SET(PROJECT_HEADERS
Config_def.h
Config_FeatureMessage.h
+ Config_PluginMessage.h
Config_XMLReader.h
Config_ModuleReader.h
Config_FeatureReader.h
SET(PROJECT_SOURCES
Config_FeatureMessage.cpp
+ Config_PluginMessage.cpp
Config_XMLReader.cpp
Config_ModuleReader.cpp
Config_FeatureReader.cpp
// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
//
-#ifndef CONFIG_MESSAGE_H
-#define CONFIG_MESSAGE_H
+#ifndef CONFIG_FEATUREMESSAGE_H
+#define CONFIG_FEATUREMESSAGE_H
#include <Config_def.h>
#include <Events_Message.h>
const static char* PLUGIN_LIBRARY = "library";
const static char* PLUGIN_SCRIPT = "script";
const static char* PLUGIN_DEPENDENCY = "dependency";
+const static char* PLUGIN_USES = "uses";
/*
* Hardcoded xml entities of dataModel.xml
#include <Config_Common.h>
#include <Config_ModuleReader.h>
#include <Config_FeatureReader.h>
+#include <Config_PluginMessage.h>
#include <Events_InfoMessage.h>
#include <libxml/parser.h>
std::string aPluginLibrary = getProperty(theNode, PLUGIN_LIBRARY);
std::string aPluginScript = getProperty(theNode, PLUGIN_SCRIPT);
std::string aPluginName = addPlugin(aPluginLibrary, aPluginScript, aPluginConf);
+ std::string aUsesPlugin = getProperty(theNode, PLUGIN_USES);
+ if (!aUsesPlugin.empty()) { // send information about hte plugin dependencies
+ std::shared_ptr<Config_PluginMessage> aMess(new Config_PluginMessage(
+ Events_Loop::loop()->eventByName(Config_PluginMessage::EVENT_ID()), aPluginName));
+ aMess->setUses(aUsesPlugin);
+ Events_Loop::loop()->send(aMess);
+ }
std::list<std::string> aFeatures = importPlugin(aPluginName, aPluginConf);
std::list<std::string>::iterator it = aFeatures.begin();
void Config_ModuleReader::loadPlugin(const std::string& thePluginName)
{
+ // informs model that plugin loading is started
+ static const Events_ID kEVENT_ID =
+ Events_Loop::loop()->eventByName(Config_PluginMessage::EVENT_ID());
+ std::shared_ptr<Config_PluginMessage> aMess(new Config_PluginMessage(kEVENT_ID, thePluginName));
+ Events_Loop::loop()->send(aMess);
+
PluginType aType = Config_ModuleReader::Binary;
if(myPluginTypes.find(thePluginName) != myPluginTypes.end()) {
aType = myPluginTypes.at(thePluginName);
--- /dev/null
+// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "Config_PluginMessage.h"
+
+Config_PluginMessage::Config_PluginMessage(const Events_ID theId,
+ const std::string& thePluginId, const void* theParent)
+ : Events_Message(theId, theParent)
+{
+ myPluginId = thePluginId;
+}
+
+Config_PluginMessage::~Config_PluginMessage()
+{
+
+}
+
+const std::string& Config_PluginMessage::pluginId() const
+{
+ return myPluginId;
+}
+
+const std::string& Config_PluginMessage::uses() const
+{
+ return myUses;
+}
+
+void Config_PluginMessage::setUses(const std::string& theUses)
+{
+ myUses = theUses;
+}
--- /dev/null
+// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef CONFIG_PLUGINMESSAGE_H
+#define CONFIG_PLUGINMESSAGE_H
+
+#include <Config_def.h>
+#include <Events_Message.h>
+
+#include <string>
+
+/*!
+ * \class Config_PluginMessage
+ * \ingroup Config
+ * \brief Information that plugin is started to load.
+ *
+ * Contains the plugin name. Event is posted just before load of the plugin
+ * before registerPlugin call.
+ */
+class Config_PluginMessage : public Events_Message
+{
+ std::string myPluginId; ///< Plugin unique id
+ std::string myUses; ///< Which plugins are used by this one Id
+
+ public:
+ /// Event ID that plugin will be loaded
+ inline static const char* EVENT_ID()
+ {
+ static const char * MY_EVENT_ID("BeforePluginLoad");
+ return MY_EVENT_ID;
+ }
+
+ /// Constructs Config_PluginMessage
+ CONFIG_EXPORT Config_PluginMessage(const Events_ID theId,
+ const std::string& thePluginId, const void* theParent = 0);
+ /// Deletes Config_PluginMessage
+ CONFIG_EXPORT virtual ~Config_PluginMessage();
+
+ /// Plugin Id
+ CONFIG_EXPORT const std::string& pluginId() const;
+ /// Which plugins are used by this one Id
+ CONFIG_EXPORT const std::string& uses() const;
+ /// Sets which plugins are used by this one Id
+ CONFIG_EXPORT void setUses(const std::string& theUses);
+};
+
+#endif // CONFIG_MESSAGE_H
#include <libxml/tree.h>
#include <fstream>
+#include <sstream>
#ifdef WIN32
#pragma warning(disable : 4996) // for getenv
#endif
Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName)
- : myXmlDoc(NULL)
+ : myXmlDoc(NULL), myRootFileName(theXmlFileName)
{
- std::string prefix = "";
- Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
- if (aProp)
- prefix = aProp->value();
- /*
- * Get path to *.xml files (typically ./bin/../plugins/)
-
- * the problem: application may be launched using python executable,
- * to use environment variable (at least for the current moment)
- */
- if (prefix.empty())
- prefix = pluginConfigFile();
-
- myDocumentPath = prefix + FSEP + theXmlFileName;
- std::ifstream aTestFile(myDocumentPath);
- if (!aTestFile)
- Events_InfoMessage("Config_XMLReader", "Unable to open %1").arg(myDocumentPath).send();
- aTestFile.close();
+ myDocumentPath = findConfigFile(theXmlFileName);
+ if (myDocumentPath.empty()) {
+ Events_InfoMessage("Config_XMLReader", "Unable to open %1").arg(theXmlFileName).send();
+ }
}
Config_XMLReader::~Config_XMLReader()
return aValue;
}
+std::string Config_XMLReader::findConfigFile(const std::string theFileName, const int theFindIndex)
+{
+ int aResultIndex = 0;
+ for(int aSolution = 0; aSolution < 12; aSolution++) {
+ std::string aFileName;
+ if (aSolution == 0) {
+ Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
+ if (!aProp)
+ continue;
+ aFileName = aProp->value();
+ } else {
+ std::ostringstream anEnvName;
+ if (aSolution == 1)
+ anEnvName<<"SHAPER_ROOT_DIR";
+ else if (aSolution == 2)
+ anEnvName<<"OPENPARTS_ROOT_DIR";
+ else
+ anEnvName<<"OPENPARTS_PLUGINS_DIR";
+
+ char* anEnv = getenv(anEnvName.str().c_str());
+ if (!anEnv)
+ continue;
+ if (aSolution > 2) { // there may be several paths separated by ";" symbol
+ std::string anEnvPart = anEnv;
+ size_t aPosStart = 0, aPosEnd;
+ for(int aSubNum = 0; aSubNum < aSolution - 3; aSubNum++) {
+ aPosStart++;
+ aPosStart = anEnvPart.find(';', aPosStart);
+ if (aPosStart == std::string::npos)
+ break;
+ }
+ if (aPosStart == std::string::npos)
+ break;
+ if (aPosStart != 0)
+ aPosStart++;
+ aPosEnd = anEnvPart.find(';', aPosStart);
+ aFileName = anEnvPart.substr(aPosStart,
+ aPosEnd == std::string::npos ? aPosEnd : aPosEnd - aPosStart) + FSEP;
+ } else {
+ aFileName = std::string(anEnv) + FSEP;
+ }
+ if (aSolution == 1)
+ aFileName += std::string("share") + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
+ else if (aSolution == 2)
+ aFileName += "plugins";
+ }
+
+ aFileName += FSEP + theFileName;
+ std::ifstream aTestFile(aFileName);
+ if (aTestFile) {
+ if (aResultIndex == theFindIndex)
+ return aFileName;
+ aResultIndex++;
+ if (aSolution == 1) // don't allow SHAPER and OpenParts paths treated simultaneously
+ aSolution++;
+ }
+ }
+ return ""; // no files found
+}
+
void Config_XMLReader::readAll()
{
- // to load external modules dependencies (like GEOm for Connector Feature
+ // to load external modules dependencies (like GEOM for Connector Feature)
Config_ModuleReader::loadScript("salome.shaper.initConfig", false);
- xmlNodePtr aRoot = findRoot();
- readRecursively(aRoot);
+ for(int aSolution = 0; true; aSolution++) {
+ std::string aFoundFile = findConfigFile(myRootFileName, aSolution);
+ if (aFoundFile.empty()) {
+ break; // no more solutions
+ }
+
+ if (myXmlDoc != NULL) { // clear the previous XML document - now the new one will be opened
+ xmlFreeDoc(myXmlDoc);
+ myXmlDoc = NULL;
+ }
+ xmlNodePtr aRoot = findRoot(aFoundFile);
+ readRecursively(aRoot);
+ }
}
void Config_XMLReader::processNode(xmlNodePtr theNode)
return true;
}
-xmlNodePtr Config_XMLReader::findRoot()
+xmlNodePtr Config_XMLReader::findRoot(const std::string theDocumentPath)
{
+ std::string aDocPath = theDocumentPath.empty() ? myDocumentPath : theDocumentPath;
if (myXmlDoc == NULL) {
- myXmlDoc = xmlParseFile(myDocumentPath.c_str());
+ myXmlDoc = xmlParseFile(aDocPath.c_str());
}
if (myXmlDoc == NULL) {
#ifdef _DEBUG
- std::cout << "Config_XMLReader::import: " << "Document " << myDocumentPath
+ std::cout << "Config_XMLReader::import: " << "Document " << aDocPath
<< " is not parsed successfully." << std::endl;
#endif
return NULL;
*/
CONFIG_EXPORT void readAll();
/*!
- * Returns xmlNodePtr to the root of reader's document
- * or NULL if not found
+ * Returns xmlNodePtr to the root of reader's document or NULL if not found.
+ * If the path to the document to read is empty, uses myDocumentPath.
*/
- CONFIG_EXPORT xmlNodePtr findRoot();
+ CONFIG_EXPORT xmlNodePtr findRoot(const std::string theDocumentPath = "");
CONFIG_EXPORT const char* encoding() const;
+ /// Checks all possible paths to configuration file given
+ /// Uses theFindIndex if several solutions can be found (this is the number of solution to find)
+ CONFIG_EXPORT static std::string
+ findConfigFile(const std::string theFileName, const int theFindIndex = 0);
+
protected:
/*!
* \brief Allows to customize reader's behavior for a node. Virtual.
protected:
std::string myDocumentPath; ///< Path to the xml document
xmlDocPtr myXmlDoc; ///< Root of the xml document
+ std::string myRootFileName; ///< name of the root file
/// A map to store all parent's attributes.
/// The key has from "Node_Name:Node_Attribute"
std::map<std::string, std::string> myCachedAttributes;
#include <Config_ValidatorMessage.h>
#include <Config_ModuleReader.h>
#include <Config_ValidatorReader.h>
+#include <Config_PluginMessage.h>
#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_ResultPart.h>
return ROOT_DOC->redoList();
}
+ModelAPI_Plugin* Model_Session::getPlugin(const std::string& thePluginName)
+{
+ if (myPluginObjs.find(thePluginName) == myPluginObjs.end()) {
+ // before load the used plugins
+ if (myUsePlugins.find(thePluginName) != myUsePlugins.end()) {
+ std::string aUse = myUsePlugins[thePluginName];
+ std::stringstream aUseStream(aUse);
+ std::string aPluginName;
+ while (std::getline(aUseStream, aPluginName, ',')) {
+ if (myPluginObjs.find(aPluginName) == myPluginObjs.end())
+ getPlugin(aPluginName);
+ }
+ }
+ // load plugin library if not yet done
+ Config_ModuleReader::loadPlugin(thePluginName);
+ }
+ if (myPluginObjs.find(thePluginName) == myPluginObjs.end()) {
+ Events_InfoMessage("Model_Session", "Can not load plugin '%1'").arg(thePluginName).send();
+ return NULL;
+ }
+ return myPluginObjs[thePluginName];
+}
+
FeaturePtr Model_Session::createFeature(std::string theFeatureID, Model_Document* theDocOwner)
{
if (this != myImpl) {
std::pair<std::string, std::string>& aPlugin = myPlugins[theFeatureID]; // plugin and doc kind
if (!aPlugin.second.empty() && aPlugin.second != theDocOwner->kind()) {
Events_InfoMessage("Model_Session",
- "Feature '%1' can be created only in document '%2' by the XML definition")
- .arg(theFeatureID).arg(aPlugin.second).send();
+ "Feature '%1' can be created only in document '%2' by the XML definition")
+ .arg(theFeatureID).arg(aPlugin.second).send();
return FeaturePtr();
}
- myCurrentPluginName = aPlugin.first;
- if (myPluginObjs.find(myCurrentPluginName) == myPluginObjs.end()) {
- // load plugin library if not yet done
- Config_ModuleReader::loadPlugin(myCurrentPluginName);
- }
- if (myPluginObjs.find(myCurrentPluginName) != myPluginObjs.end()) {
- FeaturePtr aCreated = myPluginObjs[myCurrentPluginName]->createFeature(theFeatureID);
+ ModelAPI_Plugin* aPluginObj = getPlugin(aPlugin.first);
+ if (aPluginObj) {
+ FeaturePtr aCreated = aPluginObj->createFeature(theFeatureID);
if (!aCreated) {
- Events_InfoMessage("Model_Session",
- "Can not initialize feature '%1' in plugin '%2'")
- .arg(theFeatureID).arg(myCurrentPluginName).send();
+ Events_InfoMessage("Model_Session", "Can not initialize feature '%1' in plugin '%2'")
+ .arg(theFeatureID).arg(aPlugin.first).send();
}
return aCreated;
} else {
- Events_InfoMessage("Model_Session",
- "Can not load plugin '%1'").arg(myCurrentPluginName).send();
+ Events_InfoMessage("Model_Session", "Can not load plugin '%1'").arg(aPlugin.first).send();
}
} else {
Events_InfoMessage("Model_Session",
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED), 0, true);
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED), 0, true);
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_VALIDATOR_LOADED));
+ aLoop->registerListener(this, Events_Loop::eventByName(Config_PluginMessage::EVENT_ID()));
}
void Model_Session::processEvent(const std::shared_ptr<Events_Message>& theMessage)
static const Events_ID kFeatureEvent =
Events_Loop::eventByName(Config_FeatureMessage::MODEL_EVENT());
static const Events_ID kValidatorEvent = Events_Loop::eventByName(EVENT_VALIDATOR_LOADED);
+ static const Events_ID kPluginEvent = Events_Loop::eventByName(Config_PluginMessage::EVENT_ID());
if (theMessage->eventID() == kFeatureEvent) {
const std::shared_ptr<Config_FeatureMessage> aMsg =
std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
aMsg->parameters());
}
}
+ } else if (theMessage->eventID() == kPluginEvent) { // plugin is started to load
+ std::shared_ptr<Config_PluginMessage> aMsg =
+ std::dynamic_pointer_cast<Config_PluginMessage>(theMessage);
+ if (aMsg.get()) {
+ myCurrentPluginName = aMsg->pluginId();
+ if (!aMsg->uses().empty()) {
+ myUsePlugins[myCurrentPluginName] = aMsg->uses();
+ }
+ }
} else { // create/update/delete
if (myCheckTransactions && !isOperation())
Events_InfoMessage("Model_Session",
std::map<std::string, ModelAPI_Plugin*> myPluginObjs; ///< instances of the already plugins
std::string myCurrentPluginName; ///< name of the plugin that must be loaded currently
std::shared_ptr<ModelAPI_Document> myCurrentDoc; ///< current working document
+ ///< map from plugin id to plugins which are used by it (must be loaded before this one)
+ std::map<std::string, std::string> myUsePlugins;
/// if true, generates error if document is updated outside of transaction
bool myCheckTransactions;
/// Creates the feature object using plugins functionality
FeaturePtr createFeature(std::string theFeatureID, Model_Document* theDocOwner);
+ /// Get the plugin by name. If it is not loaded, load plugin.
+ ModelAPI_Plugin* getPlugin(const std::string& thePluginName);
+
friend class Model_Document;
friend class Model_Objects;
};
QPixmap aPixmap(theValue);
if (aPixmap.isNull()) {
- std::string aPluginPath = Config_XMLReader::pluginConfigFile();
- QString aPath = QString::fromStdString(aPluginPath) + QDir::separator() + theValue;
- if (QFile::exists(aPath))
- aPixmap = QPixmap(aPath);
+ std::string aPath = Config_XMLReader::findConfigFile(theValue.toStdString());
+ if (!aPath.empty())
+ aPixmap = QPixmap(QString::fromStdString(aPath));
}
return aPixmap;
}
QImage anImage(theValue);
if (anImage.isNull()) {
- std::string aPluginPath = Config_XMLReader::pluginConfigFile();
- QString aPath = QString::fromStdString(aPluginPath) + QDir::separator() + theValue;
- if (QFile::exists(aPath))
- anImage = QImage(aPath);
+ std::string aPath = Config_XMLReader::findConfigFile(theValue.toStdString());
+ if (!aPath.empty())
+ anImage = QImage(QString::fromStdString(aPath));
}
return anImage;
}