def __init__(self, module):
        '''
        Constructor
        '''
        
        ActionBundle.__init__(self, module)
        
        # Check if JBOSS is running
        if getProcessPIDByPath(module.targetDeploymentPath):die("The JBOSS server at '" + module.targetDeploymentPath + "' is up. Installation will not continue")    
        
        # Generate a unique ActionBundle execution id
        guid = generateGUID()    
        log.info("Unique ActionBundle execution ID generated: " + guid)    

        # Prepare directory to unpack package
        module.subModule.unzippedPackagePath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "unzippedPackage")
        
        # Extract MS Admin package into tmp dir
        ExtractZipToDir(module.moduleFilename, module.subModule.unzippedPackagePath)    

        # Prepare directory to unpack package
        module.subModule.previousVersionBackupPath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "previousVersionBackup")        

        # Extract new MANIFEST.MF
        ExtractFileFromZipToDir(module.subModule.unzippedPackagePath + scriptGlobals.osDirSeparator + module.subModule.relativeWarPath, module.relativeVersionInformationPath, module.subModule.unzippedPackagePath)    

        # Prepare directory to keep backups
        # Since MS is deployed on JBOSS some paths have an %s to allow a configurable 
        # profile, so do a little sprintf to fix them
        sprintfOnDictionaryValues(module.relativeConfigurationFiles, module.targetDeploymentProfile)
        sprintfOnDictionaryValues(module.relativeCopyableFilesOrFolders, module.targetDeploymentProfile)
    def __init__(self, module):
        '''
        Constructor
        '''
        ActionBundle.__init__(self, module)
        
        # Generate a unique ActionBundle execution id
        guid = generateGUID()
        log.info("Unique ActionBundle execution ID generated: " + guid)
        
        # Check if JBOSS is running
        if getProcessPIDByPath(module.targetDeploymentPath): die("The JBOSS server at '" + module.targetDeploymentPath + "' is up. Installation will not continue")        
        
        # Prepare directory to unpack package
        unzippedPackagePath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "unzippedPackage")
        
        # Since Builder is deployed on JBOSS some paths have an %s to allow a configurable 
        # profile, so do a little sprintf to fix them
        sprintfOnDictionaryValues(module.relativeConfigurationFiles, module.targetDeploymentProfile) 
        sprintfOnDictionaryValues(module.relativeCopyableFilesOrFolders, module.targetDeploymentProfile)
        sprintfOnListValues(module.subModule.relativeCleanUpFiles, module.targetDeploymentProfile)
        
        # Extract Builder package into tmp dir
        ExtractZipToDir(module.moduleFilename, unzippedPackagePath)
        
    
        # Do this again in case new settings have been added
        # Configure m-web-builder.properties using envprops
        # Configure mgage.properties using envprops
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            ConfigureTemplateFile(module.name, lib.OptParser.options.envprops, exactExtractedLocation)
            CheckFileConfigurationIsComplete(exactExtractedLocation)
        
        
        # Copy m-web-builder.properties to conf
        # Copy mgage.properties to conf
        # Copy jboss-log4j.xml to conf
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v 
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation)       

        # Clean up files that might have been left over from previous manuall installations
        cleanUp(module)
        
        # Copy artifacts to profile
        for k, v in module.relativeCopyableFilesOrFolders.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v 
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation)
                
        # Install Plugins    
        staticFolder = readPropertyFromPropertiesFile("STATIC_FOLDER", module.name, lib.OptParser.options.envprops)  
        installDefaultPlugins(staticFolder, unzippedPackagePath, module)
    def __init__(self, module):
        """
        Constructor
        """
        ActionBundle.__init__(self, module)

        # CRM is a JBOSS webapp. Some paths have an %s to allow a configurable profile, so do a little sprintf to fix them
        sprintfOnDictionaryValues(module.relativeConfigurationFiles, module.targetDeploymentProfile)
        sprintfOnDictionaryValues(module.relativeCopyableFilesOrFolders, module.targetDeploymentProfile)
        sprintfOnDictionaryValues(module.relativeBackupOnlyFilesOrFolders, module.targetDeploymentProfile)
    def __init__(self, module):
        """
        Constructor
        """
        # Initialize application server object
        appServer = ApplicationServer(module, scriptGlobals.appsrvProperties)

        # Check if JBOSS is running
        if getProcessPIDByPathAndIdentifier(module.targetDeploymentPath, appServer.processIdentifier):
            die("The JBOSS server at '" + module.targetDeploymentPath + "' is up. Installation will not continue")

        # Since CRM is deployed on JBOSS some paths have an %s to allow a configurable
        # profile, so do a little sprintf to fix them
        sprintfOnDictionaryValues(module.relativeConfigurationFiles, module.targetDeploymentProfile)
        sprintfOnDictionaryValues(module.relativeCopyableFilesOrFolders, module.targetDeploymentProfile)

        # Prepare directory to keep backups
        previousVersionBackupPath = createDirectoriesRecursively(
            scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "previousVersionBackup"
        )

        # Backup crm-deployment.properties from conf
        # Backup mgage.properties from conf
        # Backup jboss-log4j.xml from conf
        for k, v in module.relativeConfigurationFiles.items():
            exactLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            exactBackupLocation = previousVersionBackupPath + scriptGlobals.osDirSeparator + k
            copyDirOrFile(exactLocation, exactBackupLocation)  # we do not to have do/undo actions for such operation

        # Backup crm-dtds from docs/dtd
        # Backup crm.war from deploy
        # Backup esb.jar from deploy/
        # Backup ROOT.WAR/crossdmain.xml from deploy/ROOT.WAR
        for k, v in module.relativeCopyableFilesOrFolders.items():
            exactLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            exactBackupLocation = previousVersionBackupPath + scriptGlobals.osDirSeparator + k
            copyDirOrFile(exactLocation, exactBackupLocation)  # we do not to have do/undo actions for such operation

        # Prepare directory to unpack package
        unzippedPackagePath = createDirectoriesRecursively(
            scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "unzippedPackage"
        )

        # Extract CRM package into tmp dir
        ExtractZipToDir(module.moduleFilename, unzippedPackagePath)

        # Determine last executed script in DB
        dbUsername = readPropertyFromPropertiesFile("VNA_CRM_USERNAMEBASE", module.name, lib.OptParser.options.envprops)
        dbPassword = readPropertyFromPropertiesFile("VNA_CRM_PASSWORDBASE", module.name, lib.OptParser.options.envprops)

        tmpC = readPropertyFromPropertiesFile("DBConnectionString", module.name, lib.OptParser.options.envprops)

        # If string is Clustered string
        if tmpC.lower().find("description") > 0:
            dbConnectionString = tmpC
        else:
            dbHost = tmpC[0 : tmpC.find(":")]
            dbPort = tmpC[tmpC.find(":") + 1 : tmpC.rfind(":")]
            dbSID = tmpC[tmpC.rfind(":") + 1 : len(tmpC)]
            dbConnectionString = (
                "(DESCRIPTION=(LOAD_BALANCE=yes)(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=%s))(CONNECT_DATA=(SID=%s)))"
                % (dbHost, dbPort, dbSID)
            )

        finalConnectionString = "%s/%s@%s" % (dbUsername, dbPassword, dbConnectionString)

        result = runOracleScript(
            "SELECT EXECUTED_SCRIPT FROM FIREWORKS_SCRIPT_LOG WHERE EXECUTED_ON IN (SELECT MAX(EXECUTED_ON) FROM FIREWORKS_SCRIPT_LOG);",
            finalConnectionString,
            False,
            True,
        )
        lastExecutedPath, lastExecutedFilename = os.path.split(result.strip())

        currentVersion = grepFile(
            module.versionInformationRegex,
            previousVersionBackupPath + scriptGlobals.osDirSeparator + module.relativeVersionInformationPath,
        )
        newVersion = grepFile(
            module.versionInformationRegex,
            unzippedPackagePath + scriptGlobals.osDirSeparator + module.relativeVersionInformationPath,
        )
        currentRevision = grepFile(
            module.revisionInformationRegex,
            previousVersionBackupPath + scriptGlobals.osDirSeparator + module.relativeVersionInformationPath,
        )
        newRevision = grepFile(
            module.revisionInformationRegex,
            unzippedPackagePath + scriptGlobals.osDirSeparator + module.relativeVersionInformationPath,
        )

        currentVersion = (currentVersion.replace(module.versionInformationRegex, "")).strip()
        newVersion = (newVersion.replace(module.versionInformationRegex, "")).strip()
        currentRevision = (currentRevision.replace(module.revisionInformationRegex, "")).strip()
        newRevision = (newRevision.replace(module.revisionInformationRegex, "")).strip()
        currentDirSize = getDirectoryRecursiveSize(previousVersionBackupPath)
        newDirSize = getDirectoryRecursiveSize(unzippedPackagePath)

        # Information Header
        log.info(informationAsciiHeader())

        labels = ("", "Currently Installed Module", "Module To Be Installed")
        data = """Version, %s, %s
           Revision, %s, %s
           Dir Size, %s, %s           
        """ % (
            currentVersion,
            newVersion,
            currentRevision,
            newRevision,
            currentDirSize,
            newDirSize,
        )

        rows = [row.strip().split(",") for row in data.splitlines()]
        log.info("\n\n" + indent([labels] + rows, hasHeader=True))
        log.info("Last script executed on '" + finalConnectionString + "' was '" + lastExecutedFilename + "'")
    def __init__(self, module):
        """
        Constructor
        """
        ActionBundle.__init__(self, module)

        # Initialize application server object
        appServer = ApplicationServer(module, scriptGlobals.appsrvProperties)

        # Generate a unique ActionBundle execution id
        guid = generateGUID()
        log.info("Unique ActionBundle execution ID generated: " + guid)

        # Since MSM is deployed on JBOSS some paths have an %s to allow a configurable
        # profile, so do a little sprintf to fix them
        sprintfOnDictionaryValues(module.relativeConfigurationFiles, module.targetDeploymentProfile)
        sprintfOnDictionaryValues(module.relativeCopyableFilesOrFolders, module.targetDeploymentProfile)

        # For JbosswebappPath = "/server/" + module.targetDeploymentProfile + "/deploy/" + module.subModule.name + ".war"
        # for Tomcat webappPath =  "/webapps/" + module.subModule.name
        webappPath = "/webapps/" + module.subModule.name

        # Check if module exists.
        for k, v in module.relativeCopyableFilesOrFolders.items():
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            if exactTargetLocation.find(webappPath) != -1:
                if not os.path.isdir(exactTargetLocation):
                    die(
                        "\n\n"
                        + module.subModule.name
                        + " is not installed under:"
                        + module.targetDeploymentPath
                        + ". Please first run a clean installation"
                    )

        # Get Previous Hudson data
        previousManifilePath = module.targetDeploymentPath + webappPath + "/META-INF/MANIFEST.MF"
        previousVersionInfo = grepFile(module.versionInformationRegex, previousManifilePath)
        previousBuildInfo = grepFile(module.buildInformationRegex, previousManifilePath)
        previousRevisionInfo = grepFile(module.revisionInformationRegex, previousManifilePath)
        previousRevisionInfo = (previousRevisionInfo.replace(module.revisionInformationRegex, "")).strip()
        previousVersionInfo = (previousVersionInfo.replace(module.versionInformationRegex, "")).strip()
        if previousBuildInfo != None:
            previousBuildInfo = (previousBuildInfo.replace(module.buildInformationRegex, "")).strip()

        # Construct the email notification
        emailSender = readPropertyFromPropertiesFileWithFallback(
            "emailNotificationSenderAddress",
            scriptGlobals.scriptVarSectionName,
            lib.OptParser.options.envprops,
            scriptGlobals.emailNotificationSenderAddress,
        )
        emailRecipients = scriptGlobals.globalNotificationEmailList
        emailSubject = (
            "MSM Installation: "
            + module.subModule.name
            + "@"
            + getCurrentHostname()
            + " ("
            + module.friendlyServerName
            + ")"
        )
        emailText = detailedCleanInstallationReportTemplate(
            module.subModule.name,
            previousVersionInfo,
            lib.OptParser.options.action,
            getCurrentHostname(),
            os.getcwd(),
            guid,
            " ".join(platform.uname()),
            getpass.getuser(),
            previousBuildInfo,
            previousRevisionInfo,
            lib.OptParser.options.envprops,
            scriptGlobals.workingDir,
        )

        # Email all required parties
        SendEmail(emailSender, emailRecipients, emailSubject, emailText, scriptGlobals.smtpHost, scriptGlobals.smtpPort)
    def __init__(self, module):
        """
        Constructor
        """
        ActionBundle.__init__(self, module)

        # Initialize application server object
        appServer = ApplicationServer(module, scriptGlobals.appsrvProperties)

        # Generate a unique ActionBundle execution id
        guid = generateGUID()
        log.info("Unique ActionBundle execution ID generated: " + guid)

        # Check if Tomcat is running
        if getProcessPIDByPathAndIdentifier(module.targetDeploymentPath, appServer.processIdentifier):
            die("\n\nThe Jboss server at '" + module.targetDeploymentPath + "' is up. Installation will not continue")

        # Since MSM is deployed on JBOSS some paths have an %s to allow a configurable
        # profile, so do a little sprintf to fix them
        sprintfOnDictionaryValues(module.relativeConfigurationFiles, module.targetDeploymentProfile)
        sprintfOnDictionaryValues(module.relativeCopyableFilesOrFolders, module.targetDeploymentProfile)

        # For JbosswebappPath = "/server/" + module.targetDeploymentProfile + "/deploy/" + module.subModule.name + ".war"
        # for Tomcat webappPath =  "/webapps/" + module.subModule.name
        webappPath = "/webapps/" + module.subModule.name
        # Check if module exists.
        for k, v in module.relativeCopyableFilesOrFolders.items():
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            if exactTargetLocation.find(webappPath) != -1:
                if os.path.isdir(exactTargetLocation):
                    log.info(
                        "\n##############################################################\n"
                        + module.subModule.name
                        + " is already installed under:"
                        + module.targetDeploymentPath
                        + ". Please manually backup and remove to run a clean installation (unless you want to update)\n##############################################################"
                    )
                    die()

        # Prepare directory to unpack package
        unzippedPackagePath = createDirectoriesRecursively(
            scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "unzippedPackage"
        )

        # Extract MSM package into tmp dir
        ExtractZipToDir(module.moduleFilename, unzippedPackagePath)
        CreateDirectory(unzippedPackagePath + "/bin/" + module.subModule.name)
        ExtractZipToDir(
            unzippedPackagePath + "/bin/" + module.subModule.name + ".war",
            unzippedPackagePath + "/bin/" + module.subModule.name,
        )

        # Configure xxx.properties in tmp/../conf using envprops
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            ConfigureTemplateFile(module.name, lib.OptParser.options.envprops, exactExtractedLocation)
            CheckFileConfigurationIsComplete(exactExtractedLocation)

        # Copy relativeCopyableFilesOrFolders to specified locations on Server (values)
        for k, v in module.relativeCopyableFilesOrFolders.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation)

        # Copy tmp/../conf/xxx.properties to to specified locations on Server (values)
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation)

        # Find version/revision info
        revisionInfo = grepFile(
            module.revisionInformationRegex,
            unzippedPackagePath + scriptGlobals.osDirSeparator + module.relativeVersionInformationPath,
        )
        revisionInfo = (revisionInfo.replace(module.revisionInformationRegex, "")).strip()
        versionInfo = grepFile(
            module.versionInformationRegex,
            unzippedPackagePath + scriptGlobals.osDirSeparator + module.relativeVersionInformationPath,
        )
        versionInfo = (versionInfo.replace(module.versionInformationRegex, "")).strip()
        buildInfo = grepFile(
            module.buildInformationRegex,
            unzippedPackagePath + scriptGlobals.osDirSeparator + module.relativeVersionInformationPath,
        )
        if buildInfo != None:
            buildInfo = (buildInfo.replace(module.buildInformationRegex, "")).strip()

        # Run CREATE/UPDATE/UPGRADE script
        if module.subModule.installUpdateScript != "":
            path1 = module.targetDeploymentPath + webappPath + "/" + module.subModule.installUpdateScript
            ChangePathPermissions(path1, 0744)
            path1 = path1 + " CREATE YES "
            ExecuteOSCommand(path1, None)

        # Construct the email notification
        emailSender = readPropertyFromPropertiesFileWithFallback(
            "emailNotificationSenderAddress",
            scriptGlobals.scriptVarSectionName,
            lib.OptParser.options.envprops,
            scriptGlobals.emailNotificationSenderAddress,
        )
        emailRecipients = scriptGlobals.globalNotificationEmailList
        emailSubject = (
            "MSM Installation: "
            + module.subModule.name
            + "@"
            + getCurrentHostname()
            + " ("
            + module.friendlyServerName
            + ")"
        )
        emailText = detailedCleanInstallationReportTemplate(
            module.subModule.name,
            versionInfo,
            lib.OptParser.options.action,
            getCurrentHostname(),
            os.getcwd(),
            guid,
            " ".join(platform.uname()),
            getpass.getuser(),
            buildInfo,
            revisionInfo,
            lib.OptParser.options.envprops,
            scriptGlobals.workingDir,
        )

        # Email all required parties
        SendEmail(emailSender, emailRecipients, emailSubject, emailText, scriptGlobals.smtpHost, scriptGlobals.smtpPort)
    def __init__(self, module):
        """
        Constructor
        """
        ActionBundle.__init__(self, module)

        # Initialize application server object
        appServer = ApplicationServer(module, scriptGlobals.appsrvProperties)

        # Generate a unique ActionBundle execution id
        guid = generateGUID()
        log.info("Unique ActionBundle execution ID generated: " + guid)

        # Check if Tomcat is running
        if getProcessPIDByPathAndIdentifier(module.targetDeploymentPath, appServer.processIdentifier):
            die("\n\nThe Jboss server at '" + module.targetDeploymentPath + "' is up. Installation will not continue")

        # Since MSM is deployed on JBOSS some paths have an %s to allow a configurable
        # profile, so do a little sprintf to fix them
        sprintfOnDictionaryValues(module.relativeConfigurationFiles, module.targetDeploymentProfile)
        sprintfOnDictionaryValues(module.relativeCopyableFilesOrFolders, module.targetDeploymentProfile)

        # For JbosswebappPath = "/server/" + module.targetDeploymentProfile + "/deploy/" + module.subModule.name + ".war"
        # for Tomcat webappPath =  "/webapps/" + module.subModule.name
        webappPath = "/webapps/" + module.subModule.name

        # Check if module exists.
        for k, v in module.relativeCopyableFilesOrFolders.items():
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            if exactTargetLocation.find(webappPath) != -1:
                if not os.path.isdir(exactTargetLocation):
                    die(
                        "\n\n"
                        + module.subModule.name
                        + " is not installed under:"
                        + module.targetDeploymentPath
                        + ". Please first run a clean installation"
                    )

        # Get Previous Hudson data
        previousManifilePath = module.targetDeploymentPath + webappPath + "/META-INF/MANIFEST.MF"
        previousVersionInfo = grepFile(module.versionInformationRegex, previousManifilePath)
        previousBuildInfo = grepFile(module.buildInformationRegex, previousManifilePath)
        previousRevisionInfo = grepFile(module.revisionInformationRegex, previousManifilePath)
        previousVersionInfo = (previousVersionInfo.replace(module.versionInformationRegex, "")).strip()
        if previousBuildInfo != None:
            previousBuildInfo = (previousBuildInfo.replace(module.buildInformationRegex, "")).strip()

        previousRevisionInfo = (previousRevisionInfo.replace(module.revisionInformationRegex, "")).strip()

        # Prepare directory to keep backups
        previousVersionBackupPath = createDirectoriesRecursively(
            scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "previousVersionBackup"
        )

        # Backup webapps
        if lib.OptParser.action != "install-nodb-nobackup":
            for k, v in module.relativeCopyableFilesOrFolders.items():
                exactLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
                exactBackupLocation = previousVersionBackupPath + scriptGlobals.osDirSeparator + k
                CopyDirOrFile3(exactLocation, exactBackupLocation)

        # Prepare directory to unpack package
        unzippedPackagePath = createDirectoriesRecursively(
            scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "unzippedPackage"
        )

        # Extract MSM package into tmp dir
        ExtractZipToDir(module.moduleFilename, unzippedPackagePath)
        CreateDirectory(unzippedPackagePath + "/bin/" + module.subModule.name)
        ExtractZipToDir(
            unzippedPackagePath + "/bin/" + module.subModule.name + ".war",
            unzippedPackagePath + "/bin/" + module.subModule.name,
        )

        # Configure xxx.properties in tmp/../conf using envprops
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            ConfigureTemplateFile(module.name, lib.OptParser.options.envprops, exactExtractedLocation)
            CheckFileConfigurationIsComplete(exactExtractedLocation)

        # Copy tmp/../conf/xxx.properties to to specified locations on Server (values)
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation)

        # Construct the email notification
        emailSender = readPropertyFromPropertiesFileWithFallback(
            "emailNotificationSenderAddress",
            scriptGlobals.scriptVarSectionName,
            lib.OptParser.options.envprops,
            scriptGlobals.emailNotificationSenderAddress,
        )
        emailRecipients = scriptGlobals.globalNotificationEmailList
        emailSubject = (
            "MSM Installation: "
            + module.subModule.name
            + "@"
            + getCurrentHostname()
            + " ("
            + module.friendlyServerName
            + ")"
        )
        emailText = detailedUpdateInstallationReportTemplate(
            module.subModule.name,
            previousVersionInfo,
            lib.OptParser.options.action,
            getCurrentHostname(),
            os.getcwd(),
            guid,
            " ".join(platform.uname()),
            getpass.getuser(),
            previousBuildInfo,
            previousRevisionInfo,
            lib.OptParser.options.envprops,
            previousVersionInfo,
            previousBuildInfo,
            previousRevisionInfo,
            scriptGlobals.workingDir,
        )

        # Email all required parties
        SendEmail(emailSender, emailRecipients, emailSubject, emailText, scriptGlobals.smtpHost, scriptGlobals.smtpPort)
    def __init__(self, module):
        '''
        Constructor
        '''
        ActionBundle.__init__(self, module)
        euclidModule = module.subModule
        
        # Generate a unique ActionBundle execution id
        guid = generateGUID()
        log.info("Unique ActionBundle execution ID generated: " + guid)
        
        # Check if JBOSS is running
        if getProcessPIDByPath(module.targetDeploymentPath): die("The JBOSS server at '" + module.targetDeploymentPath + "' is up. Installation will not continue")        
        
        # Prepare directory to unpack package
        unzippedPackagePath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "unzippedPackage")
        
        # Prepare backup directory
        backupPath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "backup")
        
        # Prepare explode wars directory
        explodePath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "explode")        
        
        # Prepare configuration directory
        configDirectoryPath = createDirectoriesRecursively(euclidModule.euclidConfigDir)
        
        # Since Euclid is deployed on JBOSS some paths have an %s to allow a configurable 
        # config dir, so do a little sprintf to fix them
        sprintfOnDictionaryValues(module.relativeConfigurationFiles, module.targetDeploymentProfile) 
        sprintfOnDictionaryValues(euclidModule.relativeMergableConfigurationFiles, euclidModule.euclidConfigDir)
        # Since Euclid is deployed on JBOSS some paths have an %s to allow a configurable 
        # server profile, so do a little sprintf to fix them   
        sprintfOnDictionaryValues(module.relativeCopyableFilesOrFolders, module.targetDeploymentProfile) 
        sprintfOnDictionaryValues(euclidModule.relativeWarsToBeExploded, module.targetDeploymentProfile)

        # Extract package into tmp dir
        ExtractZipToDir(module.moduleFilename, unzippedPackagePath)
        
        # Configure relativeConfigurationFiles
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            ConfigureTemplateFile(module.name, lib.OptParser.options.envprops, exactExtractedLocation)
            replaceInsensitiveStringInFile("${CREATE_SCHEMA}", "true", exactExtractedLocation)
            CheckFileConfigurationIsComplete(exactExtractedLocation)
        
        # Configure relativeMergableConfigurationFiles
        for k, v in euclidModule.relativeMergableConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            ConfigureTemplateFile(module.name, lib.OptParser.options.envprops, exactExtractedLocation)
            replaceInsensitiveStringInFile("${CREATE_SCHEMA}", "true", exactExtractedLocation)
            CheckFileConfigurationIsComplete(exactExtractedLocation)
        
        # Explode wars
#        for k, v in euclidModule.relativeWarsToBeExploded.items():
#            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
#            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
#            backupFileOrDirIfExists(exactTargetLocation,backupPath)
#            ExtractZipToDir(exactExtractedLocation, exactTargetLocation)
        for k, v in euclidModule.relativeWarsToBeExploded.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            i = rfind(k, scriptGlobals.osDirSeparator)
            if i > -1: 
                tmpExplodeWarLocation = explodePath + scriptGlobals.osDirSeparator + k[i+1:]
            else:
                tmpExplodeWarLocation = explodePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            backupFileOrDirIfExists(exactTargetLocation,backupPath)
            createDirectoriesRecursively(tmpExplodeWarLocation)
            ExtractZipToDir(exactExtractedLocation, tmpExplodeWarLocation)
            AltMoveDirOrFile(tmpExplodeWarLocation,exactTargetLocation)
            
        # Copy config files
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v 
            backupFileOrDirIfExists(exactTargetLocation,backupPath)
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation) 
        # Copy mergable config files (no need to merge on clean install)
        for k, v in euclidModule.relativeMergableConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = v 
            backupFileOrDirIfExists(exactTargetLocation,backupPath)
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation)       
        # Copy other files
        for k, v in module.relativeCopyableFilesOrFolders.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v 
            backupFileOrDirIfExists(exactTargetLocation,backupPath)
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation)
    def __init__(self, module):
        '''
        Constructor
        '''
        ActionBundle.__init__(self, module)
        euclidModule = module.subModule
        
        # Generate a unique ActionBundle execution id
        guid = generateGUID()
        log.info("Unique ActionBundle execution ID generated: " + guid)
        
        # Check if JBOSS is running
        if getProcessPIDByPath(module.targetDeploymentPath): die("The JBOSS server at '" + module.targetDeploymentPath + "' is up. Installation will not continue")        
        
        # Prepare directory to unpack package
        unzippedPackagePath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "unzippedPackage")
        
        # Prepare backup directory
        backupPath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "backup")
        
        # Prepare explode wars directory
        explodePath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "explode")
        
        # Prepare configuration directory
        configDirectoryPath = createDirectoriesRecursively(euclidModule.euclidConfigDir)
        
        # Since Euclid is deployed on JBOSS some paths have an %s to allow a configurable 
        # config dir, so do a little sprintf to fix them
        sprintfOnDictionaryValues(module.relativeConfigurationFiles, module.targetDeploymentProfile) 
        sprintfOnDictionaryValues(euclidModule.relativeMergableConfigurationFiles, euclidModule.euclidConfigDir)
        # Since Euclid is deployed on JBOSS some paths have an %s to allow a configurable 
        # server profile, so do a little sprintf to fix them   
        sprintfOnDictionaryValues(module.relativeCopyableFilesOrFolders, module.targetDeploymentProfile) 
        sprintfOnDictionaryValues(euclidModule.relativeWarsToBeExploded, module.targetDeploymentProfile)

        # Extract package into tmp dir
        ExtractZipToDir(module.moduleFilename, unzippedPackagePath)
        
        versionTmpPath = createDirectoriesRecursively(scriptGlobals.workingDir + scriptGlobals.osDirSeparator + "tmp")
        installedWarPath = module.targetDeploymentPath + scriptGlobals.osDirSeparator + "server" + scriptGlobals.osDirSeparator + module.targetDeploymentProfile + scriptGlobals.osDirSeparator + "deploy" + scriptGlobals.osDirSeparator + module.name + ".war"
        installedVersionInfo = getVersionInfoFromWar(installedWarPath, module.relativeVersionInformationPath, module.versionInformationRegex, module.revisionInformationRegex, versionTmpPath)
        newWarPath = unzippedPackagePath + scriptGlobals.osDirSeparator + "bin" + scriptGlobals.osDirSeparator + module.name + ".war"
        newVersionInfo = getVersionInfoFromWar(newWarPath, module.relativeVersionInformationPath, module.versionInformationRegex, module.revisionInformationRegex, versionTmpPath)
        log.info("\n------ UPDATE VERSION INFO ------------------------" + 
                 "\nCurrently installed: " + installedVersionInfo[0] + " (" + installedVersionInfo[1] + ")" + 
                 "\n    To be installed: " + newVersionInfo[0] + " (" + newVersionInfo[1] + ")" +
                 "\n---------------------------------------------------")
        versionSameOrNewer=False
        if compareVersions(newVersionInfo[0], installedVersionInfo[0]) < 0 :
            versionSameOrNewer=True
            continueOrCancel("\nWARNING: Installed version is newer! If you continue the installation DB migration will not be executed.")
        elif compareVersions(newVersionInfo[0], installedVersionInfo[0]) == 0 :
            versionSameOrNewer=True
            continueOrCancel("\nWARNING: Same version already installed! If you continue the installation DB migration will not be executed.")
        
        # Configure relativeConfigurationFiles
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            ConfigureTemplateFile(module.name, lib.OptParser.options.envprops, exactExtractedLocation)
            replaceInsensitiveStringInFile("${CREATE_SCHEMA}", "false", exactExtractedLocation)
            CheckFileConfigurationIsComplete(exactExtractedLocation)
        
        # Configure relativeMergableConfigurationFiles
        for k, v in euclidModule.relativeMergableConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            ConfigureTemplateFile(module.name, lib.OptParser.options.envprops, exactExtractedLocation)
            replaceInsensitiveStringInFile("${CREATE_SCHEMA}", "false", exactExtractedLocation)
            CheckFileConfigurationIsComplete(exactExtractedLocation)
        
        # Explode wars
#        for k, v in euclidModule.relativeWarsToBeExploded.items():
#            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
#            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
#            backupFileOrDirIfExists(exactTargetLocation,backupPath)
#            ExtractZipToDir(exactExtractedLocation, exactTargetLocation)
        for k, v in euclidModule.relativeWarsToBeExploded.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            i = rfind(k, scriptGlobals.osDirSeparator)
            if i > -1: 
                tmpExplodeWarLocation = explodePath + scriptGlobals.osDirSeparator + k[i+1:]
            else:
                tmpExplodeWarLocation = explodePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v
            backupFileOrDirIfExists(exactTargetLocation,backupPath)
            createDirectoriesRecursively(tmpExplodeWarLocation)
            ExtractZipToDir(exactExtractedLocation, tmpExplodeWarLocation)
            AltMoveDirOrFile(tmpExplodeWarLocation,exactTargetLocation)
        
        # Copy config files
        for k, v in module.relativeConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v 
            backupFileOrDirIfExists(exactTargetLocation,backupPath)
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation) 
            
        # Copy merge config files and copy (just copy for now)
        for k, v in euclidModule.relativeMergableConfigurationFiles.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = v 
            backupFileOrDirIfExists(exactTargetLocation,backupPath)
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation)
#            secondaryFileName = unzippedPackagePath + scriptGlobals.osDirSeparator + k
#            mergedFileName = secondaryFileName+".merged"
#            primaryFileName = v 
#            MergeSectionlessConfigFiles(primaryFileName, secondaryFileName, mergedFileName)
#            CopyDirOrFile(mergedFileName, primaryFileName)      

        # Copy other files
        for k, v in module.relativeCopyableFilesOrFolders.items():
            exactExtractedLocation = unzippedPackagePath + scriptGlobals.osDirSeparator + k
            exactTargetLocation = module.targetDeploymentPath + scriptGlobals.osDirSeparator + v 
            backupFileOrDirIfExists(exactTargetLocation,backupPath)
            CopyDirOrFile(exactExtractedLocation, exactTargetLocation)
        
        #Construct DB connection string
        if versionSameOrNewer:
            log.info("Skipping DB migration scripts execution!")
            return
        dbUsername = readPropertyFromPropertiesFile("DB_CONNECTION_USERNAME", module.name, lib.OptParser.options.envprops)
        dbPassword = readPropertyFromPropertiesFile("DB_CONNECTION_PASSWORD", module.name, lib.OptParser.options.envprops)
        connUrl = readPropertyFromPropertiesFile("DB_CONNECTION_URL", module.name, lib.OptParser.options.envprops)
        finalConnectionString = string.replace(connUrl, '@', dbUsername + '/' + dbPassword + '@', 1)
        
        # Execute DB migration scripts
        confParser = ConfigParser.ConfigParser()
        confParser.read(unzippedPackagePath + scriptGlobals.osDirSeparator + euclidModule.relativeDatabaseUpgrateDescriptionFilePath)
        ok, scripts, default = getDbUpdateScriptsToRun(installedVersionInfo[0], confParser)
        if ok == False:
            continueOrCancel("\nERROR: This installer does not support updating from " + installedVersionInfo[0] + " version!")
        elif len(default)>0:
            log.info('DB update scripts to be executed:\n' + string.join(scripts, ", "))
            continueOrCancel("\nWARNING: Default DB update scripts are used for branch(es) " + string.join(default,", ") + ". This is probably probably OK, but you should make sure that the currently installed version is supported by the update procedure (please read the deployment instructions or consult with the development team).")
        else:
            log.info('DB update scripts to be executed:\n' + string.join(scripts, ", "))
        baseDbScriptPath = unzippedPackagePath + scriptGlobals.osDirSeparator + module.relativeDatabaseUpgradeFilePath + scriptGlobals.osDirSeparator
        for script in scripts:
            #print "Execute: " + baseDbScriptPath + script
            RunOracleScriptFromFile(baseDbScriptPath + script, finalConnectionString)