Salome HOME
Fix regression in ParaView installation script: invalid path to the patch
[tools/install.git] / runInstall
index c6e5bdf8f0cad9fca3e25d78f99820d8d6e0fbd5..a01939e58ca271f357ea9ee399caf6ea48514dd1 100755 (executable)
 #!/usr/bin/env python
 
-import xmllib
-import sys, os, string, re
-
-#==============================================================
-# get_help_info
-#==============================================================
-def get_help_info() :
-    str = "\nPAL/SALOME Installation Wizard\n\n"
-    str = str + "\tUsage : \n\tInstall [-g|b] [-f <xml-file>] [-t <target-dir>] [-tmp <tmp-dir>]\n"
-    str = str + "\n"
-    str = str + " -g              Runs the Installation Wizard in the GUI mode.\n"
-    str = str + "                 In this case only <xmlfile> is taken into account \n"
-    str = str + "                 from the parameters list. This key is default.\n"
-    str = str + "\n"
-    str = str + " -b              Runs the Installation Wizard in the batch mode.\n"
-    str = str + "                 All the found parameters are taken in to account.\n"
-    str = str + "\n"
-    str = str + " -f <xml-file>   The configuration file to be parsed by the Installation Wizard.\n" 
-    str = str + "                 If this parameter is missed then the script tries to define\n"
-    str = str + "                 the Red Hat version and use the corresponding xml. For example,\n"
-    str = str + "                 for Red Hat 8.0 config_RedHat8_0.xml file is supposed to be used\n"
-    str = str + "                 by default. If the appropriate xml file is not found, the config.xml\n"
-    str = str + "                 is used by default.\n"
-    str = str + "\n"
-    str = str + " -t <target-dir> The target directory the products to be installed to.\n"
-    str = str + "                 This parameter overloads the target directory described in the\n"
-    str = str + "                 configuration file.\n"
-    str = str + "\n"
-    str = str + " -tmp <tmp-dir>  The directory which should be used for the temporary files.\n"
-    str = str + "                 This parameter overloads the temporary directory described in the\n"
-    str = str + "                 configuration file.\n"
-    str = str + "\n"
-    str = str + " -h              Prints help information.\n" 
-    return str
-
-#==============================================================
-# error_exit
-#==============================================================
-def error_exit (str = ""):
-    import sys
-    if len(str): res = "\n" + str + "\n"
-    else : res = ""
-    print res + \
-          get_help_info() 
-    sys.exit(1);
+"""
+Installation Wizard launching script.
+
+This script is the part of the SALOME installation procedure.
+Author    : Vadim SANDLER, Open CASCADE SAS (vadim.sandler@opencascade.com)
+Created   : Thu Dec 18 12:01:00 2002
+Copyright : 2002-2014 CEA
+
+"""
+
+__version__ = "1.1.5"
+
+# --- imports --- #
+import sys
+try:
+    import xml.sax, xml.dom.minidom
+    import os, re
+    import types
+    import random
+    import warnings
+except Exception, an_exc:
+    sys.exit("Error: %s! Please check the installed Python package." % str(an_exc))
+    pass
+
+# --- avoid "deprecation" warnings --- #
+warnings.filterwarnings("ignore", "", DeprecationWarning)
+
+# --- global variables --- #
+opt_parser = None
+root_path  = None
+
+# --- actions definition --- #
+__BINARIES__   = "install_binary"
+__BUILDSRC__   = "install_source_and_build"
+__PREINSTALL__ = "try_preinstalled"
+
+# --- product type definition --- #
+__CTX__COMPONENT__    = "component"
+__CTX__PREREQUISITE__ = "prerequisite"
+
+#------------------------------------------------------------------#
+#                                                                  #
+#                 COMMAND LINE ARGUMENTS PARSER                    #
+#                                                                  #
+#------------------------------------------------------------------#
 
+#===================================================================
+# class OptBaseError : base parse error
+#===================================================================
+class OptBaseError(Exception):
+    """
+    Base option parsing exception class
+    """
+    def __init__(self, msg):
+        self.msg = msg
+    def __str__ (self):
+        return self.msg
 
-#==============================================================
-# Cheks whether the passed parameter is a key.
-#==============================================================
-def is_key ( val ):
-    import re
-    if val is not None : 
-       return re.match(r'^-[a-zA-Z]', val)
-    return 0
+#===================================================================
+# class OptError : bad option error
+#===================================================================
+class OptError(OptBaseError):
+    """
+    Bad option exception class
+    """
+    def __init__ (self, msg, option):
+        self.msg = msg
+        self.option = option
+    def __str__ (self):
+        if self.option:
+            opt_prs = "<unknown>"
+            if self.option.short_opt and self.option.long_opt:
+                opt_prs = "%s/%s"%(self.option.short_opt,self.option.long_opt)
+            elif self.option.short_opt:
+                opt_prs = "%s"%(self.option.short_opt)
+            elif self.option.long_opt:
+                opt_prs = "%s"%(self.option.long_opt)
+            return "option %s: %s"%(opt_prs, self.msg)
+        return self.msg
 
-#==============================================================
-# From the list of parameters extracts value following 'key' 
-#==============================================================
-def extract_parameter ( key, args ) :
-    import sys
-    length = len(args);
-    if ( length == 0 ) :  return None
-   
-    found = 0;
-
-    for i in range(0, length-1):
-        if  args[i] == key : 
-            if ( is_key ( args[i+1]) ) :
-               print " No value after key ", key
-                sys.exit(1);
-           
-           value = args[i+1]
-            if ( i < length - 2  and is_key ( args[i+2] ) == 0 ) : #control that only one value follows key 
-                                                              #(not a list). In this case params are correct.
-               print "Too much values after key ", key
-                sys.exit(1);
-           
-           found = 1; break;
-    
-    if (found) : 
-       return  value 
-    
-    return None
+#===================================================================
+# class ArgError : bad option argument error
+#===================================================================
+class ArgError(OptBaseError):
+    """
+    Bad argument exception class
+    """
+    pass
 
+#===================================================================
+# class ValError : bad command line parameter error
+#===================================================================
+class ValError(OptBaseError):
+    """
+    Bad parameter exception class
+    """
+    pass
 
-#===============================================================
-# Extracts list of values following specified 'key' from 'args[]'
-#===============================================================
-def extract_list (key, args) : 
+#===================================================================
+# class ArgOption : command line option
+#===================================================================
+class ArgOption:
+    """
+    Option class
+    """
+    attrs   = ["short_opt", "long_opt", "dest", "action", "type", "default", "metavar", "help"]
+    actions = ["store", "store_true", "store_false"]
+    types   = ["string", "int", "float", "bool"]
+    def __init__(self, *args, **kwargs):
+        # set defaults
+        for attr in self.attrs: setattr(self, attr, None)
+        # parse arguments
+        for i in range(len(args)):
+            if i > len(self.attrs)-1:
+                msg = "Wrong number of parameters is given (maximum is %d)" % len(self.attrs)
+                raise OptBaseError(msg)
+            setattr(self, self.attrs[i], args[i])
+        for arg in kwargs:
+            if arg not in self.attrs:
+                msg = "Invalid argument: %s" % arg
+                raise OptBaseError(msg)
+            setattr(self, arg, kwargs[arg])
+        # check short option key
+        if self.short_opt and \
+               not re.match("^-[a-zA-Z]$",self.short_opt):
+            msg  = "invalid short option key; "
+            msg += "should be of the form -x (x is letter)"
+            raise OptError(msg, self)
+        # check long option key
+        if self.long_opt and \
+               not re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$",self.long_opt):
+            msg  = "invalid long option key; "
+            msg += "should be of the form --word[[-word]...] "
+            msg += "(word is letters and digits sequence)"
+            raise OptError(msg, self)
+        # check that at least one option key is defined
+        if not self.short_opt and not self.long_opt:
+            msg  = "invalid option; neither short nor long option key is defined"
+            raise OptError(msg, self)
+        # destination
+        if not self.dest and self.long_opt:
+            self.dest = self.long_opt[2:].replace('-','_')
+        if not self.dest and self.short_opt:
+            self.dest = self.short_opt[1:]
+        # action
+        if not self.action:
+            self.action = "store"
+        if self.action not in self.actions:
+            msg  = "invalid action: %s" % self.action
+            raise OptError(msg, self)
+        # type
+        if not self.type:
+            if self.action in ["store_true","store_false"]: self.type = "bool"
+            else: self.type = "string"
+        if self.type not in self.types:
+            msg  = "invalid type: %s" % self.type
+            raise OptError(msg, self)
+        if self.action in ["store_true","store_false"] and self.type != "bool":
+            msg  = "invalid type: %s : should be 'bool' or None" % self.type
+            raise OptError(msg, self)
+        # default
+        if self.default is not None:
+            try:
+                if self.type == "string": self.default = str(self.default)
+                if self.type == "int":    self.default = int(self.default)
+                if self.type == "float":  self.default = float(self.default)
+                if self.type == "bool":   self.default = boolean(self.default)
+            except :
+                msg  = "invalid default value type: should be %s" % self.type
+                raise OptError(msg, self)
+            pass
+        # metavar
+        if not self.metavar:
+            self.metavar = self.dest.upper()
+        # help
+        if not self.help:
+            self.help = ""
+        pass
 
-    lenght = len(args)
-    if ( args is None or lenght == 0 ):
-       error_exit()
+    def to_string(self):
+        """
+        Returns string representation of the option
+        """
+        opts = []
+        opt = self.short_opt
+        if opt and self.action == "store" and self.metavar: opt += " %s" % self.metavar
+        if opt: opts.append(opt)
+        opt = self.long_opt
+        if opt and self.action == "store" and self.metavar: opt += "=%s" % self.metavar
+        if opt: opts.append(opt)
+        return (", ").join(opts)
+    
+#===================================================================
+# class Values : resulting option values
+#===================================================================
+class Values:
+    """
+    Values class
+    """
+    def __init__(self):
+        pass
+        
+#===================================================================
+# class ArgParser : command line arguments parser
+#===================================================================
+class ArgParser:
+    """
+    Arguments parser class
+    """
+    def __init__(self):
+        self.options = []
+        pass
 
-    list=[]
-    found = 0
+    def add_option(self, *args, **kwargs):
+        """Register an option"""
+        o = ArgOption(*args, **kwargs)
+        self._check_option(o)
+        self.options.append(o)
+        pass
 
-    for i in  range(0, length) :
-        if args[i] == key  : 
-            if (is_key ( args[i+1]))  : 
-                error_exit();
-           
-            for i in range (i+1, lenght):
-                if is_key(args[i]) : break
-                list.append(args[i])
-            found =1; break
-     
-    return list; #empty list is returned if no values after key
+    def parse_args(self, args = None):
+        """Parse an arguments"""
+        if not args: args = sys.argv[1:]
+        values = Values()
+        for o in self.options:
+            if o.default is not None:
+                setattr(values, o.dest, o.default)
+            elif not hasattr(values,o.dest):
+                setattr(values, o.dest, None)
+        try:
+            (values, args) = self._process_args(values, args)
+        except (ArgError, ValError), e:
+            self._error(e.msg)
+
+        return (values, args)
+            
+    def print_usage(self):
+        """Print usage"""
+        print "usage: %s [options]" % os.path.basename(sys.argv[0])
+        pass
 
+    def print_help(self):
+        """Print help"""
+        self.print_usage()
+        print ""
+        olen = 0
+        _maxwidth, _indent = 79, 2
+        if len(self.options):
+            for option in self.options:
+                if olen < len(option.to_string()): olen = len(option.to_string())
+            print "options:"
+            for option in self.options:
+                strings = []
+                for hs in option.help.split("\n"):
+                    s = ""
+                    for w in hs.split():
+                        if len("%s %s" % (s,w)) > _maxwidth:
+                            strings.append(s.strip()); s = ""
+                        s = "%s %s" % (s,w)
+                    if s.strip(): strings.append(s.strip())
+                if not strings: strings[:0] = [""]
+                print "%s%s%s" % (option.to_string(), " "*(_indent+olen-len(option.to_string())), strings[0])
+                for i in range(1, len(strings)):
+                    print "%s%s" % (" "*(olen+_indent), strings[i])
+        pass
+    
+    def _check_option(self, option):
+        o = self._get_option(option.short_opt)
+        if not o: o = self._get_option(option.long_opt)
+        if o:
+            msg = "option conflicts with previously defined option(s)"
+            raise OptError(msg, option)
+        pass
 
-#==============================================================
-# Method find the $key in the list and return 1 if success
-# and 0 otherwise. 
-#==============================================================
-def find_key (key, argv) :
+    def _get_option(self, opt_key):
+        if opt_key:
+            for o in self.options:
+                if opt_key in [o.short_opt, o.long_opt]: return o
+        return None
+        
+    def _error(self, msg):
+        self.print_usage()
+        sys.exit("\n%s: error: %s\n" % (os.path.basename(sys.argv[0]), msg))
+        pass
 
-    if (not is_key(key)) : return 0
+    def _check_value(self, option, value):
+        o = self._get_option(option)
+        try:
+            if o.type == "string": return str(value)
+            if o.type == "int":    return int(value)
+            if o.type == "float":  return float(value)
+            if o.type == "bool":   return boolean(value)
+        except:
+            msg  = "invalid value type for option %s: %s; " % (option, value)
+            msg += "should be %s" % o.type
+            raise ValError(msg)
+        raise OptBaseError("unknown error")
+
+    def _process_args(self, values, args):
+        res_args = []
+        cur_opt = None
+        rargs   = []
+        for index in range(len(args)):
+            a = args[index]
+            if cur_opt and cur_opt[1].action == "store":
+                setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a))
+                cur_opt = None
+                continue
+            if a == "-":
+                rargs = args[index+1:]
+                break
+            elif re.match("^-[a-zA-Z].*", a):
+                for i in range(1,len(a)):
+                    if cur_opt and cur_opt[1].action == "store":
+                        setattr(values, cur_opt[1].dest, self._check_value(cur_opt[0], a[i:]))
+                        cur_opt = None
+                        break
+                    o = self._get_option("-%s"%a[i])
+                    if not o:
+                        raise ArgError("no such option: -%s"%a[i])
+                    if o.action == "store_true":
+                        setattr(values, o.dest, True)
+                    elif o.action == "store_false":
+                        setattr(values, o.dest, False)
+                    else:
+                        cur_opt = ("-%s"%a[i], o)
+                pass
+            elif re.match("^--[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*", a):
+                oname  = ("%s="%a).split("=")[0]
+                ovalue = ("%s="%a).split("=")[1]
+                o = self._get_option(oname)
+                if not o:
+                    raise ArgError("no such option: %s" % oname)
+                if o.action == "store_true":
+                    if ovalue:
+                        raise ValError("option %s does not take a value" % oname)
+                    setattr(values, o.dest, True)
+                elif o.action == "store_false":
+                    if ovalue:
+                        raise ValError("option %s does not take a value" % oname)
+                    setattr(values, o.dest, False)
+                else:
+                    if ovalue:
+                        setattr(values, o.dest, self._check_value(oname, ovalue))
+                    else:
+                        cur_opt = (oname, o)
+                pass
+            elif a.startswith("-"):
+                raise ArgError("bad formatted option: %s" % a)
+            else:
+                rargs = args[index:]
+                break
+        if cur_opt and cur_opt[1].action == "store":
+            raise ValError("option %s requires value" % cur_opt[0])
+        return (values, rargs)
+
+#------------------------------------------------------------------#
+#                                                                  #
+#                 XML CONFIGURATION FILES PARSER                   #
+#                                                                  #
+#------------------------------------------------------------------#
 
-    for simbol in  argv :
-        if simbol == key:
-            return 1 
-    return 0
+#===================================================================
+# class Config : general configuration options : version, target and
+#                temporary directories, etc...
+#===================================================================
+class Config :
+    """
+    General configuration file options:
+    - Install Wizard window caption
+    - SALOME platform version
+    - Copyright and license info
+    - Default target and temporary directories
+    - List of optional libraries for Salome
+    """
+    def __init__(self,
+                 theVersion   = None,
+                 theCaption   = None,
+                 theCopyright = None,
+                 theLicense   = None,
+                 thePlatforms = None,
+                 theTargetdir = None,
+                 theTmpdir    = None,
+                 theOptLibs   = None):
+        self.version   = strip(theVersion)
+        self.caption   = strip(theCaption)
+        self.copyright = strip(theCopyright)
+        self.license   = strip(theLicense)
+        self.platforms = strip(thePlatforms)
+        self.targetdir = strip(theTargetdir)
+        self.tmpdir    = strip(theTmpdir)
+        self.optlibs   = strip(theOptLibs)
 
 #==============================================================
-# Parse the list of parameters
+# class Product : pre-requisite product options
 #==============================================================
-def parse_parameters (args) :
-
-    if find_key('-h', args) :
-        print get_help_info();
-        import sys
-        sys.exit(0)
+class Product :
+    """
+    Product options:
+    - name, version
+    - target Linux OS version
+    - dependencies
+    - required disk space
+    - installation script
+    - etc...
+    """
+    def __init__(self,
+                 theName,
+                 theType               = None,
+                 theOS                 = None,
+                 theVersion            = None,
+                 theDependencies       = None,
+                 theWoGuiInstallation  = None,
+                 theInstalldiskspace   = None,
+                 theScript             = None,
+                 thePickUpEnvironment  = None):
+        self.name               = strip(theName)
+        self.type               = strip(theType)
+        self.os                 = strip(theOS)
+        self.version            = strip(theVersion)
+        self.dependencies       = strip(theDependencies)
+        self.woguiinst          = strip(theWoGuiInstallation)
+        self.installdiskspace   = strip(theInstalldiskspace)
+        self.script             = strip(theScript)
+        self.pickupEnv          = strip(thePickUpEnvironment)
+        self.whattodo           = __BINARIES__
         
-    xmlfile = extract_parameter("-f", args)
-    target_dir =  extract_parameter("-t", args)
-    tmp_dir = extract_parameter("-tmp", args)
-    if find_key('-b', args):
-        is_gui = 0
-    else : is_gui = 1
-    return [xmlfile, target_dir,  tmp_dir, is_gui]
-
-
-#=================================================================
-# The first algorithm to create the dependencies list by their level
-#=================================================================
-def get_next_level(list, products):
+    def setMode(self, mode):
+        if mode not in [__BINARIES__, __BUILDSRC__, __PREINSTALL__]:
+            return
+        self.whattodo = mode
+        return
+        
+#===================================================================
+# class ConfigParser : XML files parser implementation
+#===================================================================
+class ConfigParser:
+    """
+    XML configuration files parser
+    """
+    def __init__(self, is_force_src=False, pltname=None):
+        self.docElem = None
+        self.products = []
+        self.full_prods_list = []
+        self.config = None
+        self.is_force_src = is_force_src
+        self.pltname = pltname
+        pass
+        
+    def parse_config(self):
+        # Parse 'config' part of the XML file
+        configElem = self.docElem.getElementsByTagName('config')[0]
+        
+        self.config = Config(configElem.getAttribute('version').strip(),
+                             configElem.getAttribute('caption').strip(),
+                             configElem.getAttribute('copyright').strip(),
+                             configElem.getAttribute('license').strip(),
+                             configElem.getAttribute('platforms').strip(),
+                             configElem.getAttribute('targetdir').strip(),
+                             configElem.getAttribute('tempdir').strip(),
+                             configElem.getAttribute('optionallibs').strip())
+        if not self.pltname and self.config.platforms:
+            self.pltname = self.config.platforms.split(",")[0].strip()
+        pass
     
-    import re
-    result = []
-    expr = "(" + list[0].name
-    for i in range(1, len(list)):
-        expr = expr + "|"+ list[i].name
+    def parse_dependencies(self):
+        # Parse 'dependencies' part of the XML file
+        depsMap = {}
+        depsElem = self.docElem.getElementsByTagName('dependencies')[0]
+        for prodElem in depsElem.getElementsByTagName('product'):
+            prodName = prodElem.getAttribute('name').strip()
+            if not prodName: continue
+            depsList = []
+            for depElem in prodElem.getElementsByTagName('dep'):
+                depsList.append(depElem.firstChild.data)
+                pass
+            depsMap[prodName] = depsList
+            pass
+        return depsMap
     
-    expr = expr + ")$"
-    #expr=re.compile(expr)
+    def parse_product(self):
+        # Parse 'products' part of the XML file
+        depsMap = self.parse_dependencies()
+        prodsElem = self.docElem.getElementsByTagName('products')[0]
+        sal_prods_list = []; req_prods_list = []
+        modules_list = []; prereqs_list = []
+        for prodElem in prodsElem.getElementsByTagName('product'):
+            prodName = prodElem.getAttribute('name').strip()
+            if not prodName: continue
+            instElems = prodElem.getElementsByTagName('installation')
+            instElem = None
+            for node in instElems:
+                if not self.pltname or self.pltname == node.getAttribute('os').strip():
+                    instElem = node
+                    break
+                pass
+            if not instElem: continue
+            if check_bool(str(instElem.getAttribute('disable').strip())): continue
+            depsList = []
+            if prodName in depsMap: depsList = depsMap[prodName]
+            aProduct = Product(prodName,
+                               prodElem.getAttribute('type').strip(),
+                               instElem.getAttribute('os').strip(),
+                               instElem.getAttribute('version').strip(),
+                               depsList,
+                               instElem.getAttribute('woguimode').strip(),
+                               instElem.getAttribute('installdiskspace').strip(),
+                               instElem.getAttribute('script').strip(),
+                               instElem.getAttribute('pickupenv').strip())
+            if self.is_force_src:
+                aProduct.setMode(__BUILDSRC__)
+                pass
+            if prodElem.getAttribute('type').strip() == "component":
+                sal_prods_list.append(aProduct)
+                # fill an ordered modules list -----------
+                modules_list.append(prodName)
+                modules_list.append(prodName + "_src")
+                pass
+            else: #prerequisite
+                req_prods_list.append(aProduct)
+                # fill an ordered prerequisites list -----------
+                prereqs_list.append(prodName)
+                #AKL: prerequisite sources and temp files are removed, by default.
+                #     So, there is no need to make sources environment
+                #if aProduct.whattodo == __BUILDSRC__: prereqs_list.append(prodName + "_src")
+                pass
+            pass
+        self.products.extend( req_prods_list )
+        self.products.extend( sal_prods_list )
+        if len(self.products) != 0:
+            gcc_product = Product("gcc",
+                                  __CTX__PREREQUISITE__,
+                                  self.products[0].os,
+                                  "",
+                                  [],
+                                  None,
+                                  "0,0,0",
+                                  "gcc-common.sh",
+                                  "")
+            gcc_product.setMode(__PREINSTALL__)
+            self.products.insert(0, gcc_product)
+            prereqs_list.insert(0, gcc_product.name)
+            pass
+        self.full_prods_list.extend( prereqs_list )
+        self.full_prods_list.extend( modules_list )
+        pass
 
-    for product in products:
-        deps = re.sub(r'\s+', "", product.dependencies)
-        if re.search(expr,  deps):
-            result.append(product)
+    def parse(self, xml_file):
+        filehandle = open(xml_file)
+        sax_parser = xml.sax.make_parser()
+        doc = xml.dom.minidom.parse(filehandle, sax_parser)
+        filehandle.close()
 
-    return result
+        self.docElem = doc.documentElement
+        self.parse_config()
+        self.parse_product()
+        pass
 
+    def getProduct(self, prod):
+        for product in self.products:
+            if product.name == prod:
+                return product
+        return None
 
-def create_levels(prods):
-    import copy
-    
-    products = copy.deepcopy(prods)
-    
-    result = {}
-    import re
-    #1. find the products with empty lists of dependencies
-    list = []
-    for product in products:
-        if len(re.sub(r'\s', "", product.dependencies)) == 0 :
-            list.append(product)
 
-    if len(list) == 0 :
-        raise RuntimeError, "Products that depend on nothing are not found"
+#------------------------------------------------------------------#
+#                                                                  #
+#                         SERVICE FUNCTIONS                        #
+#                                                                  #
+#------------------------------------------------------------------#
 
-    # remove the first level products from the common list of products
-    for product in list :
-        products.remove(product)
-
-    ind = 0; 
-    result[0] = list
+#==============================================================
+# message: prints diagnostic information
+#==============================================================
+def message(msg):
+    """
+    Prints diagnostic information.
+    """
+    if msg.strip():
+        print ">>>", msg
+    pass
 
-    while (len(products)) :
-        res = get_next_level(list, products)
-        if len(res) == 0 :
-            raise RuntimeError, "Empty list of products is found"
+#==============================================================
+# warning: prints warning
+#==============================================================
+def warning(msg):
+    """
+    Prints warning.
+    """
+    if msg.strip():
+        print ""
+        print msg
+        print ""
+    pass
 
-        for product in res :
-            products.remove(product)
+#==============================================================
+# error_exit : prints (optionally) error string, then prints
+#              help information and quits
+#==============================================================
+def error_exit(msg = "", print_help = True):
+    """
+    Prints (optionally) error string,
+    then prints help information and quits.
+    """
+    # print error message
+    if len(msg.strip()):
+        print ""
+        print msg
+        print ""
+    # print help information
+    if print_help:
+        global opt_parser
+        if opt_parser:
+            opt_parser.print_help() 
+            print ""
+    # cleaning 
+    clean_all()
+    # quit
+    sys.exit(1);
+    pass
 
-        ind = ind +1
-        result[ind] =  res
-        list = res
-            
-    str = ""
-    for i in result.keys():
-        for product in  result[i]:
-            str = str + product.name + " "
+#==============================================================
+# boolean : Converts string to boolean value.
+#==============================================================
+def boolean(val):
+    """
+    Converts string to boolean value if possible.
+    Raises exception if wrong string is used.
+    """
+    if isinstance(val, types.StringType):
+        if val.strip().lower()   in ["true",  "yes", "ok"]     : return True
+        elif val.strip().lower() in ["false", "no",  "cancel"] : return False
+        else: raise TypeError("invalid boolean value")
+    return bool(val)
 
-    return str;
-            
 #=================================================================
-# The second algorithm
+# check_bool : checks boolean value: yes/no, true/false, 1/0
 #=================================================================
-def get_dependencies_set(prods) :
-    import copy
-    import re
-
-    products = copy.deepcopy(prods)
-    deps = ""
-    list = []
-
-    while (len(products)) :
-
-        tmplist = []
-        #find the products with empty list of dependencies
-        for product in products:
-            product.dependencies = re.sub(r'\s+$', "", product.dependencies)
-            product.dependencies = re.sub(r'^\s+', "", product.dependencies)
-           
-            if len(product.dependencies) == 0 :
-               tmplist.append(product); 
-               deps = deps + " " + product.name
-
-        list.append(tmplist)
-
-        #remove the products names from other products dependencies
-        for item in tmplist:
-            products.remove(item)
-
-            regexpr1 = "((^|,(\s+)?)"+item.name+"$|^"+item.name+"(\s+)?,(\s+)?)"
-            regexpr2 = ",(\s+)?"+item.name+"(\s+)?,(\s+)?"
+def check_bool(val):
+    """
+    Checks boolean value.
+    """
+    try:
+        return boolean(val)
+    except:
+        pass
+    return False
 
-            for product in products:
-                product.dependencies = re.sub(r'\s+$', "", product.dependencies)
-                product.dependencies = re.sub(r'^\s+', "", product.dependencies)
+#==============================================================
+# clean_all : performs system cleaning before exiting
+#==============================================================
+def clean_all():
+    """
+    Performs system cleaning before exiting.
+    """
+    global root_path
+    remove_dir(root_path)
+    pass
 
-                product.dependencies = re.sub(regexpr1, "", product.dependencies)
-                product.dependencies = re.sub(regexpr2, ",", product.dependencies)
+#==============================================================
+# parse_parameters : parses command line arguments
+#==============================================================
+def parse_parameters():
+    """
+    Parses command line arguments.
+    """
+    global opt_parser
+    opt_parser = ArgParser()
+    
+    help_str  = "Runs the Installation Wizard in the GUI mode [default].\n"
+    opt_parser.add_option("-g",
+                          "--gui",
+                          action="store_true",
+                          dest="gui",
+                          default=True,
+                          help=help_str)
+    help_str  = "Runs the Installation Wizard in the TUI mode."
+    opt_parser.add_option("-b",
+                          "--batch",
+                          action="store_false",
+                          dest="gui",
+                          help=help_str)
+    help_str  = "The configuration xml file.\n"
+    help_str += "If this parameter is missing, then the program tries to define the "
+    help_str += "Linux platform and use the corresponding xml file. For example, "
+    help_str += "for Red Hat 8.0 config_RedHat_8.0.xml file is used in this case. "
+    opt_parser.add_option("-f",
+                          "--file",
+                          action="store",
+                          dest="xmlfile",
+                          metavar="FILE",
+                          help=help_str)
+    help_str  = "The platform specification.\n"
+    help_str += "This option can be used in conjunction with --file option in order"
+    help_str += "to specify Linux platform name when XML file contains installation"
+    help_str += "options for several platforms."
+    opt_parser.add_option("-p",
+                          "--platform",
+                          action="store",
+                          dest="platform",
+                          metavar="PLT",
+                          help=help_str)
+    help_str  = "The target directory the products to be installed to.\n"
+    help_str += "When used this parameter overrides the default target directory "
+    help_str += "defined in the configuration xml file."
+    opt_parser.add_option("-d",
+                          "--target",
+                          action="store",
+                          dest="target_dir",
+                          metavar="DIR",
+                          help=help_str)
+    help_str  = "The directory to be used for temporary files.\n"
+    help_str += "When used this parameter overrides the default temporary directory "
+    help_str += "defined in the configuration xml file."
+    opt_parser.add_option("-t",
+                          "--tmp",
+                          action="store",
+                          dest="tmp_dir",
+                          metavar="DIR",
+                          help=help_str)
+    help_str  = "Force all products to be installed from sources \n"
+    help_str += "including SALOME modules.\n"
+    help_str += "If this option is used all the default installation modes are ignored."
+    opt_parser.add_option("-a",
+                          "--all-from-sources",
+                          action="store_true",
+                          dest="force_sources",
+                          default=False,
+                          help=help_str)
+    help_str  = "Install all SALOME binaries packages to one directory.\n"
+    help_str += "This option is ignored when --all-from-sources (-a) option is used."
+    opt_parser.add_option("-s",
+                          "--single-directory",
+                          action="store_true",
+                          dest="single_dir",
+                          default=False,
+                          help=help_str)
+    help_str  = "Prints version information and quits."
+    opt_parser.add_option("-v",
+                          "--version",
+                          action="store_true",
+                          help=help_str)
+    help_str  = "Prints this help and quits."
+    opt_parser.add_option("-h",
+                          "--help",
+                          action="store_true",
+                          help=help_str)
+    (options, args) = opt_parser.parse_args()
+    if options.help:
+        # print help info and quit
+        print "\nSALOME Installation Wizard (running on %s)\n" % get_os_name()
+        opt_parser.print_help()
+        print ""
+        sys.exit(0)
+    if options.version:
+        # print version info and quit
+        print ""
+        cmd = "./bin/SALOME_InstallWizard --version"
+        os.system(cmd)
+        print ""
+        sys.exit(0)
+    return [options.xmlfile, options.target_dir, options.tmp_dir, options.gui, options.force_sources, options.single_dir, options.platform]
 
-    return deps 
+#=================================================================
+# strip : removes spaces at the beginning and at the end of the 
+#         <param> if it is of string type
+#=================================================================
+def strip(param):
+    """
+    Removes spaces at the beginning and at the end
+    of the given parameter.
+    """
+    if type(param) == types.StringType:
+        return param.strip()
+    return param
     
+#=================================================================
+# get_dependencies : extract products dependencies
+#=================================================================
+def get_dependencies(prods):
+    """
+    Gets a list of installed and required products.
+    """
+    prods_list = []
+    for product in prods:
+        for dep in product.dependencies:
+            if dep and dep not in prods_list:
+                prods_list.append( dep )
+                dep_name = dep
+                if product.whattodo == __BUILDSRC__:
+                    dep_name = dep + "_src"
+                if dep_name not in parser.full_prods_list:
+                    msg = "Prerequisite '%s' is required for '%s' product,\n"%(dep, product.name)
+                    msg += "but the first one is absent in the list of products to be installed!\n"
+                    msg += "Please check your XML file."
+                    warning(msg)
+
+        if product.name and product.name not in prods_list:
+            prods_list.append( product.name )
+            
+    return " ".join( prods_list )
+
 #==============================================================
-# Creates dir, returns the part of path that existed early.
-# Access may be defined.
+# create_dir : creates a directory with (optional) permissions,
+#              returns the part of path that existed before
+#              directory creation; exits with error if access
+#              is denied
 #==============================================================
-def create_dir (directory, access = 0777):
-    import string, os
-    dirs = string.split(directory, "/")
-    existing = ""; dir = ""
+def create_dir(directory, access = 0777):
+    """
+    Creates a directory with (optional) permissions,
+    returns the part of path that existed before
+    directory creation; exits with error if access
+    is denied.
+    """
+    dirs = directory.split("/")
+    existing = "";
+    dir = ""
     root = ""
-    for item in dirs:
-        if len(item) == 0:  continue
-        dir = dir + "/"+item
+    for subdir in dirs:
+        if len(subdir) == 0:  continue
+        dir = "%s/%s"%(dir, subdir)
         if os.path.exists(dir):
             existing = dir
         else:
-            os.mkdir(dir, access )
-            #root= existing + "/"+item
-            if dir == existing + "/"+item :
+            try:
+                os.mkdir(dir, access)
+            except:
+                error_exit("Can't create directory: %s.\nAccess is denied."%directory)
+            if dir == "%s/%s"%(existing, subdir):
                 root = dir
-            #else : root = existing
-    
     return root
 
 #==============================================================
-# class Product 
+# substituteVars : performes environment variables substistution
+#                  the given string; if varibale is not defined
+#                  it is substituted by the empty string
 #==============================================================
-
-class Product :
-    def __init__(self, theName,
-                 theVersion            = None,
-                 theInstall            = None,
-                 theSupportred         = None,
-                 theDisable            = None,
-                 theDependencies       = None,
-                 theInstalldiskspace   = None,
-                 theTemporarydiskspace = None,
-                 theScript             = None):
-        
-
-        self.name               = theName
-        self.version            = theVersion
-        self.install            = theInstall
-        self.supported          = theSupportred
-        self.disable            = theDisable
-        self.dependencies       = theDependencies
-        self.installdiskspace   = theInstalldiskspace
-        self.temporarydiskspace = theTemporarydiskspace
-        self.script             = theScript
-
-#===================================================================
-# class Config
-#===================================================================
-class Config :
-    def __init__(self, theVersion='', theCaption='', theCopyright='', theLicense='', theOS=''):
-        self.version   = theVersion
-        self.caption   = theCaption
-        self.copyright = theCopyright
-        self.license   = theLicense
-        self.os        = theOS
-
-
-#===================================================================
-# class Path
-#===================================================================
-class Path :
-    def __init__(self, theTargetdir=".", theTmpdir="."):
-        self.targetdir = theTargetdir
-        self.tmpdir    = theTmpdir
-
-        
-#===================================================================
-# class ConfigParser
-#===================================================================
-class ConfigParser(xmllib.XMLParser):
-    def __init__(self):
-        xmllib.XMLParser.__init__(self)
-        self.products = []
-        self.currentdata = []
-        self.path = None
-        self.config = None
-        
-    def handle_data(self, data):
-        self.currentdata.append(data)
-        
-    def start_product(self, attrs):
-        aProduct = Product(attrs['name'],
-                           attrs['version'],
-                           attrs['install'],
-                           attrs['supported'],
-                           attrs['disable'],
-                           attrs['dependancies'],
-                           attrs['installdiskspace'],
-                           attrs['temporarydiskspace'],
-                           attrs['script'])
-
-        self.products.append(aProduct)
-
-    def end_product(self):
-        pass
-
-    def start_config(self, attrs):
-        self.config = Config(attrs['version'],
-                             attrs['caption'],
-                             attrs['copyright'],
-                             attrs['license'],
-                             attrs['os'])
-    def end_config(self):
-        pass
-
-    def start_path (self, attrs):
-        self.path = Path(attrs['targetdir'],
-                         attrs['tempdir'])
-        print self.path.tmpdir
-        
-    def end_path(self):
-        pass
+def substituteVars(str):
+    """
+    Performes environment variables substistution.
+    """
+    str = os.path.expanduser(str)
+    str = os.path.expandvars(str)
+    return str
 
 #================================================================
-# get the path using file name
+# get_program_path : gets program's directory path
+#                    (and performs 'cd' command there) 
 #================================================================
-def get_current_path(file_name):
-    path = "."; where = string.rfind(file_name,'/');
-    if (where != -1):
-        path = (file_name)[: where]
-        os.chdir(path);
-    path = os.getcwd() + "/"
-    return path
+def get_program_path():
+    """
+    Returns the program directory path
+    (and make this directory current).
+    """
+    path = os.path.dirname(sys.argv[0])
+    if path:
+        os.chdir(path)
+    return os.getcwd()
 
 #================================================================
-# checks dir existing 
+# check_dir : checks directory existence
 #================================================================
 def check_dir(dir):
-    if (os.path.islink(dir)) :
-        native_dir = os.readlink(dir)
-        if not os.path.exists(native_dir) :
-            print "Bad link " + native_dir + " to directory " + native_dir + ". The last does not exist."
-            return 0 # problem
-    else :
+    """
+    Checks directory existence.
+    """
+    if (os.path.islink(dir)):
+        realpath = os.path.realpath(dir)
+        if not os.path.exists(realpath):
+            msg = "Invalid link %s.\nThe directory %s a link points to does not exist. Stopped..."%(dir,realpath)
+            error_exit(msg, False)
+    else:
         if not os.path.exists(dir):
-            print "Directory " + dir + " does not exist"
-            return 0
-    return 1
+            msg = "Directory %s does not exist. Stopped..."%dir
+            error_exit(msg, False)
+    pass
 
 #===============================================================
-# Checks the disk space. Exit from interpreter if there is no
-# enough disk space.
+# check_disk_space : checks the disk space;
+#                    quits if there is no enough disk space
 #===============================================================
-def check_disk_space(products, script_dir, target_dir, tmp_dir):
-    import re, string, os
+def check_disk_space(products, scripts_dir, target_dir, tmp_dir, is_force_src=False):
+    """
+    Checks if there is enough disk space to install products.
+    Quits with error if there is no enough disk space.
+    """
     install_space = 0
     temporary_space = 0
-    for product in products :
-        product.install = re.sub(r'^\s+', "", product.install)
-        product.install = re.sub(r'\s+$', "", product.install)
-        
-        if product.disable == "true" or product.install == "use native":
-            continue
-        spaces = string.split( product.installdiskspace,',')
-        prod_space = spaces[0]
-        if (len(spaces) == 2 ) and (product.install == "install binaries") :
-            prod_space = spaces[1]
-        install_space = install_space + string.atoi(prod_space)
-        temporary_space = temporary_space + string.atoi(product.temporarydiskspace)
-    res = os.system(scripts_dir + "checkSize.sh" + " " + target_dir + " " + str(install_space))
-    if res:
-        print "There is no enough space to install the products."
-        return 0
-    
-    res = os.system(scripts_dir + "checkSize.sh" + " " + tmp_dir + " " + str(temporary_space))
+    for product in products:
+        prod_space = 0
+        try:
+            spaces = product.installdiskspace.split(',')
+            prod_space = int( spaces[0] )
+            if product.whattodo == __BINARIES__:
+                prod_space = int( spaces[0] )
+                if product.type == __CTX__COMPONENT__:
+                    prod_space += int( spaces[1] )
+            else:
+                if product.type == __CTX__PREREQUISITE__:
+                    prod_space = int( spaces[0] )
+                else:
+                    prod_space = int( spaces[2] )
+        except:
+            pass
+        install_space = install_space + prod_space
+        pass
+
+    res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", target_dir, install_space))
     if res:
-        print "There is no enough space for tmp directory."
-        return 0
-    
-    return 1
+        msg = "There is no enough space to install the products. Stopped..."
+        error_exit(msg, False)
+    pass
  
+#===============================================================
+# remove_dir : removes temporary directory
+#===============================================================
+def remove_dir(path):
+    """
+    Removes temporary directory.
+    """
+    if path and os.path.exists(path):
+        os.system("rm -rf " + path)
+    pass
 
-#================================================================
-# main
-#================================================================
-    
-if __name__ == "__main__":
-    
-    cur_dir = get_current_path(sys.argv[0])
-   
-    [xml_file, target_dir, tmp_dir, is_gui]  = parse_parameters(sys.argv)
-
-    # define xml file -----------------
-    if (xml_file is None) :
-        xml_file_name = "config.xml"
-        if os.path.exists("/proc/version"):
-            data = open("/proc/version").readline()
-            res = re.search(r'Red\s+Hat\s+\w+(\s+)?(\d[.]\d)', data)
-            if res is not None:
-                num = re.sub("[.]", "_", (res.groups())[1])
-                filename = "config_RedHat" + num+ ".xml"
-                if (os.path.exists(cur_dir + filename)):
-                    xml_file_name = filename
-                
-        xml_file = cur_dir +  xml_file_name
-    if xml_file is None or not os.path.exists(xml_file):
-        error_exit("No xml file is found try to run with options -f <xmlfile>")
+#==============================================================
+# has_binaries : returns True if some product is installed from
+#                binaries
+#===============================================================
+def has_binaries(products):
+    """
+    Returns True if some product is installed in 'binaries' mode.
+    """
+    for product in products:
+        if product.whattodo == __BINARIES__:
+            return True
+    return False
+
+#==============================================================
+# has_sources : returns True if some product is installed from
+#               sources
+#===============================================================
+def has_sources(products):
+    """
+    Returns True if some product is installed in 'sources' mode.
+    """
+    for product in products:
+        if product.whattodo == __BUILDSRC__:
+            return True
+    return False
+
+#==============================================================
+# get_tmp_dir : gets temporary directory name
+#===============================================================
+def get_tmp_dir(dir):
+    """
+    Gets temporary directory path.
+    """
+    max_attempts = 100
+    dir_prefix="INSTALLWORK"
+    range_bottom = 0; range_top = 999999
+    for i in xrange(max_attempts):
+        tmp_dir = "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top))
+        if not os.path.exists( tmp_dir ):
+            return tmp_dir
+    return "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top))
+
+#==============================================================
+# get_os_release : gets OS release; the OS name, version and
+#                  architecture
+#                  For example:
+#                  RedHat, 8.0; Mandriva, 2006.0, 64
+#===============================================================
+def get_os_release():
+    filename = "/etc/issue"
+    # ---
+    plt_name = "unknown"
+    plt_ver  = ""
+    plt_arch = ""   
+    if os.path.exists(filename):
+        # ---
+        f = open(filename)
+        lines = f.readlines()
+        f.close()
+        # ---
+        regvar  = re.compile("(.*)\s+[^\s]*[R|r]elease[^\s]*\s+([\d.]*)")
+        regvar1 = re.compile("(.*)\s+[^\s]*[L|l][I|i][N|n][U|u][X|x][^\s]*(.*)\s+([\d.]*)\s+")
+        regvar2 = re.compile("([A-Za-z]+)\s+([0-9.]+)\s+.*")
+        for l in lines:
+            res = re.search(regvar, l)
+            if not res:
+                res = re.search(regvar1, l)
+            if not res:
+                res = re.search(regvar2, l)
+            if res:
+                plt_name = " ".join(" ".join(res.groups()[:len(res.groups())-1]).split())
+                # workaround for Mandrake and other platforms
+                plt_name = plt_name.replace("Linux", "").replace("linux", "").replace("LINUX", "").strip()
+                # workaround for SuSe
+                plt_name = plt_name.replace("Welcome to", "").strip()
+                # ---
+                plt_name = " ".join(plt_name.split())
+                plt_ver  = res.group(len(res.groups()))
+                if re.search(r'x86_64', l):
+                    plt_arch = "64bit"
+                    pass
+                # workaround for Red Hat Enterprise
+                if not plt_arch:
+                    try:
+                        import platform
+                        if platform.machine() == "x86_64":
+                            plt_arch = "64bit"
+                            pass
+                        pass
+                    except:
+                        pass
+                    pass
+                break
+            pass
+        pass
+
+    return plt_name, plt_ver, plt_arch
+
+#==============================================================
+# get_os_name : gets qualified OS name
+#               For example:
+#               Mandriva 2010.0 64bit
+#===============================================================
+def get_os_name():
+    plt_name, plt_ver, plt_arch = get_os_release()
+    data = []
+    for i in plt_name, plt_ver, plt_arch:
+        if i: data.append(i)
+    return " ".join(data)
+
+#==============================================================
+# check_xml_file : checks XML file existence and readability
+#===============================================================
+def check_xml_file(xml_file):
+    """
+    Checks XML file existence and readability.
+    """
+    if not os.path.isfile(xml_file):
+        msg = "Configuration file %s is not found!"%xml_file
+        error_exit(msg, False)
 
     if not os.access(xml_file, os.R_OK):
-        print "There is no acceess to read "+ xml_file
-        sys.exit(1)
+        msg = "There is no read access for %s file!"%xml_file
+        error_exit(msg, False)
+    pass
+
+#==============================================================
+# get_supported_plts : gets map of supported Linux platforms and
+#                      corresponding configuration files
+#===============================================================
+def get_supported_platforms(xml_file=None):
+    """
+    Gets map of supported Linux platforms and
+    corresponding configuration files.
+    """
+    platforms_map = {}
+    if xml_file:
+        xml_file_list = [xml_file]
+        pass
+    else:
+        xml_file_list = filter(lambda i: i.endswith(".xml"), os.listdir(get_program_path()))
+        while 'config.xml' in xml_file_list: xml_file_list.remove('config.xml')
+        if os.path.exists(os.path.join(get_program_path(), 'config.xml')):
+            xml_file_list.append('config.xml')
+        xml_file_list = [os.path.abspath(i) for i in xml_file_list]
+        pass
+    for an_xml_file in xml_file_list: # XML files parsing
+        check_xml_file(an_xml_file)
+        parser = ConfigParser()
+        parser.parse(an_xml_file)
+        if parser.config.platforms is not None:
+            for plt in parser.config.platforms.split(","):
+                if not plt or plt in platforms_map.keys(): continue
+                platforms_map[strip(plt)] = an_xml_file
+                pass
+            pass
+        pass
+    return platforms_map
+
+#==============================================================
+# Print menu with list of supported platform
+# and return user choice
+#===============================================================
+def select_platform(all_platforms):
+    platforms = all_platforms.keys()
+    platforms.sort()
+    pltname = None
+    while not pltname:
+        print "Please, select any platform from the list below."
+        print "--------------------------"
+        for idx in range(len(platforms)):
+            print " %2d. %s" % (idx+1, " ".join(platforms[idx].split("_")))
+        print "  0. Exit"
+        print "--------------------------"
+        print "Type your choice (%d-%d) and press <Enter>:" % (0, len(platforms)),
+        try:
+            idx = raw_input()
+        except:
+            sys.exit(1)
+        try:
+            idx = int(idx)
+        except:
+            warning("Invalid input!")
+            pass
+        if idx == 0: sys.exit(0)
+        if idx > 0 and idx <= len(platforms):
+            pltname = platforms[idx-1]
+        else:
+            warning("Invalid input!")
+        pass
+    return pltname, all_platforms[pltname]
+
+#==============================================================
+# Check existence of required libraries in system and
+# warn user if some ones are absent
+#===============================================================
+def check_not_found_libs(filepath, optlibs):
+    a_file = open(filepath, 'r')
+    nf_mand_libs = list()
+    nf_opt_libs = list()
+    pref_opt_libs = optlibs.split(",")
+    for line in a_file:
+        line = line.strip()
+        if not line:
+            continue
+        line = line.split(" ")[0]
+        if line in nf_mand_libs or line in nf_opt_libs:
+            continue
+        is_optional = False;
+        for opt_lib in pref_opt_libs:
+            if line.lower().startswith(opt_lib.lower().strip()):
+                is_optional = True
+                break
+        if is_optional:
+            nf_opt_libs.append(line)
+        else:
+            nf_mand_libs.append(line)
+        pass
+
+    msg = "=== WARNING: Some libraries are absent! ===\n"
+    if nf_mand_libs:
+        msg += "One or several MANDATORY libraries listed below are not found. SALOME may not work properly.\n\t"
+        msg += "\n\t".join(nf_mand_libs)
+        msg += "\n"
+    if nf_opt_libs:
+        msg += "One or several OPTIONAL libraries listed below are not found. This does not affect on the correct work of SALOME platform.\n\t"
+        msg += "\n\t".join(nf_opt_libs)
+    if nf_mand_libs or nf_opt_libs:
+        print msg
+    a_file.close()
+    pass
+
+#------------------------------------------------------------------#
+#                                                                  #
+#                    EXECUTION STARTS HERE                         #
+#                                                                  #
+#------------------------------------------------------------------#
+
+if __name__ == "__main__":
+    # get program dir
+    cur_dir = get_program_path()
+    # parse command line
+    [xml_file, target_dir, tmp_dir, is_gui, is_force_src, is_single_dir, pltname] = parse_parameters()
+    if xml_file:   xml_file   = os.path.abspath(xml_file)
+    if target_dir: target_dir = os.path.abspath(target_dir)
+    if tmp_dir:    tmp_dir    = os.path.abspath(tmp_dir)
 
     #---- GUI ----------------
+
     if is_gui : 
         env = os.environ
         if not env.has_key("PATH") :
             env["PATH"] = ""
         if not env.has_key("LD_LIBRARY_PATH") :
-            env["LD_LIBRARY_PATH"]=  ""
+            env["LD_LIBRARY_PATH"] = ""
+
+        env["LD_LIBRARY_PATH"] =  "./bin/lib:" + ".:" + env["LD_LIBRARY_PATH"]
+        env["PATH"] = ".:" + env["PATH"]
+
+        cmd = "./bin/SALOME_InstallWizard"
+        if xml_file is not None:
+            cmd += " --file %s"%xml_file
+        if pltname is not None:
+            cmd += " --platform %s"%pltname
+        if target_dir is not None:
+            cmd += " --target %s"%target_dir
+        if tmp_dir is not None:
+            cmd += " --tmp %s"%tmp_dir
+        if is_force_src:
+            cmd += " --all-from-sources"
+        if is_single_dir:
+            cmd += " --single-directory"
+        cmd += "&"
+        sys.exit(os.system(cmd))
+
+    #-----  TUI ---------------------
+    #
+    # define xml file to be used
+    #
+    # get current Linux platform
+    plt_name, plt_ver, plt_arch = get_os_release()
+    data = []
+    for i in plt_name, plt_ver, plt_arch:
+        if i: data.append(i)
+    full_plt_name = " ".join(data)
+    # get all supported platforms
+    all_platforms = get_supported_platforms(xml_file)
+    if all_platforms:
+        if pltname:
+            # platform name is specified in the command line
+            if pltname in all_platforms:
+                # if specified platform is supported, choose the corresponding XML file for use
+                xml_file = all_platforms[pltname]
+            else:
+                # if specified platform is NOT supported, print warning message
+                # and prompt user to choose another platform
+                msg = "Specified platform is not supported: %s" % (pltname)
+                warning(msg)
+                pltname, xml_file = select_platform(all_platforms)
+                pass
+            pass
+        elif full_plt_name in all_platforms:
+            # if current platform is supported, choose the corresponding XML file for use
+            pltname  = full_plt_name
+            xml_file = all_platforms[pltname]
+        else:
+            if xml_file and len(all_platforms) == 1:
+                # XML file is specified and contains only one platform definition
+                xml_file = all_platforms.values()[0]
+                pltname  = all_platforms.keys()[0]
+            else:
+                # current Linux platform is not supported, print warning message
+                # and prompt user to choose platform from the list
+                warning("Not supported Linux platform: %s."%" ".join(data))
+                pltname, xml_file = select_platform(all_platforms)
+            pass
+        pass
+    else:
+        # current Linux platform is not supported, exit
+        if pltname:
+            msg = "Not supported Linux platform: %s."%pltname
+        else:
+            msg = "Not supported Linux platform: %s."%" ".join(data)
+        error_exit(msg, False)
+        pass
 
-        env["LD_LIBRARY_PATH"] =  ".:" +  env["LD_LIBRARY_PATH"]
-        env["PATH"] = ".:"+ env["PATH"]
+    # parse XML file -----------
+    message("Parsing XML configuration file: %s"%xml_file)
+    parser = ConfigParser(is_force_src, pltname)
+    parser.parse(xml_file)
 
-        sys.exit(os.system("cd " + cur_dir + "; ./bin/SALOME_InstallWizard " + xml_file +"&"))
-        
-        
+    # source directory map
+    bin_dir = ""
+    if parser.config.platforms:
+        bin_dir += "/%s"%"_".join( parser.pltname.split() )
+    subdir = { __BINARIES__   : "BINARIES" + bin_dir,
+               __BUILDSRC__   : "SOURCES",
+               __PREINSTALL__ : ""}
 
-    #-----  TUI ---------------------
+    # check scripts directory -----------
+    scripts_dir = "%s/%s"%(cur_dir, "config_files")
+    check_dir(scripts_dir)
 
-    #print xml_file, target_dir, tmp_dir, is_gui
-    
-    filehandle = open(xml_file)
-    data = filehandle.read()
-    filehandle.close()
-    parser = ConfigParser()
-    parser.feed(data)
-    parser.close()
-
-    # definitions :
-    # map
-    what_to_do = { "install sources":"install_source",
-                   "install binaries":"install_binary",
-                   "use native":"try_native"}
-    # define tmp dir  -----------
-    if tmp_dir is None:
-        tmp_dir = parser.path.tmpdir
-    root_path = ""
-    if not os.path.exists(tmp_dir):
-        print "Creating " + tmp_dir; root_path = create_dir(tmp_dir) ; 
-        import random
-        tmp_dir = tmp_dir + "/INSTALLWORK" + str(random.randint(10000,100000))
-        create_dir(tmp_dir,0755)
-        if not os.path.exists(tmp_dir):
-            error_exit("There is no tmp directory " + tmp_dir + ". Use -tmp key to set directory or correct xml file\n\n")
+    # check products archives directories -----------
+    has_bin = has_binaries(parser.products)
+    has_src = has_sources(parser.products)
+    source_dir = "%s/%s"%(cur_dir, "Products")
 
-    if not os.access(tmp_dir, os.W_OK) :
-        str = "We have no write permissions for directory " + tmp_dir + ". Use -tmp key to set directory or correct xml file"
-        error_exit(str)
-        
-    # define target dir  --------
+    if has_src or has_bin:
+        check_dir(source_dir)
+
+    if has_src:
+        check_dir("%s/%s"%(source_dir,subdir[__BUILDSRC__]))
+
+    if has_bin:
+        check_dir("%s/%s"%(source_dir,subdir[__BINARIES__]))
+
+    # check/create target dir -----------
     if target_dir is None:
-        target_dir = parser.path.targetdir
+        target_dir = parser.config.targetdir
+    target_dir = substituteVars(target_dir)
+
+    message("Creating target directory: " + target_dir)
+    create_dir(target_dir, 0755)
 
     if not os.path.exists(target_dir):
-        print "Creating " + target_dir; create_dir(target_dir, 0755)
-        if not os.path.exists(target_dir):
-            error_exit("There is no target directory " + target_dir + ". Use -t key to set directory or correct xml file\n\n")
+        error_exit("Invalid target directory: " + target_dir)
 
     if not os.access(target_dir, os.W_OK) :
-        str = "We have no write permissions for directory " + target_dir + ". Use -t key to set directory or correct xml file"
-        error_exit(str)
-    
+        error_exit("There is no write permissions for the directory: " + target_dir)
 
-    # define products dir ------------
-    source_dir =  cur_dir + "Products" ; 
-    if not check_dir(source_dir):
-        if len(root_path) and os.path.exists(root_path):
-            os.system("rm -r -f "+ root_path)
-        sys.exit(1)
-       
-    subdir = {"install sources"  : "SOURCES",
-              "install binaries" : "BINARIES/"+parser.config.os,
-              "use native": ""}
-
-
-    #  define scripts dir ------------
-    scripts_dir = cur_dir + "config_files/"
-    if not check_dir(scripts_dir):
-        if len(root_path) and os.path.exists(root_path):
-            os.system("rm -r -f "+ root_path)
-        sys.exit(1)
-    os.chdir(scripts_dir)
+    # check/create temporary dir -----------
+    if tmp_dir is None:
+        tmp_dir = parser.config.tmpdir
+    if not tmp_dir:
+        tmp_dir = "/tmp"
+    tmp_dir = substituteVars(tmp_dir)
+    tmp_dir = get_tmp_dir(tmp_dir)
+
+    message("Creating temporary directory: " + tmp_dir)
+    root_path = create_dir(tmp_dir, 0755)
+   
+    if not os.path.exists(tmp_dir):
+        error_exit("Invalid temporary directory: " + tmp_dir)
 
-    list_of_dep =  create_levels(parser.products)
-    #list_of_dep =  get_dependencies_set(parser.products)
+    if not os.access(tmp_dir, os.W_OK) :
+        error_exit("There is no write permissions for the directory: " + tmp_dir)
+        
+    # check available disk space -----------
+    message("Checking available disk space")
+    check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir, is_force_src)
 
-    if check_disk_space(parser.products, scripts_dir, target_dir, tmp_dir) :
-        for product in parser.products :
+    # change current directory -----------
+    os.chdir(scripts_dir)
 
-            if product.disable == "true": continue
+    # get dependencies list -----------
+    list_of_dep = get_dependencies(parser.products)
+    products_string = " ".join(parser.full_prods_list)
 
-            cmd = scripts_dir +  product.script + " " + \
-                  what_to_do[product.install]+ " " + \
-                  tmp_dir + " " + \
-                  source_dir + "/" + subdir[product.install] + " " + \
-                  target_dir + " " + \
-                  '"' + list_of_dep + '"' + " " + \
-                  product.name
+    # don't remove sources and tmp files, by default -----------
+    rm_src_tmp = "FALSE"
 
+    # starting -----------
+    message("Starting ...")
+    
+    # install products -----------
+    for product in parser.products:
+        # remove only prerequisites temporary files
+        if product.type == __CTX__PREREQUISITE__ or \
+           (product.type == __CTX__COMPONENT__ and product.whattodo == __BUILDSRC__):
+            rm_src_tmp = "TRUE"
+        message("... processing %s ..."%product.name)
+        cmd = '%s/%s %s %s %s/%s %s "%s" %s "%s" %s/%s %s %s/%s' % (
+            scripts_dir, product.script,
+            product.whattodo,
+            tmp_dir,
+            source_dir, subdir[product.whattodo],
+            target_dir,
+            products_string,
+            product.name,
+            products_string,
+            source_dir, subdir[__BUILDSRC__],
+            rm_src_tmp,
+            source_dir, subdir[__BINARIES__]
+            )
+        # install all modules with GUI
+        if product.woguiinst is not None and product.woguiinst != "":
+           cmd += ' TRUE'
+        # use single directory or not
+        if product.whattodo == __BINARIES__ and product.type == __CTX__COMPONENT__ and is_single_dir:
+            cmd += ' TRUE'
+        res = os.system(cmd)
+        rm_src_tmp = "FALSE"
+        pass
+
+    # pickup environment -----------
+    message("Creating environment files")
+    for product in parser.products :
+        if check_bool(product.pickupEnv):
+            cmd = '%s/%s pickup_env %s %s/%s %s "%s" %s "%s" %s/%s %s %s/%s' % (
+                scripts_dir, product.script,
+                tmp_dir,
+                source_dir, subdir[product.whattodo],
+                target_dir,
+                products_string,
+                product.name,
+                products_string,
+                source_dir, subdir[__BUILDSRC__],
+                rm_src_tmp,
+                source_dir, subdir[__BINARIES__]
+                )
+            # install all modules with GUI
+            if product.woguiinst is not None and product.woguiinst != "":
+               cmd += ' TRUE'
+            # use single directory or not
+            if product.whattodo == __BINARIES__ and product.type == __CTX__COMPONENT__ and is_single_dir:
+                cmd += ' TRUE'
             res = os.system(cmd)
-            if res : break;
+            pass
+        pass
 
-    if len(root_path) and os.path.exists(root_path):
-        os.system("rm -r -f "+ root_path)
+    if not is_force_src:
+        if is_single_dir:
+            # modify *.la files, if --single-directory option was pointed -----------
+            message("Modifying of *.la files of SALOME modules...")
+            cmd = '%s/modifyLaFiles.sh modify_la_files %s' % (scripts_dir, target_dir)
+            res = os.system(cmd)
+        else:
+            # check that all required libraries are in system
+            message("Check existence of Fortran and other required libraries...")
+            cmd = '%s/checkFortran.sh find_libraries %s > %s/not_found_libs.txt' % (scripts_dir, target_dir, tmp_dir)
+            if os.system(cmd):
+                check_not_found_libs("%s/not_found_libs.txt" % (tmp_dir), parser.config.optlibs)
+
+    # clean temporary directory -----------
+    message("Cleaning temporary directory")
+    clean_all()
+    
+    # finishing -----------
+    message("Finished!")
+    pass