]> SALOME platform Git repositories - tools/libbatch.git/blob - src/Core/CommandsOverloader.cxx
Salome HOME
06f70576d1165628db2f615090bcdfd73fff5573
[tools/libbatch.git] / src / Core / CommandsOverloader.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 /*
23  * CommandsOverloader.cxx :
24  *
25  * Author : Margarita KARPUNINA - OCC
26  * Date   : October 2022
27  *
28  */
29
30 #include <fstream>
31 #include <set>
32 #include <sstream>
33 #include <iostream>
34
35 #include <libbatch_config.h>
36
37 #include "CommandsOverloader.hxx"
38
39 #include "RunTimeException.hxx"
40
41 using namespace std;
42
43
44 namespace Batch {
45
46   static set<string> supportedCmds({"RM", "SH", "CP", "MKDIR", "RSH", "RCP", "SSH", "SCP", "RSYNC"});
47
48   /*!
49    * Constructor.
50    */
51   CommandsOverloader::CommandsOverloader()
52   {
53     bool isFileDefined;
54     isCmdFileDefined(isFileDefined);
55     if (!isFileDefined && isCheckCmdsDefined()) {
56       cout << "================================================================" << endl;
57       cout << "Commands found on the system at compile time are used." << endl;
58       cout << "================================================================" << endl;
59     }
60   }
61
62   /*!
63    * Destructor.
64    */
65   CommandsOverloader::~CommandsOverloader()
66   {
67   }
68
69   /*!
70    * Return the CommandsOverloader singleton.
71    */
72   CommandsOverloader& CommandsOverloader::getInstance () {
73     static CommandsOverloader instance;
74     return instance;
75   }
76
77   /*!
78    * Return an overridden definition of RM command.
79    */
80   string CommandsOverloader::RM_Command() {
81     string cmd = CMD_Command("RM");
82     if (cmd.empty()) {
83 #ifdef RM_COMMAND
84       return RM_COMMAND;
85 #else
86       throw RunTimeException("Can't use SH protocol (RM command was "
87                              "not found neither in the file pointed by "
88                              "LIBBATCH_OVERRIDE_CMDS environment variable "
89                              "nor on the system at compile time).");
90 #endif
91     } else {
92       return cmd;
93     }
94   }
95
96   /*!
97    * Return an overridden definition of SH command.
98    */
99   string CommandsOverloader::SH_Command() {
100     string cmd = CMD_Command("SH");
101     if (cmd.empty()) {
102 #ifdef SH_COMMAND
103       return SH_COMMAND;
104 #else
105       throw RunTimeException("Can't use SH protocol (SH command was "
106                              "not found neither in the file pointed by "
107                              "LIBBATCH_OVERRIDE_CMDS environment variable "
108                              "nor on the system at compile time).");
109 #endif
110     } else {
111       return cmd;
112     }
113   }
114
115   /*!
116    * Return an overridden definition of CP command.
117    */
118   string CommandsOverloader::CP_Command() {
119     string cmd = CMD_Command("CP");
120     if (cmd.empty()) {
121 #ifdef CP_COMMAND
122       return CP_COMMAND;
123 #else
124       throw RunTimeException("Can't use SH protocol (CP command was "
125                              "not found neither in the file pointed by "
126                              "LIBBATCH_OVERRIDE_CMDS environment variable "
127                              "nor on the system at compile time).");
128 #endif
129     } else {
130       return cmd;
131     }
132   }
133
134   /*!
135    * Return an overridden definition of MKDIR command.
136    */
137   string CommandsOverloader::MKDIR_Command() {
138     string cmd = CMD_Command("MKDIR");
139     if (cmd.empty()) {
140 #ifdef MKDIR_COMMAND
141       return MKDIR_COMMAND;
142 #else
143       throw RunTimeException("Can't use SH protocol (MKDIR command was "
144                              "not found neither in the file pointed by "
145                              "LIBBATCH_OVERRIDE_CMDS environment variable "
146                              "nor on the system at compile time).");
147 #endif
148     } else {
149       return cmd;
150     }
151   }
152
153   /*!
154    * Return an overridden definition of RSH command.
155    */
156   string CommandsOverloader::RSH_Command() {
157     string cmd = CMD_Command("RSH");
158     if (cmd.empty()) {
159 #ifdef RSH_COMMAND
160       return RSH_COMMAND;
161 #else
162       throw RunTimeException("Can't use RSH protocol (RSH command was "
163                              "not found neither in the file pointed by "
164                              "LIBBATCH_OVERRIDE_CMDS environment variable "
165                              "nor on the system at compile time).");
166 #endif
167     } else {
168       return cmd;
169     }
170   }
171
172   /*!
173    * Return an overridden definition of RCP command.
174    */
175   string CommandsOverloader::RCP_Command() {
176     string cmd = CMD_Command("RCP");
177     if (cmd.empty()) {
178 #ifdef RCP_COMMAND
179       return RCP_COMMAND;
180 #else
181       throw RunTimeException("Can't use RSH protocol (RCP command was "
182                              "not found neither in the file pointed by "
183                              "LIBBATCH_OVERRIDE_CMDS environment variable "
184                              "nor on the system at compile time).");
185 #endif
186     } else {
187       return cmd;
188     }
189   }
190
191   /*!
192    * Return an overridden definition of SSH command.
193    */
194   string CommandsOverloader::SSH_Command() {
195     string cmd = CMD_Command("SSH");
196     if (cmd.empty()) {
197 #ifdef SSH_COMMAND
198       return SSH_COMMAND;
199 #else
200       throw RunTimeException("Can't use SSH protocol (SSH command was "
201                              "not found neither in the file pointed by "
202                              "LIBBATCH_OVERRIDE_CMDS environment variable "
203                              "nor on the system at compile time).");
204 #endif
205     } else {
206       return cmd;
207     }
208   }
209
210   /*!
211    * Return an overridden definition of SCP command.
212    */
213   string CommandsOverloader::SCP_Command() {
214     string cmd = CMD_Command("SCP");
215     if (cmd.empty()) {
216 #ifdef SCP_COMMAND
217       return SCP_COMMAND;
218 #else
219       throw RunTimeException("Can't use SSH protocol (SCP command was "
220                              "not found neither in the file pointed by "
221                              "LIBBATCH_OVERRIDE_CMDS environment variable "
222                              "nor on the system at compile time).");
223 #endif
224     } else {
225       return cmd;
226     }
227   }
228
229   /*!
230    * Return an overridden definition of RSYNC command.
231    */
232   string CommandsOverloader::RSYNC_Command() {
233     string cmd = CMD_Command("RSYNC");
234     if (cmd.empty()) {
235 #ifdef RSYNC_COMMAND
236       return RSYNC_COMMAND;
237 #else
238       throw RunTimeException("Can't use RSYNC protocol (RSYNC command was "
239                              "not found neither in the file pointed by "
240                              "LIBBATCH_OVERRIDE_CMDS environment variable "
241                              "nor on the system at compile time).");
242 #endif
243     } else {
244       return cmd;
245     }
246   }
247
248   /*!
249    * Parse text file with the given file name and fill in the map of 
250    * <CMD> - <associated command desired by the user at runtime>.
251    * \param theFilename the name of text file to be parsed
252    */
253   void CommandsOverloader::parse(const std::string & theFilename) {
254     ifstream fileStream(theFilename.c_str());
255     if (!fileStream) {
256       stringstream errMsg;
257       errMsg << "Can't open file with overridden commands definitions " << theFilename;
258       throw RunTimeException(errMsg.str());
259     }
260     string line;
261     bool empty = true;
262     int lineNumber = 1;
263     while (getline(fileStream, line)) {
264       string str = line;
265       if (!str.empty()) {
266         empty = false;
267         // Find ' ' symbol and split the line
268         size_t pos = str.find_first_of(' ');
269         if (pos == string::npos) {
270           stringstream errMsg;
271           errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
272                  << ": Syntax error (missing ' ' character between key and value): " << line;
273           throw RunTimeException(errMsg.str());
274         } else {
275           string key = str.substr(0, pos);
276           string value = str.substr(pos+1);
277
278           // Check non-completeness of the file.
279           string trimmedKey = trim(key);
280           string trimmedValue = trim(value);
281           if (trimmedKey.empty() || trimmedValue.empty()) {
282             stringstream errMsg;
283             errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
284                    << ": The non-completeness of the file: " << line;
285             throw RunTimeException(errMsg.str());
286           }
287
288           // Check the presence of an unsupported command.
289           if (supportedCmds.find(trimmedKey) == supportedCmds.end()) {
290             stringstream errMsg;
291             errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
292                    << ": The presence of an unsupported command: " << trimmedKey;
293             throw RunTimeException(errMsg.str());
294           }
295
296           if (!hasKey(trimmedKey)) {
297             _cmdmap[trimmedKey] = trimmedValue;
298           }
299           else {
300             // Redifinition of already overloaded command is found.
301             stringstream errMsg;
302             errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
303                    <<": A repetition of the " << trimmedKey << " key in several lines.";
304             throw RunTimeException(errMsg.str());
305           }
306         }
307       }
308       ++lineNumber;
309     }
310     if (empty) {
311       stringstream errMsg;
312       errMsg << "Wrong format of " << theFilename << " file: Empty file.";
313       throw RunTimeException(errMsg.str());
314     }
315     fileStream.close();
316   }
317
318   /*!
319    * Strip leading and trailing spaces in the given string.
320    * \param theStr string to be stripped
321    * \return stripped string
322    */
323   std::string CommandsOverloader::trim(const std::string & theStr) const noexcept
324   {
325     size_t beg = theStr.find_first_not_of(" \t");
326     if (beg == string::npos) beg = 0;
327     size_t end = theStr.find_last_not_of(" \t");
328     return theStr.substr(beg, end-beg+1);
329   }
330
331   /*!
332    * Check, if file with overloaded commands is defined by
333    * LIBBATCH_OVERRIDE_CMDS environment variable.
334    * \param theIsDefined in/out parameter; true, if file is defined; false - otherwise
335    * \return the name of file with overloaded commands
336    */
337   const char * CommandsOverloader::isCmdFileDefined(bool & theIsDefined) const
338   {
339     const char * filename = getenv("LIBBATCH_OVERRIDE_CMDS");
340     theIsDefined = (filename != NULL && !string(filename).empty());
341     return filename;
342   }
343
344   /*!
345    * Check, if it is needed to show information about overloaded or not
346    * commands are used. It can be switched ON via the environment
347    * variable LIBBATCH_CHECK_CMDS=1.
348    * \return true, if it is needed to show information; false - otherwise
349    */
350   bool CommandsOverloader::isCheckCmdsDefined() const
351   {
352     char * check_cmds_env = getenv("LIBBATCH_CHECK_CMDS");
353     if (check_cmds_env && atoi(check_cmds_env) == 1)
354       return true;
355     return false;
356   }
357
358   /*!
359    * Return an overridden definition of the given command.
360    * \param theKey command name
361    * \return overridden definition of the given command
362    */
363   string CommandsOverloader::CMD_Command(const std::string & theKey) {
364     if (_cmdmap.empty()) {
365       bool isFileDefined;
366       const char * filename = isCmdFileDefined(isFileDefined);
367       if (isFileDefined) {
368         // Environment variable LIBBATCH_OVERRIDE_CMDS is defined.
369         // Parse text file pointed by LIBBATCH_OVERRIDE_CMDS environment variable.
370         parse(filename);
371         // Note: If environment variable LIBBATCH_OVERRIDE_CMDS is not defined,
372         // use command configuration established at compile time.
373         
374         // Showing information about overloaded or not commands are used is disabled by default.
375         // It can be switched ON via the environment variable: LIBBATCH_CHECK_CMDS=1
376         if (isCheckCmdsDefined()) {
377           cout << "================================================================" << endl;
378           if (_cmdmap.empty()) {
379             cout << "Commands found on the system at compile time are used." << endl;
380           } else if (_cmdmap.size() == supportedCmds.size()) {
381             cout << "Overloaded commands are used." << endl;
382           } else {
383             cout << "Command(s)" << endl;
384             map<string,string>::const_iterator iter;
385             for (iter = _cmdmap.begin() ; iter != _cmdmap.end() ; ++iter) {
386               cout << "\t" << iter->first << endl;
387             }
388             cout << "is(are) overloaded." << endl;
389             cout << "The rest command(s) is(are) found on the system at compile time." << endl;
390           }
391           cout << "================================================================" << endl;
392         }
393       }
394     }
395
396     return (hasKey(theKey) ? _cmdmap[theKey] : string());
397   }
398
399   /*!
400    * Check, if commands map contains the given command key.
401    * \param theKey command name
402    * \return true, if command key exists in the map
403    */
404   bool CommandsOverloader::hasKey(const string & theKey) const
405   {
406     return (_cmdmap.find(theKey) != _cmdmap.end());
407   }
408
409 }