]> SALOME platform Git repositories - tools/libbatch.git/blob - src/Core/CommandsOverloader.cxx
Salome HOME
56e00ddfb7853f33143e5892eae9588dc696db62
[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
47   static set<string> supportedCmds({"RM", "SH", "CP", "MKDIR", "RSH", "RCP", "SSH", "SCP", "RSYNC"});
48
49   /*!
50    * Constructor.
51    */
52   CommandsOverloader::CommandsOverloader()
53   {
54     if (!isCmdFileDefined() && isCheckCmdsDefined())
55     {
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   {
74     static CommandsOverloader instance;
75     return instance;
76   }
77
78   /*!
79    * Return an overridden definition of RM command.
80    */
81   string CommandsOverloader::RM_Command()
82   {
83     string cmd = CMD_Command("RM");
84     if (!cmd.empty())
85     {
86       return cmd;
87     }
88
89 #ifdef RM_COMMAND
90     return RM_COMMAND;
91 #else
92     throw RunTimeException("Can't use SH protocol (RM command was "
93                            "not found neither in the file pointed by "
94                            "LIBBATCH_OVERRIDE_CMDS environment variable "
95                            "nor on the system at compile time).");
96 #endif
97   }
98
99   /*!
100    * Return an overridden definition of SH command.
101    */
102   string CommandsOverloader::SH_Command()
103   {
104     string cmd = CMD_Command("SH");
105     if (!cmd.empty())
106     {
107       return cmd;
108     }
109
110 #ifdef SH_COMMAND
111     return SH_COMMAND;
112 #else
113     throw RunTimeException("Can't use SH protocol (SH command was "
114                            "not found neither in the file pointed by "
115                            "LIBBATCH_OVERRIDE_CMDS environment variable "
116                            "nor on the system at compile time).");
117 #endif
118   }
119
120   /*!
121    * Return an overridden definition of CP command.
122    */
123   string CommandsOverloader::CP_Command()
124   {
125     string cmd = CMD_Command("CP");
126     if (!cmd.empty())
127     {
128       return cmd;
129     }
130
131 #ifdef CP_COMMAND
132     return CP_COMMAND;
133 #else
134     throw RunTimeException("Can't use SH protocol (CP command was "
135                            "not found neither in the file pointed by "
136                            "LIBBATCH_OVERRIDE_CMDS environment variable "
137                            "nor on the system at compile time).");
138 #endif
139   }
140
141   /*!
142    * Return an overridden definition of MKDIR command.
143    */
144   string CommandsOverloader::MKDIR_Command()
145   {
146     string cmd = CMD_Command("MKDIR");
147     if (!cmd.empty())
148     {
149       return cmd;
150     }
151
152 #ifdef MKDIR_COMMAND
153     return MKDIR_COMMAND;
154 #else
155     throw RunTimeException("Can't use SH protocol (MKDIR command was "
156                            "not found neither in the file pointed by "
157                            "LIBBATCH_OVERRIDE_CMDS environment variable "
158                            "nor on the system at compile time).");
159 #endif
160   }
161
162   /*!
163    * Return an overridden definition of RSH command.
164    */
165   string CommandsOverloader::RSH_Command()
166   {
167     string cmd = CMD_Command("RSH");
168     if (!cmd.empty())
169     {
170       return cmd;
171     }
172
173 #ifdef RSH_COMMAND
174     return RSH_COMMAND;
175 #else
176     throw RunTimeException("Can't use RSH protocol (RSH command was "
177                            "not found neither in the file pointed by "
178                            "LIBBATCH_OVERRIDE_CMDS environment variable "
179                            "nor on the system at compile time).");
180 #endif
181   }
182
183   /*!
184    * Return an overridden definition of RCP command.
185    */
186   string CommandsOverloader::RCP_Command()
187   {
188     string cmd = CMD_Command("RCP");
189     if (!cmd.empty())
190     {
191       return cmd;
192     }
193
194 #ifdef RCP_COMMAND
195     return RCP_COMMAND;
196 #else
197     throw RunTimeException("Can't use RSH protocol (RCP command was "
198                            "not found neither in the file pointed by "
199                            "LIBBATCH_OVERRIDE_CMDS environment variable "
200                            "nor on the system at compile time).");
201 #endif
202   }
203
204   /*!
205    * Return an overridden definition of SSH command.
206    */
207   string CommandsOverloader::SSH_Command()
208   {
209     string cmd = CMD_Command("SSH");
210     if (!cmd.empty())
211     {
212       return cmd;
213     }
214
215 #ifdef SSH_COMMAND
216     return SSH_COMMAND;
217 #else
218     throw RunTimeException("Can't use SSH protocol (SSH command was "
219                            "not found neither in the file pointed by "
220                            "LIBBATCH_OVERRIDE_CMDS environment variable "
221                            "nor on the system at compile time).");
222 #endif
223   }
224
225   /*!
226    * Return an overridden definition of SCP command.
227    */
228   string CommandsOverloader::SCP_Command()
229   {
230     string cmd = CMD_Command("SCP");
231     if (!cmd.empty())
232     {
233       return cmd;
234     }
235
236 #ifdef SCP_COMMAND
237     return SCP_COMMAND;
238 #else
239     throw RunTimeException("Can't use SSH protocol (SCP command was "
240                            "not found neither in the file pointed by "
241                            "LIBBATCH_OVERRIDE_CMDS environment variable "
242                            "nor on the system at compile time).");
243 #endif
244   }
245
246   /*!
247    * Return an overridden definition of RSYNC command.
248    */
249   string CommandsOverloader::RSYNC_Command()
250   {
251     string cmd = CMD_Command("RSYNC");
252     if (!cmd.empty())
253     {
254       return cmd;
255     }
256
257 #ifdef RSYNC_COMMAND
258     return RSYNC_COMMAND;
259 #else
260     throw RunTimeException("Can't use RSYNC protocol (RSYNC command was "
261                            "not found neither in the file pointed by "
262                            "LIBBATCH_OVERRIDE_CMDS environment variable "
263                            "nor on the system at compile time).");
264 #endif
265   }
266
267   /*!
268    * Parse text file with the given file name and fill in the map of 
269    * <CMD> - <associated command desired by the user at runtime>.
270    * \param theFilename the name of text file to be parsed
271    */
272   void CommandsOverloader::parse(const std::string & theFilename)
273   {
274     ifstream fileStream(theFilename.c_str());
275     if (!fileStream)
276     {
277       stringstream errMsg;
278       errMsg << "Can't open file with overridden commands definitions " << theFilename;
279       throw RunTimeException(errMsg.str());
280     }
281     string line;
282     bool empty = true;
283     int lineNumber = 1;
284     while (getline(fileStream, line))
285     {
286       string str = line;
287       if (!str.empty())
288       {
289         empty = false;
290         // Find ' ' symbol and split the line
291         size_t pos = str.find_first_of(' ');
292         if (pos == string::npos)
293         {
294           stringstream errMsg;
295           errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
296                  << ": Syntax error (missing ' ' character between key and value): " << line;
297           throw RunTimeException(errMsg.str());
298         } else
299         {
300           string key = str.substr(0, pos);
301           string value = str.substr(pos+1);
302
303           // Check non-completeness of the file.
304           string trimmedKey = trim(key);
305           string trimmedValue = trim(value);
306           if (trimmedKey.empty() || trimmedValue.empty())
307           {
308             stringstream errMsg;
309             errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
310                    << ": The non-completeness of the file: " << line;
311             throw RunTimeException(errMsg.str());
312           }
313
314           // Check the presence of an unsupported command.
315           if (supportedCmds.find(trimmedKey) == supportedCmds.end())
316           {
317             stringstream errMsg;
318             errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
319                    << ": The presence of an unsupported command: " << trimmedKey;
320             throw RunTimeException(errMsg.str());
321           }
322
323           if (!hasKey(trimmedKey))
324           {
325             _cmdmap[trimmedKey] = trimmedValue;
326           }
327           else
328           {
329             // Redifinition of already overloaded command is found.
330             stringstream errMsg;
331             errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
332                    <<": A repetition of the " << trimmedKey << " key in several lines.";
333             throw RunTimeException(errMsg.str());
334           }
335         }
336       }
337       ++lineNumber;
338     }
339     if (empty)
340     {
341       stringstream errMsg;
342       errMsg << "Wrong format of " << theFilename << " file: Empty file.";
343       throw RunTimeException(errMsg.str());
344     }
345     fileStream.close();
346   }
347
348   /*!
349    * Strip leading and trailing spaces in the given string.
350    * \param theStr string to be stripped
351    * \return stripped string
352    */
353   string CommandsOverloader::trim(const std::string & theStr) const noexcept
354   {
355     size_t beg = theStr.find_first_not_of(" \t");
356     if (beg == string::npos) beg = 0;
357     size_t end = theStr.find_last_not_of(" \t");
358     return theStr.substr(beg, end-beg+1);
359   }
360
361   /*!
362    * Return name of file with overloaded commands defined by
363    * LIBBATCH_OVERRIDE_CMDS environment variable.
364    * \return the name of file with overloaded commands
365    */
366   string CommandsOverloader::getCmdFileName() const
367   {
368     auto parseCmdFileName = []() -> std::string
369     {
370       const char* cmdFileName = getenv("LIBBATCH_OVERRIDE_CMDS");
371       if (cmdFileName != NULL && !string(cmdFileName).empty())
372       {
373         return cmdFileName;
374       }
375       return {};
376     };
377     
378     static const string cmdFileName = parseCmdFileName();
379     return cmdFileName;
380   }
381   
382   /*!
383    * Check, if file with overloaded commands is defined by
384    * LIBBATCH_OVERRIDE_CMDS environment variable.
385    * \return true, if file is defined; false - otherwise
386    */
387   bool CommandsOverloader::isCmdFileDefined() const
388   {
389     static const bool isFileDefined = !getCmdFileName().empty();
390     return isFileDefined;
391   }
392
393   /*!
394    * Check, if it is needed to show information about overloaded or not
395    * commands are used. It can be switched ON via the environment
396    * variable LIBBATCH_CHECK_CMDS=1.
397    * \return true, if it is needed to show information; false - otherwise
398    */
399   bool CommandsOverloader::isCheckCmdsDefined() const
400   {
401     char * check_cmds_env = getenv("LIBBATCH_CHECK_CMDS");
402     if (check_cmds_env && atoi(check_cmds_env) == 1)
403       return true;
404     return false;
405   }
406
407   /*!
408    * Return an overridden definition of the given command.
409    * \param theKey command name
410    * \return overridden definition of the given command
411    */
412   string CommandsOverloader::CMD_Command(const std::string & theKey)
413   {
414     if (_cmdmap.empty())
415     {
416       if (isCmdFileDefined())
417       {
418         // Environment variable LIBBATCH_OVERRIDE_CMDS is defined.
419         // Parse text file pointed by LIBBATCH_OVERRIDE_CMDS environment variable.
420         parse(getCmdFileName());
421         // Note: If environment variable LIBBATCH_OVERRIDE_CMDS is not defined,
422         // use command configuration established at compile time.
423         
424         // Showing information about overloaded or not commands are used is disabled by default.
425         // It can be switched ON via the environment variable: LIBBATCH_CHECK_CMDS=1
426         if (isCheckCmdsDefined())
427         {
428           cout << "================================================================" << endl;
429           if (_cmdmap.empty())
430           {
431             cout << "Commands found on the system at compile time are used." << endl;
432           } else if (_cmdmap.size() == supportedCmds.size())
433           {
434             cout << "Overloaded commands are used." << endl;
435           } else
436           {
437             cout << "Command(s)" << endl;
438             map<string,string>::const_iterator iter;
439             for (iter = _cmdmap.begin() ; iter != _cmdmap.end() ; ++iter)
440             {
441               cout << "\t" << iter->first << endl;
442             }
443             cout << "is(are) overloaded." << endl;
444             cout << "The rest command(s) is(are) found on the system at compile time." << endl;
445           }
446           cout << "================================================================" << endl;
447         }
448       }
449     }
450
451     return hasKey(theKey) ? _cmdmap[theKey] : string();
452   }
453
454   /*!
455    * Check, if commands map contains the given command key.
456    * \param theKey command name
457    * \return true, if command key exists in the map
458    */
459   bool CommandsOverloader::hasKey(const string & theKey) const
460   {
461     return (_cmdmap.find(theKey) != _cmdmap.end());
462   }
463
464 }