1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 from __future__ import with_statement
27 __authors__ = [ "Marie-Francoise Incardona", "Olof Svensson", "Jerome Kieffer" ]
28 __contact__ = "svensson@esrf.fr"
29 __license__ = "LGPLv3+"
30 __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
31
32 import os, sys, time
33 from EDThreading import Semaphore
34 from EDCommandLine import EDCommandLine
35 from EDVerbose import EDVerbose
36 from EDConfigurationStatic import EDConfigurationStatic
37 from EDMessage import EDMessage
38 from EDUtilsPath import EDUtilsPath
39 from EDUtilsFile import EDUtilsFile
40 from EDFactoryPluginStatic import EDFactoryPluginStatic
44 """
45 This is the main EDNA application class. This class can be sub-classed for any specific application need.
46 An EDNA application is able to launch an entry point plugin. It accepts the following parameter:
47 --execute : name of the plugin to be executed
48 --inputFile : related plugin data (xml input data file name)
49 --outputFile : related plugin result (xml output data file name)
50 --conf : configuration file name
51 --basedir : where the application working directory should go
52 --DEBUG or --debug : turns on debugging
53 -v or --version : Displays the application name and version
54 --verbose : Turns on verbose mode
55 --no-log : Turns off logging
56 -h or --help : Prints out an usage message
57 """
58
59 CONFIGURATION_PARAM_LABEL = "--conf"
60 PLUGIN_PARAM_LABEL = "--execute"
61 DATASET_PARAM_LABEL = "--inputFile"
62 OUTPUT_PARAM_LABEL = "--outputFile"
63 DATASET_BASE_DIRECTORY = "--basedir"
64 DEBUG_PARAM_LABEL_1 = "--DEBUG"
65 DEBUG_PARAM_LABEL_2 = "--debug"
66 VERSION_PARAM_LABEL_1 = "-v"
67 VERSION_PARAM_LABEL_2 = "--version"
68 VERBOSE_MODE_LABEL = "--verbose"
69 NO_LOG_LABEL = "--no-log"
70 HELP_LABEL_1 = "-h"
71 HELP_LABEL_2 = "--help"
72
73 __edConfiguration = None
74 __edFactoryPlugin = None
75 __semaphore = Semaphore()
76
77
78 - def __init__(self, _strName="EDApplication", \
79 _strVersion="1.0.1", \
80 _strPluginName=None, \
81 _strConfigurationFileName=None, \
82 _strDataInputFilePath=None, \
83 _edLogFile=None, \
84 _strBaseDir=None, \
85 _strWorkingDir=None, \
86 _strDataOutputFilePath=None):
87 self.__strName = _strName
88 self.__strVersion = _strVersion
89 self.__strPluginName = _strPluginName
90 self.__strConfigurationFileName = _strConfigurationFileName
91 self.__strDataInputFilePath = _strDataInputFilePath
92 self.__strDataOutputFilePath = _strDataOutputFilePath
93 self.__edLogFile = _edLogFile
94 self.__strBaseDir = _strBaseDir
95 self.__strWorkingDir = _strWorkingDir
96 self.__strFullApplicationWorkingDirectory = None
97 self.__strXMLData = None
98 self.__listErrorMessages = []
99 self.__listWarningMessages = []
100 self.__xsDataOutput = None
101 self.__edObtainedOutputDataFile = None
102 self.__strDataOutputFilePath = None
103 self.__edPlugin = None
104 self.__edCommandLine = EDCommandLine(sys.argv)
105 self.__strApplicationInstanceName = self.__strName + "_" + time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))
106 self.__strLogFileName = self.__strApplicationInstanceName + ".log"
107 self.__bIsFailure = False
108 self.__strCurrentWorkingDirectory = os.getcwd()
109 self.__strConfigurationHome = None
110 self.__strPathToLogFile = None
111
112
114 """
115 This is the main execute method which executes preProcess, process and postProcess.
116 """
117 self.preProcess()
118 self.process()
119 self.postProcess()
120
121
123 """
124 Creates the application working directory (log dir)
125 Initializes the configuration
126 retrieves the plugin xml data to be passed to the plugin
127 """
128 EDVerbose.DEBUG("EDApplication.preProcess")
129 self.processCommandline()
130 if (not self.__bIsFailure):
131
132 strPluginLocation = EDFactoryPluginStatic.getFactoryPlugin().getModuleLocation(self.__strPluginName)
133 if (strPluginLocation is None):
134 EDVerbose.error("Plugin %s cannot be loaded!" % self.__strPluginName)
135 self.__bIsFailure = True
136
137 if (self.getDataInputFilePath() is not None) and (not os.path.exists(self.__strDataInputFilePath)):
138 EDVerbose.error("Input XML file not found : %s" % self.__strDataInputFilePath)
139 self.__bIsFailure = True
140
141 if (self.__strDataOutputFilePath is not None):
142 strOutputDirectory = os.path.dirname(self.__strDataOutputFilePath)
143 if (strOutputDirectory is None or strOutputDirectory == ""):
144 strOutputDirectory = os.getcwd()
145 self.__strDataOutputFilePath = os.path.join(strOutputDirectory, self.__strDataOutputFilePath)
146 if (not os.access(strOutputDirectory, os.W_OK)):
147 EDVerbose.error("Output directory not writable: %s" % strOutputDirectory)
148 self.__bIsFailure = True
149 elif (os.path.exists(self.__strDataOutputFilePath)):
150 if (not os.access(self.__strDataOutputFilePath, os.W_OK)):
151 EDVerbose.error("Output file not writable: %s" % self.__strDataOutputFilePath)
152 self.__bIsFailure = True
153 if (not self.__bIsFailure):
154 EDVerbose.DEBUG("EDApplication.PLUGIN_PARAM_LABEL: " + EDApplication.PLUGIN_PARAM_LABEL)
155
156 if self.__strConfigurationFileName is not None:
157
158 if (os.path.exists(self.__strConfigurationFileName)):
159 EDVerbose.screen("Loading Configuration file: %s" % self.__strConfigurationFileName)
160 EDConfigurationStatic.addConfigurationFile(self.__strConfigurationFileName, _bReplace=True)
161 else:
162 EDVerbose.warning("Cannot find configuration file: %s" % self.__strConfigurationFileName)
163 pyDictionary = {}
164 pyDictionary[ "${EDNA_HOME}" ] = EDUtilsPath.getEdnaHome()
165 if self.getDataInputFilePath() is not None:
166 self.__strXMLData = EDUtilsFile.readFileAndParseVariables(self.getDataInputFilePath(), pyDictionary)
167
168 if(self.__strWorkingDir is None):
169 self.__strWorkingDir = self.__strApplicationInstanceName
170 self.createApplicationWorkingDirectory()
171
172
191
192
193
194
233
234
235
251
252
260
261
269
270
271
282
283
294
295
305
306
317
318
319
320
321
322 - def postProcess(self):
323 """
324 """
325
326 os.chdir(self.__strCurrentWorkingDirectory)
327
328
329 @classmethod
361
362
363 @classmethod
367
368
369 @classmethod
373
374
375 @classmethod
379
380
383
384
386 """
387 Getter for base directory
388 @return: path of the base directory
389 @rtype: string
390 """
391 return self.__strBaseDir
392
393
395 """
396 Created the working directory of the application (<date>-<application name>)
397 First tries to retrieve the base dir from --basedir option or related parameter from constructor
398 Otherwise tries to retrieve it from EDNA_BASE_DIRECTORY environment variable
399 Otherwise put the base dir as the current directory
400 """
401 EDVerbose.DEBUG("EDApplication.createApplicationWorkingDirectory")
402 strBaseDirectory = self.getBaseDir()
403 strDateTime = time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))
404 self.__strFullApplicationWorkingDirectory = os.path.join(strBaseDirectory, self.__strWorkingDir)
405
406 if(os.path.exists(self.__strFullApplicationWorkingDirectory) or \
407 os.path.exists(self.__strFullApplicationWorkingDirectory)):
408
409 iIndex = 1
410 bContinueFlag = True
411 while (bContinueFlag):
412 self.__strFullApplicationWorkingDirectory = os.path.join(strBaseDirectory,
413 "%s_%d" % \
414 (strDateTime, \
415 iIndex))
416 if(os.path.isdir(self.__strFullApplicationWorkingDirectory) or \
417 os.path.exists(self.__strFullApplicationWorkingDirectory)):
418 iIndex += 1
419 else:
420 bContinueFlag = False
421
422 os.mkdir(self.__strFullApplicationWorkingDirectory)
423
424 os.chdir(self.__strFullApplicationWorkingDirectory)
425
426
428 return self.__strFullApplicationWorkingDirectory
429
431 return self.__strCurrentWorkingDirectory
432
433
435 """
436 """
437 EDVerbose.DEBUG("EDApplication.doSuccessActionPlugin")
438
439 self.__listWarningMessages = _edPlugin.getListOfWarningMessages()
440 EDVerbose.DEBUG("EDApplication.doSuccessActionPlugin: Plugin %s Successful with : %i Warnings " % (_edPlugin.getPluginName(), len(self.__listWarningMessages)))
441 for warningMessage in self.__listWarningMessages:
442 EDVerbose.screen(warningMessage)
443 self.__listErrorMessages = _edPlugin.getListOfErrorMessages()
444 EDVerbose.DEBUG("EDApplication.doSuccessActionPlugin: Plugin %s Successful with : %i Errors" % (_edPlugin.getPluginName(), len(self.__listErrorMessages)))
445 for errorMessage in self.__listErrorMessages:
446 EDVerbose.error(errorMessage)
447 if (_edPlugin.hasDataOutput()):
448 xsDataOutput = _edPlugin.getDataOutput()
449 if (xsDataOutput is not None and self.__strDataOutputFilePath is not None):
450 xsDataOutput.exportToFile(self.__strDataOutputFilePath)
451 if (xsDataOutput is not None and self.__edObtainedOutputDataFile is not None):
452 xsDataOutput.exportToFile(self.__edObtainedOutputDataFile)
453
454
456 EDVerbose.DEBUG("EDApplication.doFailureActionPlugin")
457
458
459 EDVerbose.DEBUG("EDApplication.doFailureActionPlugin: Plugin %s failed" % _edPlugin.getClassName())
460 self.__listWarningMessages = _edPlugin.getListOfWarningMessages()
461 for warningMessage in self.__listWarningMessages:
462 EDVerbose.screen(warningMessage)
463
464 self.__listErrorMessages = _edPlugin.getListOfErrorMessages()
465 for errorMessage in self.__listErrorMessages:
466 EDVerbose.screen(errorMessage)
467 if (_edPlugin.hasDataOutput()):
468 xsDataOutput = _edPlugin.getDataOutput()
469 if (xsDataOutput is not None and self.__strDataOutputFilePath is not None):
470 xsDataOutput.exportToFile(self.__strDataOutputFilePath)
471 if (xsDataOutput is not None and self.__edObtainedOutputDataFile is not None):
472 xsDataOutput.exportToFile(self.__edObtainedOutputDataFile)
473
474
476 return self.__edPlugin
477
478
480 return self.__xsDataOutput
481
482
484 return self.__listWarningMessages
485
486
488 return self.__listErrorMessages
489
490
492 return self.__edCommandLine
493
494
497
498
503
505 with self.__class__.__semaphore:
506 strCommandLineArgument = self.__edCommandLine.getArgument(_strKey)
507 return strCommandLineArgument
508
509 @classmethod
511 """
512 Lock the whole class
513 """
514 cls.__semaphore.acquire()
515
516
517 @classmethod
519 """
520 Unlock the whole class
521 """
522 cls.__semaphore.release()
523
524
526 return self.__strName + "-" + self.__strVersion
527
528
530 """
531 Getter for working dir
532 @rtype: string
533 @return working dir
534 """
535 return self.__strWorkingDir
536
537
539 """
540 Setter for working dir
541 @type _strDir: string
542 @param _strDir: working dir
543 """
544 self.__strWorkingDir = _strDir
545
546
548 return self.__bIsFailure
549
550
552 self.__bIsFailure = _bFailure
553
554
556 return self.__strPluginName
557