ws_config2Service.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2017 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "ws_config2Service.hpp"
  14. #include "jfile.hpp"
  15. #include "SchemaItem.hpp"
  16. #include "jexcept.hpp"
  17. #include "ws_config2Error.hpp"
  18. static const std::string CFG2_MASTER_CONFIG_FILE = "environment.xsd";
  19. static const std::string CFG2_CONFIG_DIR = COMPONENTFILES_DIR PATHSEPSTR "config2xml" PATHSEPSTR;
  20. static const std::string CFG2_SOURCE_DIR = CONFIG_SOURCE_DIR;
  21. static const std::string ACTIVE_ENVIRONMENT_FILE = CONFIG_DIR PATHSEPSTR ENV_XML_FILE;
  22. Cws_config2Ex::Cws_config2Ex()
  23. {
  24. m_sessionKey = 0;
  25. }
  26. Cws_config2Ex::~Cws_config2Ex()
  27. {
  28. }
  29. bool Cws_config2Ex::onOpenSession(IEspContext &context, IEspOpenSessionRequest &req, IEspOpenSessionResponse &resp)
  30. {
  31. bool loaded = false;
  32. ConfigMgrSession *pNewSession = new ConfigMgrSession();
  33. std::string inputMasterFile = req.getMasterSchemaFile();
  34. std::string inputSchemaPath = req.getSchemaPath();
  35. std::string inputSourcePath = req.getSourcePath();
  36. std::string inputActivePath = req.getSourcePath();
  37. pNewSession->masterConfigFile = (inputMasterFile != "") ? inputMasterFile : CFG2_MASTER_CONFIG_FILE;
  38. pNewSession->username = req.getUsername();
  39. pNewSession->schemaPath = !inputSchemaPath.empty() ? inputSchemaPath : CFG2_CONFIG_DIR;
  40. pNewSession->sourcePath = !inputSourcePath.empty() ? inputSourcePath : CFG2_SOURCE_DIR;
  41. pNewSession->activePath = !inputActivePath.empty() ? inputActivePath : ACTIVE_ENVIRONMENT_FILE;
  42. //
  43. // Only XML supported at this time
  44. pNewSession->configType = XML;
  45. //
  46. // Open the session by loading the schema, which is done during session init
  47. std::vector<std::string> cfgParms;
  48. cfgParms.push_back("buildset.xml"); // Note that this is hardcoded for now, when other types suppored, must be passed in
  49. if (pNewSession->initializeSession(cfgParms))
  50. {
  51. std::string sessionId = std::to_string(m_sessionKey);
  52. resp.setSessionId(sessionId.c_str());
  53. m_sessions[sessionId] = pNewSession;
  54. m_sessionKey++;
  55. }
  56. else
  57. {
  58. std::string errMsg = pNewSession->getLastMsg();
  59. delete pNewSession;
  60. throw MakeStringException(CFGMGR_ERROR_SESSION_NOT_CREATED, "Error creating session, error: %s", errMsg.c_str());
  61. }
  62. return true;
  63. }
  64. bool Cws_config2Ex::onCloseSession(IEspContext &context, IEspCloseSessionRequest &req, IEspEmptyResponse &resp)
  65. {
  66. std::string sessionId = req.getSessionId();
  67. ConfigMgrSession *pSession = getConfigSession(sessionId);
  68. if (pSession->modified)
  69. {
  70. if (!req.getForceClose())
  71. {
  72. throw MakeStringException(CFGMGR_ERROR_ENVIRONMENT_MODIFIED, "Current environment is modified, either save or close it first");
  73. }
  74. }
  75. deleteConfigSession(sessionId);
  76. return true;
  77. }
  78. bool Cws_config2Ex::onGetOpenSessions(IEspContext &context, IEspListOpenSessionsRequest &req, IEspListOpenSessionsResponse &resp)
  79. {
  80. IArrayOf<IEspOpenSessionInfo> openSessions;
  81. for (auto sessionIt=m_sessions.begin(); sessionIt != m_sessions.end(); ++sessionIt)
  82. {
  83. ConfigMgrSession *pSession = sessionIt->second;
  84. Owned<IEspOpenSessionInfo> pSessionInfo = createOpenSessionInfo();
  85. pSessionInfo->setUsername(pSession->username.c_str());
  86. pSessionInfo->setCurEnvironmentFile(pSession->curEnvironmentFile.c_str());
  87. pSessionInfo->setLocked(pSession->locked);
  88. pSessionInfo->setModified(pSession->modified);
  89. openSessions.append(*pSessionInfo.getLink());
  90. }
  91. resp.setOpenSessions(openSessions);
  92. return true;
  93. }
  94. bool Cws_config2Ex::onGetEnvironmentFileList(IEspContext &context, IEspCommonSessionRequest &req, IEspGetEnvironmentListResponse &resp)
  95. {
  96. std::string sessionId = req.getSessionId();
  97. ConfigMgrSession *pSession = getConfigSession(sessionId);
  98. //
  99. // Calculate md5 checksum of the current active environment for use in comparing against the available list
  100. // of environments so the active environment is identified in the returned list
  101. StringBuffer activeConfig_md5sum;
  102. md5_filesum(pSession->activePath.c_str(), activeConfig_md5sum);
  103. IArrayOf<IEspEnvironmentFileType> environmentFiles;
  104. Owned<IFile> pDir = createIFile(CFG2_SOURCE_DIR.c_str());
  105. if (pDir->exists())
  106. {
  107. Owned<IDirectoryIterator> it = pDir->directoryFiles(NULL, false, true);
  108. ForEach(*it)
  109. {
  110. StringBuffer filename;
  111. it->getName(filename);
  112. String str(filename);
  113. str.toLowerCase();
  114. if (str.endsWith(pSession->getEnvironmentFileExtension().c_str()))
  115. {
  116. Owned<IEspEnvironmentFileType> pEnvFile = createEnvironmentFileType();
  117. pEnvFile->setFilename(filename.str());
  118. //
  119. // See if active
  120. StringBuffer curEnvFile_md5sum;
  121. std::string fullPath;
  122. std::string fname = filename.str();
  123. pSession->getEnvironmentFullyQualifiedPath(fname, fullPath);
  124. md5_filesum(fullPath.c_str(), curEnvFile_md5sum);
  125. if (strcmp(curEnvFile_md5sum.str(),activeConfig_md5sum.str()) == 0)
  126. {
  127. pEnvFile->setIsActive(true);
  128. }
  129. environmentFiles.append(*pEnvFile.getLink());
  130. }
  131. }
  132. resp.setEnvironmentFiles(environmentFiles);
  133. }
  134. return true;
  135. }
  136. bool Cws_config2Ex::onOpenEnvironmentFile(IEspContext &context, IEspOpenEnvironmentFileRequest &req, IEspOpenEnvironmentFileResponse &resp)
  137. {
  138. bool doOpen = false;
  139. ConfigMgrSession *pSession = getConfigSession(req.getSessionId());
  140. //
  141. // See if modified (which can only be true if an environment is currently loaded)
  142. if (pSession->modified)
  143. {
  144. throw MakeStringException(CFGMGR_ERROR_ENVIRONMENT_MODIFIED, "Current environment is modified, either save or close it first");
  145. }
  146. std::string newEnvFile = req.getFilename();
  147. if (!pSession->loadEnvironment(newEnvFile))
  148. {
  149. throw MakeStringException(CFGMGR_ERROR_ENVIRONMENT_NOT_LOADED, "Unable to load environment, error = %s", pSession->getLastMsg().c_str());
  150. }
  151. resp.setRootNodeId("0");
  152. return true;
  153. }
  154. bool Cws_config2Ex::onCloseEnvironmentFile(IEspContext &context, IEspCloseEnvironmentFileRequest &req, IEspEmptyResponse &resp)
  155. {
  156. bool doClose = false;
  157. ConfigMgrSession *pSession = getConfigSession(req.getSessionId());
  158. if (pSession->modified)
  159. {
  160. pSession = getConfigSessionForUpdate(req.getSessionId(), req.getSessionLockKey()); // forces the lock key check
  161. //
  162. // Since modified, only allow close if discard changes is set
  163. if (!req.getDiscardChanges())
  164. {
  165. throw MakeStringException(CFGMGR_ERROR_ENVIRONMENT_MODIFIED, "Current environment is modified, either save, close, or set discardChanges");
  166. }
  167. }
  168. pSession->closeEnvironment();
  169. return true;
  170. }
  171. bool Cws_config2Ex::onSaveEnvironmentFile(IEspContext &context, IEspSaveEnvironmentFileRequest &req, IEspEmptyResponse &resp)
  172. {
  173. // todo: If this envronment file is loaded by any other session, go mark that session that the environment has changed
  174. // and don't allow a save w/o reloading first. maybe add a reload request. Add relevant errors.
  175. // also make sure if filename is specified that it
  176. // 1. does not match the current loaded environment if current environment is modified and lock key is missing or does not match
  177. // 2. does not match the name of any other open session's loaded and locked environment.
  178. std::string sessionId = req.getSessionId();
  179. ConfigMgrSession *pSession = getConfigSession(sessionId); // only verify session ID, lock key verified below
  180. std::string saveFilename = req.getFilename();
  181. bool doSave = true;
  182. bool wasSaved = false;
  183. //
  184. // If a new filename is given, then search existing sessions to see if the filename matches any open
  185. // environments that have locked it. If so, prevent the save.
  186. if (!saveFilename.empty())
  187. {
  188. for (auto sessionIt = m_sessions.begin(); sessionIt != m_sessions.end(); ++sessionIt)
  189. {
  190. if (sessionIt->second->curEnvironmentFile == saveFilename && sessionIt->second->locked)
  191. {
  192. throw MakeStringException(CFGMGR_ERROR_ENVIRONMENT_LOCKED, "Target environment is currently locked by another session");
  193. }
  194. }
  195. }
  196. //
  197. // If session if modified and saving over exiting environment, check lock key
  198. if (saveFilename.empty() && pSession->modified)
  199. {
  200. pSession = getConfigSessionForUpdate(req.getSessionLockKey(), req.getSessionLockKey());
  201. }
  202. if (!pSession->saveEnvironment(saveFilename))
  203. {
  204. throw MakeStringException(CFGMGR_ERROR_SAVE_ENVIRONMENT, "There was a problem saving the environment");
  205. }
  206. //
  207. // Save was completed, if a new filename was given, then search existing sessions to see if the filename
  208. // matches any open environments. If so, mark the session as having the environment externally modified
  209. // which prevents that session from locking the environment. Note that another session having the
  210. // environment locked would have prevented this session from locking the same environment.
  211. if (!saveFilename.empty())
  212. {
  213. for (auto sessionIt = m_sessions.begin(); sessionIt != m_sessions.end(); ++sessionIt)
  214. {
  215. if (sessionIt->second->curEnvironmentFile == saveFilename)
  216. {
  217. sessionIt->second->externallyModified = true;
  218. }
  219. }
  220. }
  221. return true;
  222. }
  223. bool Cws_config2Ex::onLockSession(IEspContext &context, IEspCommonSessionRequest &req, IEspLockSessionResponse &resp)
  224. {
  225. std::string sessionId = req.getSessionId();
  226. ConfigMgrSession *pSession = getConfigSession(sessionId);
  227. if (pSession->locked)
  228. {
  229. throw MakeStringException(CFGMGR_ERROR_ENVIRONMENT_LOCKED, "Current enironment already locked");
  230. }
  231. if (pSession->curEnvironmentFile.empty())
  232. {
  233. throw MakeStringException(CFGMGR_ERROR_NO_ENVIRONMENT, "No environment loaded");
  234. }
  235. if (pSession->externallyModified)
  236. {
  237. throw MakeStringException(CFGMGR_ERROR_ENV_EXTERNAL_CHANGE, "No environment loaded");
  238. }
  239. //
  240. // Search existing sessions to see if any currently have this environment file locked
  241. for (auto sessionIt = m_sessions.begin(); sessionIt != m_sessions.end(); ++sessionIt)
  242. {
  243. if (sessionIt->second != pSession && sessionIt->second->locked && pSession->curEnvironmentFile == sessionIt->second->curEnvironmentFile)
  244. {
  245. throw MakeStringException(CFGMGR_ERROR_ENVIRONMENT_LOCKED, "Environment is locked by another session");
  246. }
  247. }
  248. if (pSession->lock())
  249. {
  250. resp.setSessionLockKey(pSession->lockKey.c_str());
  251. }
  252. else
  253. {
  254. throw MakeStringException(CFGMGR_ERROR_ENVIRONMENT_LOCKING, "Error locking the session");
  255. }
  256. return true;
  257. }
  258. bool Cws_config2Ex::onUnlockSession(IEspContext &context, IEspUnlockSessionRequest &req, IEspEmptyResponse &resp)
  259. {
  260. ConfigMgrSession *pSession = getConfigSessionForUpdate(req.getSessionId(), req.getSessionLockKey());
  261. if (!pSession->unlock(req.getSessionLockKey()))
  262. {
  263. throw MakeStringException(CFGMGR_ERROR_ENVIRONMENT_LOCKING, "Error unlocking the session");
  264. }
  265. return true;
  266. }
  267. bool Cws_config2Ex::onGetNode(IEspContext &context, IEspNodeRequest &req, IEspGetNodeResponse &resp)
  268. {
  269. std::string sessionId = req.getSessionId();
  270. std::string id = req.getNodeId();
  271. ConfigMgrSession *pSession = getConfigSession(sessionId);
  272. Status status;
  273. EnvironmentMgr *pEnvMgr = pSession->m_pEnvMgr;
  274. std::shared_ptr<EnvironmentNode> pNode = pEnvMgr->getEnvironmentNode(id);
  275. if (pNode == nullptr)
  276. {
  277. throw MakeStringException(CFGMGR_ERROR_NODE_INVALID, "Environment node ID is not valid");
  278. }
  279. getNodeResponse(pNode, resp);
  280. pNode->validate(status, false); // validate this node only
  281. addStatusToResponse(status, pSession, reinterpret_cast<IEspStatusResponse &>(resp));
  282. //
  283. // Finalize the response
  284. resp.setNodeId(id.c_str());
  285. return true;
  286. }
  287. bool Cws_config2Ex::onInsertNode(IEspContext &context, IEspInsertNodeRequest &req, IEspGetNodeResponse &resp)
  288. {
  289. ConfigMgrSession *pSession = getConfigSessionForUpdate(req.getSessionId(), req.getSessionLockKey());
  290. Status status;
  291. std::string parentNodeId = req.getParentNodeId();
  292. std::shared_ptr<EnvironmentNode> pNode = pSession->m_pEnvMgr->getEnvironmentNode(parentNodeId);
  293. if (pNode)
  294. {
  295. std::shared_ptr<EnvironmentNode> pNewNode = pSession->m_pEnvMgr->addNewEnvironmentNode(parentNodeId, req.getNodeType(), status);
  296. if (pNewNode)
  297. {
  298. getNodeResponse(pNewNode, resp);
  299. resp.setNodeId(pNewNode->getId().c_str());
  300. pSession->modified = true;
  301. }
  302. }
  303. else
  304. {
  305. throw MakeStringException(CFGMGR_ERROR_NODE_INVALID, "Environment node ID is not valid");
  306. }
  307. addStatusToResponse(status, pSession, reinterpret_cast<IEspStatusResponse &>(resp));
  308. return true;
  309. }
  310. bool Cws_config2Ex::onRemoveNode(IEspContext &context, IEspRemoveNodeRequest &req, IEspStatusResponse &resp)
  311. {
  312. std::string sessionId = req.getSessionId();
  313. std::string key = req.getSessionLockKey();
  314. ConfigMgrSession *pSession = getConfigSessionForUpdate(sessionId, key);
  315. Status status;
  316. std::string nodeId = req.getNodeId();
  317. if (!pSession->m_pEnvMgr->removeEnvironmentNode(nodeId))
  318. {
  319. throw MakeStringException(CFGMGR_ERROR_NODE_INVALID, "Environment node ID is not valid");
  320. }
  321. pSession->modified = true;
  322. pSession->m_pEnvMgr->validate(status, false);
  323. addStatusToResponse(status, pSession, resp);
  324. return true;
  325. }
  326. bool Cws_config2Ex::onValidateEnvironment(IEspContext &context, IEspValidateEnvironmentRequest &req, IEspStatusResponse &resp)
  327. {
  328. Status status;
  329. std::string sessionId = req.getSessionId();
  330. ConfigMgrSession *pSession = getConfigSession(sessionId);
  331. pSession->m_pEnvMgr->validate(status, req.getIncludeHiddenNodes());
  332. addStatusToResponse(status, pSession, resp);
  333. return true;
  334. }
  335. bool Cws_config2Ex::onSetValues(IEspContext &context, IEspSetValuesRequest &req, IEspStatusResponse &resp)
  336. {
  337. Status status;
  338. std::string sessionId = req.getSessionId();
  339. std::string key = req.getSessionLockKey();
  340. ConfigMgrSession *pSession = getConfigSessionForUpdate(sessionId, key);
  341. std::string id = req.getNodeId();
  342. std::shared_ptr<EnvironmentNode> pNode = pSession->m_pEnvMgr->getEnvironmentNode(id);
  343. if (pNode == nullptr)
  344. {
  345. throw MakeStringException(CFGMGR_ERROR_NODE_INVALID, "Environment node ID is not valid");
  346. }
  347. bool forceCreate = req.getForceCreate();
  348. bool allowInvalid = req.getAllowInvalid();
  349. IArrayOf<IConstAttributeValueType> &attrbuteValues = req.getAttributeValues();
  350. std::vector<NameValue> values;
  351. ForEachItemIn(i, attrbuteValues)
  352. {
  353. IConstAttributeValueType& attrVal = attrbuteValues.item(i);
  354. NameValue value;
  355. value.name = attrVal.getName();
  356. value.value = attrVal.getValue();
  357. values.push_back(value);
  358. }
  359. pNode->setAttributeValues(values, status, allowInvalid, forceCreate);
  360. pSession->modified = true;
  361. addStatusToResponse(status, pSession, resp);
  362. return true;
  363. }
  364. bool Cws_config2Ex::onGetParents(IEspContext &context, IEspNodeRequest &req, IEspGetParentsResponse &resp)
  365. {
  366. std::string nodeId = req.getNodeId();
  367. std::string sessionId = req.getSessionId();
  368. ConfigMgrSession *pSession = getConfigSession(sessionId);
  369. StringArray ids;
  370. std::shared_ptr<EnvironmentNode> pNode = pSession->m_pEnvMgr->getEnvironmentNode(nodeId);
  371. if (pNode == nullptr)
  372. {
  373. throw MakeStringException(CFGMGR_ERROR_NODE_INVALID, "Environment node ID is not valid");
  374. }
  375. while (pNode)
  376. {
  377. pNode = pNode->getParent();
  378. if (pNode)
  379. {
  380. ids.append(pNode->getId().c_str());
  381. }
  382. }
  383. return true;
  384. }
  385. bool Cws_config2Ex::onGetNodeTree(IEspContext &context, IEspGetTreeRequest &req, IEspGetTreeResponse &resp)
  386. {
  387. std::string nodeId = req.getNodeId();
  388. std::string sessionId = req.getSessionId();
  389. ConfigMgrSession *pSession = getConfigSession(sessionId);
  390. std::shared_ptr<EnvironmentNode> pNode = pSession->m_pEnvMgr->getEnvironmentNode(nodeId);
  391. if (pNode)
  392. {
  393. getNodeTree(pNode, resp.updateTree(), req.getNumLevels(), req.getIncludeAttributes());
  394. }
  395. return true;
  396. }
  397. void Cws_config2Ex::addStatusToResponse(const Status &status, ConfigMgrSession *pSession, IEspStatusResponse &resp) const
  398. {
  399. std::vector<statusMsg> statusMsgs = status.getMessages();
  400. IArrayOf<IEspStatusMsgType> msgs;
  401. for (auto msgIt=statusMsgs.begin(); msgIt!=statusMsgs.end(); ++msgIt)
  402. {
  403. Owned<IEspStatusMsgType> pStatusMsg = createStatusMsgType();
  404. pStatusMsg->setNodeId((*msgIt).nodeId.c_str());
  405. pStatusMsg->setMsg((*msgIt).msg.c_str());
  406. pStatusMsg->setMsgLevel(status.getStatusTypeString((*msgIt).msgLevel).c_str());
  407. pStatusMsg->setAttribute((*msgIt).attribute.c_str());
  408. if (!(*msgIt).nodeId.empty() && pSession != nullptr)
  409. {
  410. StringArray ids;
  411. getNodeParents((*msgIt).nodeId, pSession, ids);
  412. std::shared_ptr<EnvironmentNode> pNode = pSession->m_pEnvMgr->getEnvironmentNode((*msgIt).nodeId);
  413. pStatusMsg->setNodeName(pNode->getName().c_str());
  414. pStatusMsg->setParentIdList(ids);
  415. }
  416. msgs.append(*pStatusMsg.getLink());
  417. }
  418. resp.updateStatus().setStatus(msgs);
  419. resp.updateStatus().setError(status.isError());
  420. }
  421. ConfigMgrSession *Cws_config2Ex::getConfigSession(const std::string &sessionId)
  422. {
  423. ConfigMgrSession *pSession = nullptr;
  424. if (sessionId.empty())
  425. throw MakeStringException(CFGMGR_ERROR_MISSING_SESSION_ID, "Session ID required");
  426. auto it = m_sessions.find(sessionId);
  427. if (it != m_sessions.end())
  428. {
  429. pSession = (it->second);
  430. }
  431. if (pSession == nullptr)
  432. throw MakeStringException(CFGMGR_ERROR_INVALID_SESSION_ID, "Session ID not valid");
  433. return pSession;
  434. }
  435. ConfigMgrSession *Cws_config2Ex::getConfigSessionForUpdate(const std::string &sessionId, const std::string &lockKey)
  436. {
  437. ConfigMgrSession *pSession = getConfigSession(sessionId);
  438. if (!pSession->doesKeyFit(lockKey))
  439. {
  440. throw MakeStringException(CFGMGR_ERROR_LOCK_KEY_INVALID, "Session lock key is missing or invalid");
  441. }
  442. return pSession;
  443. }
  444. bool Cws_config2Ex::deleteConfigSession(const std::string &sessionId)
  445. {
  446. bool rc = false;
  447. ConfigMgrSession *pSession = getConfigSession(sessionId);
  448. if (pSession)
  449. {
  450. m_sessions.erase(sessionId);
  451. delete pSession;
  452. rc = true;
  453. }
  454. return rc;
  455. }
  456. void Cws_config2Ex::getNodeResponse(const std::shared_ptr<EnvironmentNode> &pNode, IEspGetNodeResponse &resp) const
  457. {
  458. const std::shared_ptr<SchemaItem> &pNodeSchemaItem = pNode->getSchemaItem();
  459. std::string nodeDisplayName;
  460. resp.setNodeId(pNode->getId().c_str());
  461. //
  462. // Fill in base node info struct
  463. getNodeInfo(pNode, resp.updateNodeInfo());
  464. //
  465. // Handle the attributes
  466. IArrayOf<IEspAttributeType> nodeAttributes;
  467. if (pNode->hasAttributes())
  468. {
  469. std::vector<std::shared_ptr<EnvironmentValue>> attributes;
  470. pNode->getAttributes(attributes);
  471. getAttributes(attributes, nodeAttributes);
  472. }
  473. resp.setAttributes(nodeAttributes);
  474. //
  475. // Now the children
  476. IArrayOf<IEspNodeType> childNodes;
  477. if (pNode->hasChildren())
  478. {
  479. std::vector<std::shared_ptr<EnvironmentNode>> children;
  480. pNode->getChildren(children);
  481. for (auto it=children.begin(); it!=children.end(); ++it)
  482. {
  483. std::shared_ptr<EnvironmentNode> pChildEnvNode = *it;
  484. const std::shared_ptr<SchemaItem> pSchemaItem = pChildEnvNode->getSchemaItem();
  485. Owned<IEspNodeType> pChildNode = createNodeType();
  486. getNodeInfo(pChildEnvNode, pChildNode->updateNodeInfo());
  487. pChildNode->setNodeId(pChildEnvNode->getId().c_str());
  488. pChildNode->setNumChildren(pChildEnvNode->getNumChildren());
  489. childNodes.append(*pChildNode.getLink());
  490. }
  491. }
  492. resp.setChildren(childNodes);
  493. //
  494. // Build a list of items that can be inserted under this node
  495. IArrayOf<IEspNodeInfoType> newNodes;
  496. std::vector<std::shared_ptr<SchemaItem>> insertableList;
  497. pNode->getInsertableItems(insertableList);
  498. for (auto it=insertableList.begin(); it!=insertableList.end(); ++it)
  499. {
  500. std::shared_ptr<SchemaItem> pSchemaItem = *it;
  501. Owned<IEspNodeInfoType> pNodeInfo = createNodeInfoType();
  502. getNodeInfo(pSchemaItem, *pNodeInfo);
  503. pNodeInfo->setRequired(pSchemaItem->isRequired()); // only filled in for insertable items
  504. newNodes.append(*pNodeInfo.getLink());
  505. }
  506. resp.setInsertable(newNodes);
  507. if (pNodeSchemaItem->isItemValueDefined())
  508. {
  509. resp.setLocalValueDefined(true);
  510. const std::shared_ptr<SchemaValue> &pNodeSchemaValue = pNodeSchemaItem->getItemSchemaValue();
  511. const std::shared_ptr<SchemaType> &pType = pNodeSchemaValue->getType();
  512. resp.updateValue().updateType().setName(pType->getName().c_str());
  513. if (pType->getLimits()->isMaxSet())
  514. {
  515. resp.updateValue().updateType().updateLimits().setMaxValid(true);
  516. resp.updateValue().updateType().updateLimits().setMax(pType->getLimits()->getMax());
  517. }
  518. if (pType->getLimits()->isMinSet())
  519. {
  520. resp.updateValue().updateType().updateLimits().setMinValid(true);
  521. resp.updateValue().updateType().updateLimits().setMin(pType->getLimits()->getMin());
  522. }
  523. if (pNode->isLocalValueSet())
  524. {
  525. const std::shared_ptr<EnvironmentValue> &pLocalValue = pNode->getLocalEnvValue();
  526. resp.updateValue().setCurrentValue(pLocalValue->getValue().c_str());
  527. //
  528. // Type information
  529. const std::shared_ptr<SchemaValue> pLocalSchemaValue = pLocalValue->getSchemaValue();
  530. const std::shared_ptr<SchemaType> &pLocalType = pLocalSchemaValue->getType();
  531. std::shared_ptr<SchemaTypeLimits> &pLimits = pLocalType->getLimits();
  532. resp.updateValue().updateType().setName(pLocalType->getName().c_str());
  533. if (pLocalType->getLimits()->isMaxSet())
  534. {
  535. resp.updateValue().updateType().updateLimits().setMaxValid(true);
  536. resp.updateValue().updateType().updateLimits().setMax(pLocalType->getLimits()->getMax());
  537. }
  538. if (pLocalType->getLimits()->isMinSet())
  539. {
  540. resp.updateValue().updateType().updateLimits().setMinValid(true);
  541. resp.updateValue().updateType().updateLimits().setMin(pLocalType->getLimits()->getMin());
  542. }
  543. resp.updateValue().setRequired(pLocalSchemaValue->isRequired());
  544. resp.updateValue().setReadOnly(pLocalSchemaValue->isReadOnly());
  545. resp.updateValue().setHidden(pLocalSchemaValue->isHidden());
  546. }
  547. }
  548. }
  549. void Cws_config2Ex::getNodeInfo(const std::shared_ptr<EnvironmentNode> &pNode, IEspNodeInfoType &nodeInfo) const
  550. {
  551. const std::shared_ptr<SchemaItem> &pNodeSchemaItem = pNode->getSchemaItem();
  552. std::string nodeDisplayName;
  553. //
  554. // Fill in base node info struct
  555. getNodeInfo(pNodeSchemaItem, nodeInfo); // fill it in based on schema
  556. getNodeDisplayName(pNode, nodeDisplayName); // possibly override the displayname
  557. nodeInfo.setName(nodeDisplayName.c_str());
  558. }
  559. void Cws_config2Ex::getNodeInfo(const std::shared_ptr<SchemaItem> &pNodeSchemaItem, IEspNodeInfoType &nodeInfo) const
  560. {
  561. //
  562. // Fill in base node info struct
  563. nodeInfo.setName(pNodeSchemaItem->getProperty("displayName").c_str());
  564. nodeInfo.setNodeType(pNodeSchemaItem->getItemType().c_str());
  565. nodeInfo.setClass(pNodeSchemaItem->getProperty("className").c_str());
  566. nodeInfo.setCategory(pNodeSchemaItem->getProperty("category").c_str());
  567. nodeInfo.setTooltip(pNodeSchemaItem->getProperty("tooltip").c_str());
  568. nodeInfo.setHidden(pNodeSchemaItem->isHidden());
  569. }
  570. void Cws_config2Ex::getAttributes(const std::vector<std::shared_ptr<EnvironmentValue>> &attributes, IArrayOf<IEspAttributeType> &nodeAttributes) const
  571. {
  572. for (auto it=attributes.begin(); it!=attributes.end(); ++it)
  573. {
  574. std::shared_ptr<EnvironmentValue> pAttr = *it;
  575. Owned<IEspAttributeType> pAttribute = createAttributeType();
  576. const std::shared_ptr<SchemaValue> &pSchemaValue = pAttr->getSchemaValue();
  577. std::string attributeName = pAttr->getName();
  578. pAttribute->setName(attributeName.c_str());
  579. pAttribute->setDisplayName(pSchemaValue->getDisplayName().c_str());
  580. pAttribute->setTooltip(pSchemaValue->getTooltip().c_str());
  581. const std::shared_ptr<SchemaType> &pType = pSchemaValue->getType();
  582. std::shared_ptr<SchemaTypeLimits> &pLimits = pType->getLimits();
  583. pAttribute->updateType().setName(pType->getName().c_str());
  584. if (pType->getLimits()->isMaxSet())
  585. {
  586. pAttribute->updateType().updateLimits().setMaxValid(true);
  587. pAttribute->updateType().updateLimits().setMax(pType->getLimits()->getMax());
  588. }
  589. if (pType->getLimits()->isMinSet())
  590. {
  591. pAttribute->updateType().updateLimits().setMinValid(true);
  592. pAttribute->updateType().updateLimits().setMin(pType->getLimits()->getMin());
  593. }
  594. pAttribute->setRequired(pSchemaValue->isRequired());
  595. pAttribute->setReadOnly(pSchemaValue->isReadOnly());
  596. pAttribute->setHidden(pSchemaValue->isHidden());
  597. std::vector<AllowedValue> allowedValues;
  598. pSchemaValue->getAllowedValues(allowedValues, pAttr.get());
  599. if (!allowedValues.empty())
  600. {
  601. IArrayOf<IEspChoiceType> choices;
  602. for (auto valueIt=allowedValues.begin(); valueIt!=allowedValues.end(); ++valueIt)
  603. {
  604. Owned<IEspChoiceType> pChoice = createChoiceType();
  605. pChoice->setDisplayName((*valueIt).m_displayName.c_str());
  606. pChoice->setValue((*valueIt).m_value.c_str());
  607. pChoice->setDesc((*valueIt).m_description.c_str());
  608. choices.append(*pChoice.getLink());
  609. }
  610. pAttribute->updateType().updateLimits().setChoiceList(choices);
  611. }
  612. pAttribute->setCurrentValue(pAttr->getValue().c_str());
  613. pAttribute->setDefaultValue(pSchemaValue->getDefaultValue().c_str());
  614. nodeAttributes.append(*pAttribute.getLink());
  615. }
  616. }
  617. void Cws_config2Ex::getNodeDisplayName(const std::shared_ptr<EnvironmentNode> &pNode, std::string &nodeDisplayName) const
  618. {
  619. const std::shared_ptr<SchemaItem> &pNodeSchemaItem = pNode->getSchemaItem();
  620. nodeDisplayName = pNodeSchemaItem->getProperty("displayName");
  621. if (pNode->hasAttributes())
  622. {
  623. std::shared_ptr<EnvironmentValue> pAttr = pNode->getAttribute("name");
  624. if (pAttr && pAttr->isValueSet())
  625. {
  626. nodeDisplayName = pAttr->getValue(); // better usability value
  627. }
  628. }
  629. }
  630. void Cws_config2Ex::getNodeParents(const std::string &nodeId, ConfigMgrSession *pSession, StringArray &parentNodeIds) const
  631. {
  632. std::shared_ptr<EnvironmentNode> pNode = pSession->m_pEnvMgr->getEnvironmentNode(nodeId);
  633. if (pNode)
  634. {
  635. while (pNode)
  636. {
  637. pNode = pNode->getParent();
  638. if (pNode)
  639. {
  640. parentNodeIds.append(pNode->getId().c_str());
  641. }
  642. }
  643. }
  644. }
  645. void Cws_config2Ex::getNodeTree(const std::shared_ptr<EnvironmentNode> &pNode, IEspTreeElementType &treeElement, int levels, bool includeAttributes) const
  646. {
  647. //
  648. // Fill in this element
  649. treeElement.setNodeId(pNode->getId().c_str());
  650. getNodeInfo(pNode, treeElement.updateNodeInfo());
  651. if (includeAttributes && pNode->hasAttributes())
  652. {
  653. IArrayOf<IEspAttributeType> nodeAttributes;
  654. std::vector<std::shared_ptr<EnvironmentValue>> attributes;
  655. pNode->getAttributes(attributes);
  656. getAttributes(attributes, nodeAttributes);
  657. treeElement.setAttributes(nodeAttributes);
  658. }
  659. //
  660. // If we need to descend more levels, do so
  661. if (levels > 0)
  662. {
  663. --levels;
  664. IArrayOf<IEspTreeElementType> childNodes;
  665. if (pNode->hasChildren())
  666. {
  667. std::vector<std::shared_ptr<EnvironmentNode>> children;
  668. pNode->getChildren(children);
  669. for (auto it=children.begin(); it!=children.end(); ++it)
  670. {
  671. Owned<IEspTreeElementType> pTreeElement = createTreeElementType();
  672. getNodeTree(*it, *pTreeElement, levels, includeAttributes);
  673. childNodes.append(*pTreeElement.getLink());
  674. }
  675. }
  676. treeElement.setChildren(childNodes);
  677. }
  678. }