1 # Copyright (C) 2005 OPEN CASCADE, CEA, EDF R&D, LEG
2 # PRINCIPIA R&D, EADS CCR, Lip6, BV, CEDRAT
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License.
8 # This library is distributed in the hope that it will be useful
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 import os, glob, string, sys, re
23 # names of tags in XML configuration file
28 # names of attributes in XML configuration file
32 # certain values in XML configuration file ("launch" section)
40 portkill_nam = "portkill"
41 killall_nam = "killall"
42 modules_nam = "modules"
43 embedded_nam = "embedded"
44 standalone_nam = "standalone"
45 containers_nam = "containers"
48 except_nam = "noexcepthandler"
49 terminal_nam = "terminal"
52 # values in XML configuration file giving specific module parameters (<module_name> section)
53 # which are stored in opts with key <module_name>_<parameter> (eg SMESH_plugins)
54 plugins_nam = "plugins"
56 # values passed as arguments, NOT read from XML config file, but set from within this script
57 appname_nam = "appname"
60 script_nam = "pyscript"
62 # values of boolean type (must be '0' or '1').
63 # xml_parser.boolValue() is used for correct setting
64 boolKeys = ( gui_nam, splash_nam, logger_nam, file_nam, xterm_nam, portkill_nam, killall_nam, interp_nam, except_nam )
67 listKeys = ( containers_nam, embedded_nam, key_nam, modules_nam, standalone_nam, plugins_nam )
70 # Get the application version
71 # Uses GUI_ROOT_DIR (or KERNEL_ROOT_DIR in batch mode) +/bin/salome/VERSION file
76 root_dir = os.environ.get( 'KERNEL_ROOT_DIR', '' ) # KERNEL_ROOT_DIR or "" if not found
77 if root_dir and os.path.exists( root_dir + "/bin/salome/VERSION" ):
78 filename = root_dir + "/bin/salome/VERSION"
79 root_dir = os.environ.get( 'GUI_ROOT_DIR', '' ) # GUI_ROOT_DIR "" if not found
80 if root_dir and os.path.exists( root_dir + "/bin/salome/VERSION" ):
81 filename = root_dir + "/bin/salome/VERSION"
83 str = open( filename, "r" ).readline() # str = "THIS IS SALOME - SALOMEGUI VERSION: 3.0.0"
84 match = re.search( r':\s+([a-zA-Z0-9.]+)\s*$', str )
86 return match.group( 1 )
92 # Calculate and return configuration file unique ID
93 # For example: for SALOME version 3.1.0a1 the id is 300999701
95 def version_id( fname ):
96 vers = fname.split(".")
99 mr = re.search(r'^([0-9]+)([A-Za-z]?)([0-9]*)',vers[2])
102 release = int(mr.group(1))
104 if len(mr.group(2)): dev1 = ord(mr.group(2))
105 if len(mr.group(3)): dev2 = int(mr.group(3))
106 dev = dev1 * 100 + dev2
110 ver = ver * 100 + minor
111 ver = ver * 100 + release
113 if dev > 0: ver = ver - 10000 + dev
117 # Get user configuration file name
122 return "" # not unknown version
123 filename = "%s/.%src.%s" % (os.environ['HOME'], appname, v)
124 if os.path.exists(filename):
125 return filename # user preferences file for the current version exists
127 id0 = version_id( v )
128 # get all existing user preferences files
129 files = glob.glob( os.environ['HOME'] + "/." + appname + "rc.*" )
132 match = re.search( r'\.%src\.([a-zA-Z0-9.]+)$'%appname, file )
133 if match: f2v[file] = match.group(1)
137 ver = version_id( f2v[file] )
138 if ver and abs(last_version-id0) > abs(ver-id0):
143 # -----------------------------------------------------------------------------
146 # XML reader for launch configuration file usage
152 def __init__(self, fileName, _opts ):
153 print "Configure parser: processing %s ..." % fileName
156 self.section = section_to_skip
157 parser = xml.sax.make_parser()
158 parser.setContentHandler(self)
159 parser.parse(fileName)
162 def boolValue( self, str ):
163 if str in ("yes", "y", "1"):
165 elif str in ("no", "n", "0"):
171 def startElement(self, name, attrs):
172 self.space.append(name)
175 # if we are analyzing "section" element and its "name" attribute is
176 # either "launch" or module name -- set section_name
177 if self.space == [doc_tag, sec_tag] and nam_att in attrs.getNames():
178 section_name = attrs.getValue( nam_att )
179 if section_name == lanch_nam:
180 self.section = section_name # launch section
181 elif self.opts.has_key( modules_nam ) and \
182 section_name in self.opts[ modules_nam ]:
183 self.section = section_name # <module> section
185 self.section = section_to_skip # any other section
188 # if we are analyzing "parameter" elements - children of either
189 # "section launch" or "section "<module>"" element, then store them
190 # in self.opts assiciative array (key = [<module>_ + ] value of "name" attribute)
191 elif self.section != section_to_skip and \
192 self.space == [doc_tag, sec_tag, par_tag] and \
193 nam_att in attrs.getNames() and \
194 val_att in attrs.getNames():
195 nam = attrs.getValue( nam_att )
196 val = attrs.getValue( val_att )
197 if self.section == lanch_nam: # key for launch section
199 else: # key for <module> section
200 key = self.section + "_" + nam
202 self.opts[key] = self.boolValue( val ) # assign boolean value: 0 or 1
203 elif nam in listKeys:
204 self.opts[key] = val.split( ',' ) # assign list value: []
206 self.opts[key] = val;
210 def endElement(self, name):
213 if self.section != section_to_skip and name == sec_tag:
214 self.section = section_to_skip
217 def characters(self, content):
220 def processingInstruction(self, target, data):
223 def setDocumentLocator(self, locator):
226 def startDocument(self):
230 def endDocument(self):
234 # -----------------------------------------------------------------------------
237 # Command line options parser
239 def options_parser(line):
242 for delimiter in [" ", ",", "="]:
244 list += string.split(o, delimiter)
252 while i < len(source):
253 if source[i][0] != '-':
255 elif source[i][1] == '-':
261 if key is None and not result:
267 while i < len(source) and source[i][0] != '-':
268 result[key].append(source[i])
274 # -----------------------------------------------------------------------------
277 # Get the environment
280 # this attribute is obsolete
284 # Collect launch configuration files:
285 # - The environment variable "<appname>Config" (SalomeAppConfig) which can
286 # define a list of directories (separated by ':' or ';' symbol) is checked
287 # - If the environment variable "<appname>Config" is not set, only
288 # ${GUI_ROOT_DIR}/share/salome/resources/gui is inspected
289 # - ${GUI_ROOT_DIR}/share/salome/resources/gui directory is always inspected
290 # so it is not necessary to put it in the "<appname>Config" variable
291 # - The directories which are inspected are checked for files "<appname>.xml"
292 # (SalomeApp.xml) which define SALOME configuration
293 # - These directories are analyzed beginning from the last one in the list,
294 # so the first directory listed in "<appname>Config" environment variable
295 # has higher priority: it means that if some configuration options
296 # is found in the next analyzed cofiguration file - it will be replaced
297 # - The last configuration file which is parsed is user configuration file
298 # situated in the home directory: "~/.<appname>rc[.<version>]" (~/SalomeApprc.3.2.0)
300 # - Command line options have the highest priority and replace options
301 # specified in configuration file(s)
305 config_var = appname+'Config'
307 # set resources variable SaloemAppConfig if it is not set yet
309 if os.getenv(config_var):
310 dirs += re.split('[;|:]', os.getenv(config_var))
311 if os.getenv("GUI_ROOT_DIR") and os.path.isdir( os.getenv("GUI_ROOT_DIR") + "/share/salome/resources/gui" ):
312 dirs += [os.getenv("GUI_ROOT_DIR") + "/share/salome/resources/gui"]
313 os.environ[config_var] = ":".join(dirs)
315 dirs.reverse() # reverse order, like in "path" variable - FILO-style processing
317 _opts = {} # associative array of options to be filled
319 # parse SalomeApp.xml files in directories specified by SalomeAppConfig env variable
321 filename = dir+'/'+appname+'.xml'
322 if not os.path.exists(filename):
323 print "Configure parser: Warning : could not find configuration file %s" % filename
326 p = xml_parser(filename, _opts)
329 print "Configure parser: Error : can not read configuration file %s" % filename
332 # parse .SalomeApprc.<version> file in user's home directory if it exists
333 # if user file for the current version is not found the nearest to it is used
334 filename = userFile()
335 if not filename or not os.path.exists(filename):
336 print "Configure parser: Warning : could not find user configuration file"
339 p = xml_parser(filename, _opts)
342 print 'Configure parser: Error : can not read user configuration file'
346 # set default values for options which are NOT set in config files
347 for aKey in listKeys:
348 if not args.has_key( aKey ):
351 for aKey in boolKeys:
352 if not args.has_key( aKey ):
357 args[file_nam]=[afile]
359 args[appname_nam] = appname
361 # get the port number
364 file = open(os.environ["OMNIORB_CONFIG"], "r")
367 l = string.split(s, ":")
368 if string.split(l[0], " ")[0] == "ORBInitRef" or string.split(l[0], " ")[0] == "InitRef" :
369 my_port = int(l[len(l)-1])
376 args[port_nam] = my_port
378 # read command-line options
379 # each option given in command line overrides the option from xml config file
382 cmd_opts = options_parser(sys.argv[1:])
383 kernel_root_dir=os.environ["KERNEL_ROOT_DIR"]
388 # check if all command line options are correct
389 short_opts = ("h","g","l","f","x","m","e","s","c","p","k","t","i","r","z")
390 long_opts = (help_nam,gui_nam,logger_nam,file_nam,xterm_nam,modules_nam,
391 embedded_nam,standalone_nam,containers_nam,portkill_nam,
392 killall_nam,terminal_nam,interp_nam,except_nam,splash_nam,
396 if opt not in short_opts and opt not in long_opts:
397 print "Configure parser: Error : command line error : -%s" % opt
403 if cmd_opts.has_key("h") or cmd_opts.has_key(help_nam):
405 USAGE: runSalome.py [options]
407 Command line options:
409 --gui (-g) Launch in GUI mode [default].
410 --terminal (-t) Launching without GUI (in the terminal mode).
411 --terminal=<python_script>[,...] Launching without GUI (in the terminal mode) and
412 (-t=<python_script>[,...]) additionally import python script(s).
413 --logger (-l) Redirect messages to the CORBA collector.
414 --file=<file> (-f=<file>) Redirect messages to the log file.
415 --xterm (-x) Launch each SALOME server in own xterm console.
416 --modules=<module1>,<module2>,... SALOME module list (where <module1>, <module2>
417 (-m=<module1>,<module2>,...) are the names of SALOME modules which should be
418 available in the SALOME session).
419 --embedded=<server1>,<server2>,... CORBA servers to be launched in the Session
420 (-e=<server1>,<server2>,...) embedded mode.
421 Valid values for <serverN>: registry, study,
422 moduleCatalog, cppContainer
423 [default: all mentioned].
424 --standalone=<server1>,<server2>,... CORBA servers to be launched in the standalone
425 (-s=<server1>,<server2>,...) mode (as separate processes).
426 Valid values for <serverN>: registry, study,
427 moduleCatalog, cppContainer, pyContainer,
429 [default: pyContainer,supervContainer].
430 --containers=<container1>,... [obsolete] SALOME containers to be launched.
431 (-c=<container1>,...) Valid values: cpp, python, superv
432 [default: use --embedded and --standalone
434 --portkill (-p) Kill SALOME with the current port.
435 --killall (-k) Kill all running SALOME sessions.
436 --interp=<N> (-i=<N>) The number of additional xterm sessions to open.
437 In each xterm session SALOME environment is set
439 --splash (-z) Display splash screen.
440 --noexcepthandler (-r) Disable centralized exception handling
442 --test=<hdf_file_andor_python_scripts> HDF file to be opened on GUI starting and/or
443 Python script(s) to be imported in the GUI
444 study. The files can appear in arbitrary order.
445 If the HDF file is given it is opened, otherwise
446 the new empty study is created.
447 Python scripts are imported in the order of
449 This option is avaiable only in GUI mode,
450 for batch mode use --terminal(-t) option.
451 --help (-h) Print this help info
453 For each SALOME module, the environment variable <moduleN>_ROOT_DIR must be set.
454 KERNEL_ROOT_DIR is mandatory.
459 # apply command-line options to the arguments
460 BATCHMODE_FORCED = False
461 args[script_nam] = []
463 if opt in [ 'g', gui_nam ] :
464 if not BATCHMODE_FORCED: args[gui_nam] = 1
465 elif opt in [ 't', terminal_nam ] :
467 args[script_nam] = cmd_opts[opt]
468 BATCHMODE_FORCED = True
469 elif opt in [ 'z', splash_nam ] :
471 elif opt in [ 'r', except_nam ] :
473 elif opt in [ 'l', logger_nam ] :
475 elif opt in [ 'f', file_nam ] :
476 args[file_nam] = cmd_opts[opt]
477 elif opt in [ 'x', xterm_nam ] :
479 elif opt in [ 'i', interp_nam ] :
480 args[interp_nam] = cmd_opts[opt]
481 elif opt in [ 'm', modules_nam ] :
482 args[modules_nam] = cmd_opts[opt]
483 elif opt in [ 'e', embedded_nam ] :
484 args[embedded_nam] = cmd_opts[opt]
485 elif opt in [ 's', standalone_nam ] :
486 args[standalone_nam] = cmd_opts[opt]
487 elif opt in [ 'c', containers_nam ] :
488 args[containers_nam] = cmd_opts[opt]
489 elif opt in [ 'p', portkill_nam ] :
490 args[portkill_nam] = 1
491 elif opt in [ 'k', killall_nam ] :
492 args[killall_nam] = 1
493 elif opt in [ case_nam ] :
494 args[case_nam] = cmd_opts[opt]
497 # if --modules (-m) command line option is not given
498 # try SALOME_MODULES environment variable
499 if not cmd_opts.has_key( "m" ) and \
500 not cmd_opts.has_key( modules_nam ) and \
501 os.getenv( "SALOME_MODULES" ):
502 args[modules_nam] = re.split( "[:;,]", os.getenv( "SALOME_MODULES" ) )
505 # disable signals handling
506 if args[except_nam] == 1:
507 os.environ["NOT_INTERCEPT_SIGNALS"] = "1"
510 # now modify SalomeAppConfig environment variable
511 # to take into account the SALOME modules
512 dirs = re.split('[;|:]', os.environ[config_var] )
514 for m in args[modules_nam]:
515 if m not in ["KERNEL", "GUI", ""] and os.getenv("%s_ROOT_DIR"%m):
516 d1 = os.getenv("%s_ROOT_DIR"%m) + "/share/salome/resources/" + m.lower()
517 d2 = os.getenv("%s_ROOT_DIR"%m) + "/share/salome/resources"
518 if os.path.exists( "%s/%s.xml"%(d1, appname) ):
520 elif os.path.exists( "%s/%s.xml"%(d2, appname) ):
522 os.environ[config_var] = ":".join(dirs)