#!/bin/bash
# Add methods which is common across any type of installer

syncEtc() {
    local srcEtc=${JF_PRODUCT_HOME}/app/misc/etc
    local targetEtc=${JF_PRODUCT_HOME}/var/etc
    local accessSecurity=${JF_PRODUCT_HOME}/var/bootstrap/access/etc/security
    local filebeatDir=${JF_PRODUCT_HOME}/var/data/filebeat

    # Use this if there are any configuration files need to be copied over to specific service directory
    local relativeFolders=""

    # Add space seperated file list to copy only if not available
    local relativeFilesNoOverwrite=""

    local basicTemplate="system.basic-template.yaml"
    # Add space seperated file list to overwrite on copy
    local relativeFilesReplace="${basicTemplate} system.full-template.yaml filebeat.yaml"

    createDir "${targetEtc}" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}"

    for folder in ${relativeFolders}
    do
        createDir "${targetEtc}/${folder}" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}"
    done

    for file in ${relativeFilesNoOverwrite}
    do
        copyFile "${srcEtc}/${file}" "${targetEtc}/${file}" "no_overwrite"
    done

    for file in ${relativeFilesReplace}
    do
        copyFile "${srcEtc}/${file}" "${targetEtc}/${file}"
    done

    copyFile "${srcEtc}/${basicTemplate}" "${targetEtc}/system.yaml" "no_overwrite"

    [ -d "${filebeatDir}" ] || \
        createRecursiveDir "${JF_PRODUCT_HOME}/var" "data filebeat" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}" >/dev/null 2>&1 || true

    [ -d "${accessSecurity}" ] || \
        createRecursiveDir "${JF_PRODUCT_HOME}/var" "bootstrap access etc security" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}" >/dev/null 2>&1 || true
}

# Bootstraping custom java security file
bootstrapJavaSecurityFile(){
    local javaSecurityFileName="java.security"
    local srcJavaSecurityFilepath="${JF_PRODUCT_HOME}/var/bootstrap/artifactory/java"
    local desJavaSecurityFilepath="${JF_PRODUCT_HOME}/app/third-party/java/conf/security"
    
    if [[ -f "${srcJavaSecurityFilepath}/${javaSecurityFileName}" ]]; then
        logger "Bootstraping custom java security file"
        # backup existing java security file
        local backupJavaSecurityFile="${desJavaSecurityFilepath}/${javaSecurityFileName}.$(date +"%Y%m%d%H%M")"
        mv -f ${desJavaSecurityFilepath}/${javaSecurityFileName} ${backupJavaSecurityFile} || warn "Moving ${desJavaSecurityFilepath}/${javaSecurityFileName} to ${backupJavaSecurityFile} failed"
        # copy custom java security file
        copyFile "${srcJavaSecurityFilepath}/${javaSecurityFileName}" "${desJavaSecurityFilepath}/${javaSecurityFileName}"
        chmod 755 "${desJavaSecurityFilepath}/${javaSecurityFileName}" >/dev/null 2>&1 || true
        rm -f "${srcJavaSecurityFilepath}/${javaSecurityFileName}" || warn "Failed to remove file ${srcJavaSecurityFilepath}/${javaSecurityFileName}"
    fi
}

removeOriginalJoinKey() {
    logDebug "Method removeOriginalJoinKey"
    local actualJoinKey="${JF_PRODUCT_HOME}/var/etc/security/join.key"
    local keySecurityJoinKeyFile="shared.security.joinKeyFile"
    local keySecurityJoinKey="shared.security.joinKey"

    getSystemValue "${keySecurityJoinKeyFile}" "NOT_SET" "false"
    if [ "${YAML_VALUE}" != "NOT_SET" ]; then
        actualJoinKey="${YAML_VALUE}"
        removeYamlValue "${keySecurityJoinKeyFile}" "${JF_PRODUCT_HOME}/var/etc/system.yaml"
    fi

     if [ -f "$actualJoinKey" ]; then
        rm -f "$actualJoinKey"
    fi

    getSystemValue "${keySecurityJoinKey}" "NOT_SET" "false"
    if [ "${YAML_VALUE}" != "NOT_SET" ]; then
        removeYamlValue "${keySecurityJoinKey}" "${JF_PRODUCT_HOME}/var/etc/system.yaml"
    fi
}

prioritizeCustomJoinKey(){
    logDebug "Method removeJoinKeyIfBootstrapping"

    # If the user wants to bootstrap with a specific join key, delete the original
    local bootstrapKey="${JF_PRODUCT_HOME}/var/bootstrap/access/etc/security/join.key"

    if [ -f "${bootstrapKey}" ]; then
        logger "Bootstrap joinKey found in [$bootstrapKey:]. Deleting original"
        removeOriginalJoinKey
    fi
}

initNode() {
    export NODE="${JF_PRODUCT_HOME}/app/third-party/node/bin/node"
    export NODE_ENV=PRODUCTION #TODO (matank): should be removed after JFUI-1372 will be resolved
}

initJava() {
    getSystemValue "shared.javaHome" "${JF_PRODUCT_HOME}/app/third-party/java"
    JAVA_HOME="${YAML_VALUE}"
    export JAVA_HOME
    export JRE_HOME=${JAVA_HOME}
    
    if [ ! -z "${PATH}" ]; then
        export PATH="${PATH}":"${JAVA_HOME}"/bin
    else
        export PATH="${JAVA_HOME}"/bin
    fi
}

addExtraJavaArgs () {
    local extra_java_options=
    getSystemValue "shared.extraJavaOpts" "NOT_SET"
    extra_java_options="${YAML_VALUE}"

    if [[ "${extra_java_options}" != "NOT_SET" ]]; then
        JF_SHARED_EXTRAJAVAOPTS="${extra_java_options}"
    fi

    removeDuplicateJavaOpts "${JAVA_OPTIONS}" "${JF_SHARED_EXTRAJAVAOPTS}"
    JAVA_OPTIONS="${UNIQUE_DEFAULT_JAVA_OPTIONS}"

    export JF_SHARED_EXTRAJAVAOPTS
    export JAVA_OPTIONS="${JAVA_OPTIONS} ${JF_SHARED_EXTRAJAVAOPTS}"
}

# Check if access needs to run in dedicated tomcat
runAccessOnArtifactoryTomcat(){
    local runOnArtifactoryTomcat=
    getSystemValue "access.runOnArtifactoryTomcat" "false"
    runOnArtifactoryTomcat="${YAML_VALUE}"

    if [[ "${runOnArtifactoryTomcat}" == "true" ]]; then
        return 0
    else
        return 1
    fi
}

configureServerXml () {
    # this is to support toggle of access and rt in split tomcat vs single tomcat
    # until toggle feature [INST-8549] is removed, any new server xml template added with access should include a file with access connector and one without
    local templateFilePostFixForAccess=""
    if runAccessOnArtifactoryTomcat; then
        templateFilePostFixForAccess=".access"
    fi

    local server_xml=${JF_PRODUCT_HOME}/app/artifactory/tomcat/conf/server.xml
    local server_xml_template=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.template${templateFilePostFixForAccess}
    local server_xml_template_copy=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.template.copy
    local yaml_server_xml=
    local httpsEnabledValue=
    local serverXmlKey="shared.tomcat.server.xml"
    local httpsEnabledKey="artifactory.tomcat.httpsConnector.enabled"
    local httpsCrtYamlKey="artifactory.tomcat.httpsConnector.certificateFile"
    local httpsPvtYamlKey="artifactory.tomcat.httpsConnector.certificateKeyFile"
    local routerDataKeysPath="${JF_PRODUCT_HOME}/var/data/router/keys"
    local routerBootstrapKeysPath="${JF_PRODUCT_HOME}/var/bootstrap/router/keys"

    if runMissionControl; then
       local mcEnabledValue=true
    fi
    
    if [[ $(isRunningInsideAContainer 2>/dev/null) == "$FLAG_Y" ]]; then
        #setting tomcat folders to write permissions so that the below operations can be done
        setTomcatFoldersWrite
    fi

    # select http server.xml mc template if mc.enabled to true
    [[ "${mcEnabledValue}" == "true" ]] && server_xml_template=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.mc.template${templateFilePostFixForAccess}

    #################### New Platform Service Architecture ############################
    # Based on flags JF_ARTIFACTORY_SERVICE_ENABLED,JF_ACCESS_ENABLED and PLATFORM_SERVICE_ENABLED 
    # Select the templates for new Platform Service Architecture
    if [[ "${JF_ARTIFACTORY_SERVICE_ENABLED}" == "true" ]]; then
        server_xml_template=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.rt.template
        server_xml_template_copy=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.rt.template.copy
        logger "Artifactory Service is enabled, Consumes server.xml template - ${server_xml_template}"
    fi
    if [[ "${mcEnabledValue}" == "true" && "$PLATFORM_SERVICE_ENABLED" == "true" ]]; then
        # select http server.xml.ps.template if JF_MC_ENABLED and PLATFORM_SERVICE_ENABLED is enabled to true
        server_xml_template=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.mc.ps.template
        server_xml_template_copy=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.mc.ps.template.copy
        logger "Mission Control is enabled, Consumes server.xml template - ${server_xml_template}"
    fi
    ###################################################################################

    getSystemValue "${httpsEnabledKey}" "NOT_SET" "false"
    httpsEnabledValue=${YAML_VALUE}
    if [[ "${httpsEnabledValue}" == "true" ]]; then
        server_xml_template=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.https.hotreload.template${templateFilePostFixForAccess}
        server_xml_template_copy=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.https.hotreload.template.copy
        server_xml_template_custom=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.https.custom.template${templateFilePostFixForAccess}
        server_xml_template_custom_copy=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.https.custom.template.copy
        
        #################### New Platform Service Architecture ############################
        # Based on flags JF_ARTIFACTORY_SERVICE_ENABLED on enabling https
        # Select the templates for new Platform Service Architecture
        if [[ "${JF_ARTIFACTORY_SERVICE_ENABLED}" == "true" ]]; then
            server_xml_template=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.https.hotreload.rt.template
            server_xml_template_copy=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.https.hotreload.rt.template.copy
            server_xml_template_custom=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.https.custom.rt.template
            server_xml_template_custom_copy=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.https.custom.rt.template.copy
        fi
        ###################################################################################

        # select https server.xml mc template if mc.enabled to true
        if [[ "${mcEnabledValue}" == "true" ]]; then 
            server_xml_template=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.mc.https.hotreload.template${templateFilePostFixForAccess}
            server_xml_template_copy=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.mc.https.hotreload.template.copy
            server_xml_template_custom=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.mc.https.custom.template${templateFilePostFixForAccess}
            server_xml_template_custom_copy=${JF_PRODUCT_HOME}/app/misc/tomcat/server.xml.mc.https.custom.template.copy
        fi

        getSystemValue "${httpsCrtYamlKey}" "NOT_SET" "false"
        yamlCrtValue=${YAML_VALUE}
        getSystemValue "${httpsPvtYamlKey}" "NOT_SET" "false"
        yamlPvtKeyValue=${YAML_VALUE}
        # check private key and  cert files
        checkCertsAndKeysInSystemYaml "${yamlCrtValue}" "${yamlPvtKeyValue}" "${httpsCrtYamlKey}" "${httpsPvtYamlKey}" "${routerDataKeysPath}"
    fi

    [ -f ${server_xml_template} ] || errorExit "${server_xml_template} not found"
    getSystemValue "${serverXmlKey}" "NOT_SET" "false"
    yaml_server_xml=${YAML_VALUE}
    # Save original and replace with the template
    if [[ -f "${server_xml}" &&  ! -f "${server_xml}".orig ]]; then
        logger "Saving ${server_xml} as ${server_xml}.orig"
        mv -f ${server_xml} ${server_xml}.orig || errorExit "Moving ${server_xml} to ${server_xml}.orig failed"
    fi
    if [ "${yaml_server_xml}" != "NOT_SET" ]; then
        logger "Creating ${server_xml} from ${serverXmlKey} in system.yaml"
        echo "${YAML_VALUE}" > "${server_xml}" || errorExit "Failed to create ${server_xml}, please check if ${serverXmlKey} has a valid xml value"
    else

        logger "Using Tomcat template to generate : ${server_xml}"

        cp -f "${server_xml_template}" "${server_xml_template_copy}" || errorExit "Copying ${server_xml_template_copy} to ${server_xml_template_copy} failed"
        resolveSystemKeys "${server_xml_template_copy}"
        mv -f "${server_xml_template_copy}" "${server_xml}" || errorExit "Copying ${server_xml_template_copy} to ${server_xml} failed"

        if [[ "${httpsEnabledValue}" == "true" ]]; then
            customServerExtn=$(getcustomServerExtn "${routerDataKeysPath}")
            # TODO simplify this logic later
            if [[ -f "${routerBootstrapKeysPath}/custom-server.${customServerExtn}" && -f "${routerBootstrapKeysPath}/custom-server.key" ]]; then
                CUSTOM_HTTPS_SERVER_XML=true
            elif [[ -f "${routerDataKeysPath}/custom-server.${customServerExtn}" && -f "${routerDataKeysPath}/custom-server.key" ]]; then
                CUSTOM_HTTPS_SERVER_XML=true
            elif [[ "${yamlCrtValue}" != "NOT_SET" && "${yamlPvtKeyValue}" != "NOT_SET" ]]; then
                CUSTOM_HTTPS_SERVER_XML=true
            else
                CUSTOM_HTTPS_SERVER_XML=false
            fi

            if $CUSTOM_HTTPS_SERVER_XML ; then
                cp -f "${server_xml_template_custom}" "${server_xml_template_custom_copy}" || errorExit "Copying ${server_xml_template_custom_copy} to ${server_xml_template_custom_copy} failed"
                resolveSystemKeys "${server_xml_template_custom_copy}"
                mv -f "${server_xml_template_custom_copy}" "${server_xml}" || errorExit "Copying ${server_xml_template_custom_copy} to ${server_xml} failed"
            fi
        fi
    fi

    #Setting Tomcat shutdown command
    TOMCAT_SHUTDOWN_COMMAND=$(< /dev/urandom LC_ALL=C tr -dc A-Za-z | head -c12 2>/dev/null)
    [ -z "$TOMCAT_SHUTDOWN_COMMAND" ] && TOMCAT_SHUTDOWN_COMMAND=RaNDmSTriNg
    if [[ $(uname) == "Darwin" ]]; then
        sed -i '' -e "s:shutdown=\"SHUTDOWN\":shutdown=\"$TOMCAT_SHUTDOWN_COMMAND\":" ${server_xml}
    else
        sed -i -e "s:shutdown=\"SHUTDOWN\":shutdown=\"$TOMCAT_SHUTDOWN_COMMAND\":" ${server_xml}
    fi

    if [[ $(isRunningInsideAContainer 2>/dev/null) == "$FLAG_Y" ]]; then
        #setting tomcat folders to readonly after the operation
        setTomcatFoldersReadOnly
    fi
}

getcustomServerExtn() {
    local routerDataKeysPath="$1"
    local customServerExtn="crt"
    local fileExtn=
    local supportFileExtns="crt cer pem"
    if [[ -d "${routerDataKeysPath}" ]]; then
        for fileExtn in $supportFileExtns; do
            local customCertList=$(ls ${routerDataKeysPath})
            if [[ "${customCertList}" == *"custom-server.${fileExtn}"* ]]; then
                customServerExtn="${fileExtn}"
            fi
        done
    fi
    echo "${customServerExtn}"
}

# setting custom certificate and private key path to environment variable
bootstrapCustomCertsAndKeys() {
    local routerDataKeysPath="$1"

    customServerExtn=$(getcustomServerExtn "${routerDataKeysPath}")

    if [[ -f "${routerDataKeysPath}/custom-server.${customServerExtn}" && -f "${routerDataKeysPath}/custom-server.key" ]]; then
        logger "Setting custom ${customServerExtn} and key path to environment variable"
        JF_ARTIFACTORY_TOMCAT_HTTPSCONNECTOR_CERTIFICATEKEYFILE="${routerDataKeysPath}/custom-server.key"
        JF_ARTIFACTORY_TOMCAT_HTTPSCONNECTOR_CERTIFICATEFILE="${routerDataKeysPath}/custom-server.${customServerExtn}"
    elif [[ ! -f "${routerDataKeysPath}/custom-server.${customServerExtn}" && -f "${routerDataKeysPath}/custom-server.key" ]]; then
        errorExit "custom-server.key found, but could not find custom-server.${customServerExtn} in path ${routerDataKeysPath}"
    elif [[ -f "${routerDataKeysPath}/custom-server.${customServerExtn}" && ! -f "${routerDataKeysPath}/custom-server.key" ]]; then
        errorExit "custom-server.${customServerExtn} found, but could not find custom-server.key in path ${routerDataKeysPath}"
    fi
}

# Check for private key and certificate configured in system.yaml 
checkCertsAndKeysInSystemYaml() {
    local yamlCrtValue="$1"
    local yamlPvtKeyValue="$2"
    local httpsCrtYamlKey="$3"
    local httpsPvtYamlKey="$4"
    local routerDataKeysPath="$5"
 
    if [[ "${yamlCrtValue}" == "NOT_SET" && "${yamlPvtKeyValue}" != "NOT_SET" ]]; then
        [[ -f "${yamlPvtKeyValue}" ]] || errorExit "Could not find private key in path ${yamlPvtKeyValue}. Update ${httpsPvtYamlKey} with correct <private key path> in ${JF_PRODUCT_HOME}/var/etc/system.yaml"
        errorExit "Private key path is set, but certificate path is not set. Configure ${httpsCrtYamlKey} with <certificate path> in ${JF_PRODUCT_HOME}/var/etc/system.yaml"
    elif [[ "${yamlCrtValue}" != "NOT_SET" && "${yamlPvtKeyValue}" == "NOT_SET" ]]; then
        [[ -f "${yamlCrtValue}" ]] || errorExit "Could not find certificate in path ${yamlCrtValue}. Update ${httpsCrtYamlKey} with correct <certificate path> in ${JF_PRODUCT_HOME}/var/etc/system.yaml"
        errorExit "Certificate path is set, but private key path is not set. Configure ${httpsPvtYamlKey} with <private key path> in ${JF_PRODUCT_HOME}/var/etc/system.yaml"
    elif [[ "${yamlCrtValue}" != "NOT_SET" && "${yamlPvtKeyValue}" != "NOT_SET" ]]; then
        # Private key and certificate configured in system.yaml
        logger "Using private key and certificate files from the path configured in system.yaml"
    elif [[ "${yamlCrtValue}" == "NOT_SET" && "${yamlPvtKeyValue}" == "NOT_SET" ]]; then
        # check for custom certificate and private key under location ${JF_PRODUCT_HOME}/var/data/router/keys
        bootstrapCustomCertsAndKeys "${routerDataKeysPath}"
    fi
}
    
checkJavaVersion(){
    local javaHome=${1:-${JAVA_HOME}}

    if [[ -n "$javaHome" ]] && [[ -x "$javaHome/bin/java" ]];  then
        _java="$javaHome/bin/java"
    elif type -p java >/dev/null ; then
        _java=java
    else
        echo "No java found"
        exit 99
    fi

    if [[ "$_java" ]]; then
        "$_java" -version 2>&1| \
        awk -F\" '/version/{\
            if ($2 < 11) {\
                printf "%s is too old must be at least java 11\n", $2;\
                exit 0;\
            } else exit 1}' && exit 99
    fi
}

createSymlink() {
    local target=$1
    local link=$2

    [ ! -z "${target}" ] || errorExit "target is not provided to create a symlink"
    [ ! -z "${link}"   ] || errorExit "source is not provided to create a symlink"

    if [[ -d "${link}" && ! -L "${link}" ]];
    then
        # Uncomment this to get debug logs
        # if its a directory, create a copy and move its content back to symlink
        # logger """The target symbolic link ${link} is a directory,
        #                 performing the following operations to change this from directory to symlink,
        #                 - move ${link} to ${link}.copy
        #                 - create link ${link} to ${target}
        #                 - copy content of ${link}.copy to ${link}"""

        mv -f  "${link}"        "${link}.copy" || errorExit "Could not create ${link}.copy directory from ${link}"
        ln -s  "${target}"      "${link}"      || errorExit "Could not create link from ${link} to ${target}"
        cp -fr "${link}.copy"/* "${link}"      || errorExit "Could not copy content from ${link}.copy to ${link}"
        rm -fr "${link}".copy;
    elif [ ! -L "${link}" ];
    then
        ln -s "${target}" "${link}" || errorExit "Could not create link from ${link} to ${target}"
    fi
}

setRouterToplogy(){
    JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jfrt,jfac,jfmd,jffe,jfob

    if runJFConnect; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES="${JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES},jfcon"
    fi
    if runMissionControl; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES="${JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES},jfmc"
    fi
    if runEvent; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES="${JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES},jfevt"
    fi
    # if runFederation; then
    #     JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES="${JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES},jfrtfs"
    # fi
    if runEvidence; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES="${JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES},jfevd"
    fi
    #################### New Platform Service Architecture ############################
    # Based on flags JF_ARTIFACTORY_SERVICE_ENABLED,JF_ACCESS_ENABLED and PLATFORM_SERVICE_ENABLED 
    if [[ "$JF_ARTIFACTORY_SERVICE_ENABLED" == "true" ]]; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jfrt,jfmd,jfob
    fi
    if [[ "$JF_MC_ENABLED" == "true" && "$PLATFORM_SERVICE_ENABLED" == "true" ]]; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jfmc,jfob
    fi
    if [[ "$JF_JFCONNECT_ENABLED" == "true" && "$PLATFORM_SERVICE_ENABLED" == "true" ]]; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jfcon,jfob
    fi
    if [[ "$JF_EVENT_ENABLED" == "true" && "$PLATFORM_SERVICE_ENABLED" == "true" ]]; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jfevt,jfob
    fi
    if [[ "$JF_METADATA_ENABLED" == "true" && "$PLATFORM_SERVICE_ENABLED" == "true" ]]; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jfmd,jfob
    fi
    if [[ "$JF_ACCESS_ENABLED" == "true" && "$PLATFORM_SERVICE_ENABLED" == "true" ]]; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jfac,jfob
    fi
    if [[ "$JF_FRONTEND_ENABLED" == "true" && "$PLATFORM_SERVICE_ENABLED" == "true" ]]; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jffe,jfob
    fi
    # if [[ "$JF_FEDERATION_ENABLED" == "true" && "$PLATFORM_SERVICE_ENABLED" == "true" ]]; then
    #     JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jfrtfs,jfob
    # fi

    if [[ "$JF_EVIDENCE_ENABLED" == "true" && "$PLATFORM_SERVICE_ENABLED" == "true" ]]; then
        JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES=jfevd,jfob
    fi

    export JF_ROUTER_TOPOLOGY_LOCAL_REQUIREDSERVICETYPES
}

copyCustomTomcatDrivers(){
    local customLib=${JF_PRODUCT_HOME}/var/bootstrap/artifactory/tomcat/lib
    local tomcatLib=${JF_PRODUCT_HOME}/app/artifactory/tomcat/lib
    local isDeleted=no
    local driverFile=
    local removeLib=(el-api.jar)

    for driver in ${tomcatLib}/*; do
        driverFile=$(basename "${driver}")
        if [[ " ${removeLib[@]} " =~ " ${driverFile} " ]]; then
            logger "Removing deprecated driver : ${driverFile}"
            rm -f "${driver}" || warn "Failed to remove file ${driver}"
        fi
    done

    [ -d "${customLib}" ] || return

    for driver in ${customLib}/*; do
        [ -f "${driver}" ] || continue

        driverFile=$(basename "${driver}")

        if [ "${isDeleted}" != "yes" ]; then
            logger "Removing old custom drivers : ${tomcatLib}/jf_*"
            rm -fr "${tomcatLib}"/jf_* || warn "Failed to remove files ${tomcatLib}/jf_*, copy of custom drivers will still proceed"
            isDeleted=yes
        fi

        logger "Copying ${driver} to ${tomcatLib}/jf_${driverFile}"
        copyFile "${driver}" "${tomcatLib}/jf_${driverFile}"

        # Try to make sure the driver has read and execute where its possible, ignore and proceed on failure
        chmod +rx "${tomcatLib}/jf_${driverFile}" >/dev/null 2>&1 || true
    done
}

# On enable/disable --> copy/remove - mc.xml and mc.war files in $JF_PRODUCT_HOME}/app/artifactory/tomcat
toggleMissionControl() {
    local source=${JF_PRODUCT_HOME}/app/misc/tomcat
    local target=${JF_PRODUCT_HOME}/app/artifactory/tomcat
    if runMissionControl; then
        copyFile "${source}/mc.xml" "${target}/conf/Catalina/localhost" "no_overwrite"
        if [[ $(isRunningInsideAContainer 2>/dev/null) == "$FLAG_Y" ]]; then
            cp -rf "${source}/mc" "${target}/webapps/"
        else
            copyFile "${source}/mc.war" "${target}/webapps" "no_overwrite"
        fi

        if [[ "$JF_ARTIFACTORY_SERVICE_ENABLED" == "false" ]]; then
                rm -f "${target}/conf/Catalina/localhost/artifactory.xml"
                rm -rf "${target}/webapps/artifactory"
        fi
    else
        if [[ $(isRunningInsideAContainer 2>/dev/null) == "$FLAG_Y" ]]; then
            rm -rf "${target}/webapps/mc"
            rm -f "${target}/conf/Catalina/localhost/mc.xml"
        else
            rm -rf "${target}/webapps/mc"
            rm -f "${target}/webapps/mc.war"
            rm -f "${target}/conf/Catalina/localhost/mc.xml"
        fi
    fi
}

toggleRTandAccess() {
    local source=${JF_PRODUCT_HOME}/app/misc/tomcat
    local target=${JF_PRODUCT_HOME}/app/artifactory/tomcat
    if [[ "$JF_ARTIFACTORY_SERVICE_ENABLED" == "false" ]]; then
        rm -f "${target}/conf/Catalina/localhost/artifactory.xml"
        rm -rf "${target}/webapps/artifactory"
    fi
}

copyAccessToRTTomcat() {
    local miscDir=${JF_PRODUCT_HOME}/app/misc
    local accessTomcatHome=${JF_PRODUCT_HOME}/app/access/tomcat
    local rtTomcatHome=${JF_PRODUCT_HOME}/app/artifactory/tomcat

    local sourceAcccessXml="${miscDir}/tomcat/access.xml"
    local targetAcccessXml="${rtTomcatHome}/conf/Catalina/localhost/access.xml"

    local sourceAcccessWar="${accessTomcatHome}/webapps/access.war"
    local targetAcccessWar="${rtTomcatHome}/webapps/access.war"

    local sourceAcccessExplodedWar="${accessTomcatHome}/webapps/access"
    local targetAcccessExplodedWar="${rtTomcatHome}/webapps/access"

    logger "Configuration is changed for access to run on tomcat of artifactory, copying ${sourceAcccessXml} to ${targetAcccessXml}"
    cp -f "${sourceAcccessXml}" "${targetAcccessXml}"

    if [[ $(isRunningInsideAContainer 2>/dev/null) == "$FLAG_Y" ]]; then
        if [ ! -d "${targetAcccessExplodedWar}" ]; then
            logger "Configuration is changed for access to run on tomcat of artifactory, copying ${sourceAcccessExplodedWar} to ${targetAcccessExplodedWar}"
            cp -fr "${sourceAcccessExplodedWar}" "${targetAcccessExplodedWar}"
        fi
    else
        logger "Configuration is changed for access to run on tomcat of artifactory, copying ${sourceAcccessWar} to ${targetAcccessWar}"
        cp -f "${sourceAcccessWar}" "${targetAcccessWar}"
    fi
}

removeAccessFromRTTomcat() {
    local rtTomcatHome=${JF_PRODUCT_HOME}/app/artifactory/tomcat

    local targetAcccessXml="${rtTomcatHome}/conf/Catalina/localhost/access.xml"
    local targetAcccessWar="${rtTomcatHome}/webapps/access.war"
    local targetAcccessExplodedWar="${rtTomcatHome}/webapps/access"

    for target in "${targetAcccessXml}" "${targetAcccessWar}" "${targetAcccessExplodedWar}"; do
        if [ -f "${target}" ] || [ -d "${target}" ]; then
            logger "Removing redundant acccess related files [ ${target} ] from artifactory tomcat"
            rm -fr "${target}" || errorExit "Failed to remove ${target}"
        fi    
    done
}

toggleAccessFilesFromRTTomcat() {
    if ! runAccess; then
        return 0;
    fi
    if runAccessOnArtifactoryTomcat; then
        copyAccessToRTTomcat
    else
        removeAccessFromRTTomcat
    fi
}

prepareTomcat() {
    local parentWorkDir=${JF_PRODUCT_HOME}/var/work
    local parentDirCreatedNow="no"

    export CATALINA_HOME="${TOMCAT_HOME}"
    export CATALINA_TMPDIR=${parentWorkDir}/artifactory/tomcat/temp

    local defaultWorkDir=${parentWorkDir}/artifactory/tomcat
    getSystemValue "shared.tomcat.workDir" "${defaultWorkDir}"
    local workDir="${YAML_VALUE}"

    if [[ $(isRunningInsideAContainer 2>/dev/null) == "$FLAG_Y" ]]; then
        #setting tomcat folders to write permissions so that the below operations can be done
        setTomcatFoldersWrite
    fi

    [ -d  "${parentWorkDir}" ] || parentDirCreatedNow="yes"

    createDir "${JF_PRODUCT_HOME}/var/work" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}"

    [ -d "${CATALINA_TMPDIR}" ] || \
        createRecursiveDir "${parentWorkDir}" "artifactory tomcat temp" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}" >/dev/null

    if [[ "${workDir}" == "${defaultWorkDir}" ]]; then
        [ -d "${workDir}" ] || \
            createRecursiveDir "${parentWorkDir}" "artifactory tomcat" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}" >/dev/null
    else
        [ -d "${workDir}" ] || \
            createDir "${workDir}" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}"
    fi

    copyCustomTomcatDrivers
    toggleMissionControl
    toggleRTandAccess
    toggleAccessFilesFromRTTomcat

    [ ! -z "${CATALINA_PID_FOLDER}" ] && createDir "${CATALINA_PID_FOLDER}" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}" || true

    if [ ! -z "${JF_ARTIFACTORY_USER}" ] && [ ! -z "${JF_ARTIFACTORY_GROUP}" ]; then
        # Change directory ownership for 7.x to 7.x upgrade (if the directory is already created with root)
        [ -d "${parentWorkDir}/artifactory" ] && \
            io_setOwnershipNonRecursive "${parentWorkDir}/artifactory" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}" || true

        [ ! -z "${CATALINA_PID_FOLDER}" ] && [ -d "${CATALINA_PID_FOLDER}" ] && \
            io_setOwnership "${CATALINA_PID_FOLDER}" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}" || true

        [ "${parentDirCreatedNow}" == "yes" ] && [ -d "${parentWorkDir}" ] && \
            io_setOwnership "${parentWorkDir}" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}" || true
    fi

    if [[ $(isRunningInsideAContainer 2>/dev/null) == "$FLAG_Y" ]]; then
        #setting tomcat folders to readonly after the operations
        setTomcatFoldersReadOnly
    fi
}

# Add additional files from a location given as key (system.yaml or env) to destination
# srcKey        : path in system.yaml
# target        : target location to copy to
# defaultSrcDir : deafult source directory to copy files from
#
# Example : 
#    addExtraFiles "acccess.extraConf" "/var/opt/jfrog/artifactory/etc/access" "/access_extraconf"
addExtraFiles () {
    local srcKey=$1
    local target=$2
    local defaultSrcDir=${3:-"NOT_SET"}
    local extraConfDir=

    if [[ -z "${srcKey}" || -z "${target}" ]]; then
        return
    fi

    getSystemValue "${srcKey}" "$defaultSrcDir"
    extraConfDir="${YAML_VALUE}"

    if [[ "${extraConfDir}" == "NOT_SET" ]]; then
        return
    fi

    # If directory not empty
    if [ -d "${extraConfDir}" ] && [ "$(ls -A ${extraConfDir})" ]; then
        logger "Adding files from ${extraConfDir} to ${target}"
        copyFilesNoOverwrite "${extraConfDir}" "${target}"
    fi
}

findShutdownPort() {
    CATALINA_MGNT_PORT=${CATALINA_MGNT_PORT:-8015}
    if command -v netstat 2>/dev/null; then
        SHUTDOWN_PORT=$(netstat -vatn|grep LISTEN|grep $CATALINA_MGNT_PORT|wc -l)
    else
        (</dev/tcp/localhost/${CATALINA_MGNT_PORT}) 2>/dev/null
        if [[ $? -eq 0 ]]; then
            SHUTDOWN_PORT=1
        else
            SHUTDOWN_PORT=0
        fi
    fi
}

isAlive() {
    pidValue=""
    javaPs=""
    if [[ -e "$JF_ARTIFACTORY_PID" ]]; then
        pidValue=$(cat ${JF_ARTIFACTORY_PID})
        if [ -n "$pidValue" ]; then
            javaPs="$(ps -p ${pidValue} | grep java)"
        fi
    fi
}

createDirectory () {
    [[ -d "$1" ]] || mkdir -p $1 || errorExit "Could not create dir $1"
}

checkArtHome() {
    if [ -z "${JF_PRODUCT_HOME}" ] || [ ! -d "${JF_PRODUCT_HOME}" ]; then
        errorArtHome "ERROR: Artifactory home folder not defined or does not exists at ${JF_PRODUCT_HOME}"
    fi
}

checkTomcatHome() {
    if [ -z "$TOMCAT_HOME" ] || [ ! -d "$TOMCAT_HOME" ]; then
        errorArtHome "ERROR: Tomcat Artifactory folder not defined or does not exists at $TOMCAT_HOME"
    fi
}

#Altering tomcat permissions for installer operations
setTomcatFoldersWrite() {
    if [ -z "$TOMCAT_HOME" ] || [ ! -d "$TOMCAT_HOME" ]; then
        errorArtHome "ERROR: Tomcat Artifactory folder not defined or does not exists at $TOMCAT_HOME"
    fi

    chmod 0766 ${JF_PRODUCT_HOME}/app/artifactory/tomcat/webapps/
    chmod 0766 ${JF_PRODUCT_HOME}/app/artifactory/tomcat/conf/
}

#Setting tomcat access to read-only to prevent sec incursions
setTomcatFoldersReadOnly() {
    if [ -z "$TOMCAT_HOME" ] || [ ! -d "$TOMCAT_HOME" ]; then
        errorArtHome "ERROR: Tomcat Artifactory folder not defined or does not exists at $TOMCAT_HOME"
    fi

    chmod 0555 ${JF_PRODUCT_HOME}/app/artifactory/tomcat/webapps/
    chmod 0555 ${JF_PRODUCT_HOME}/app/artifactory/tomcat/conf/
}

checkArData() {
    [ -z "${JF_PRODUCT_HOME}" ] && errorExit "Artifactory home (JF_PRODUCT_HOME) is not defined"
}

checkArtUser() {
    local defaultUser="artifactory"
    # This will set default user and password if its not set in system.yaml or as environment variable
    setUserGroup "${defaultUser}"
    # User under which all the microservices will run
    [ ! -z "$JF_ARTIFACTORY_USER"  ] || JF_ARTIFACTORY_USER=${defaultUser}
    [ ! -z "$JF_ARTIFACTORY_GROUP" ] || JF_ARTIFACTORY_GROUP=${defaultUser}
}

changeArtOwnership(){
    local dir=$1
    local user=${2:-"${JF_ARTIFACTORY_USER}"}
    local group=${3:-"${JF_ARTIFACTORY_GROUP}"}

    [ -z "$dir" ] && return || true
    chown -R "${user}":"${group}" $dir || errorExit "Unable to set ownership on [ $dir ], command : chown -R ${JF_ARTIFACTORY_USER}:${JF_ARTIFACTORY_GROUP} ${dir}"
}

# Check if conditions to run local router are met
runRouter() {
    local isEnabled=
    getSystemValue "${ROUTER_SERVICE_NAME}.enabled" "true"
    isEnabled="${YAML_VALUE}"

    if [[ "${isEnabled}" == "true" && -f "${routerScript}" ]]; then
        return 0
    else
        return 1
    fi
}

# Check if conditions to run local observability are met
runObservability() {
    local isEnabled=
    getSystemValue "${OBSERVABILITY_NAME}.enabled" "true"
    isEnabled="${YAML_VALUE}"

    if [[ "${isEnabled}" == "true" && -f "${observabilityScript}" ]]; then
        return 0
    else
        return 1
    fi
}

# Check if conditions to run local federation are met
runFederation() {
    local isEnabled=
    getSystemValue "${FEDERATION_NAME}.enabled" "false"
    federationIsEnabled="${YAML_VALUE}"
    getSystemValue "${FEDERATION_NAME}.embedded" "false"
    local isEmbedded="${YAML_VALUE}"

    if [[ "${federationIsEnabled}" == "true" ]] && [[ "${isEmbedded}" == "true" ]]  && [ -f ${federationScript} ]; then
        return 0
    else
        return 1
    fi
}

# Check if conditions to run local event are met
runEvent() {
    local isEnabled=
    getSystemValue "${EVENT_NAME}.enabled" "true"
    isEnabled="${YAML_VALUE}"

    if [[ "${isEnabled}" == "true" && -f "${eventScript}" ]]; then
        return 0
    else
        return 1
    fi
}

# Returns Y if this method is run inside a pod
######################################################################
##############  NOTE: This methos is temporary method   ##############
### This method is checking for script is running inside pod only ###
## Evidence service should not run for non k8s based installations ##
######################################################################
isRunningInsidePod() {
    local check1=$(grep -sq 'kubepods' /proc/1/cgroup; echo $?)
    local check2=$(grep -sq 'containers' /proc/self/mountinfo; echo $?)
    if [[ $check1 == 0 && $check2 == 0 ]]; then
        echo -n "$FLAG_Y"
    else
        echo -n "$FLAG_N"
    fi
}


# Check if conditions to run local evidence are met
runEvidence() {

    if [[ $(isRunningInsidePod 2>/dev/null) != "$FLAG_Y" ]]; then
        return 1
    fi

    local isEnabled=
    getSystemValue "${EVIDENCE_NAME}.enabled" "false"
    isEnabled="${YAML_VALUE}"

    if [[ "${isEnabled}" == "true" && -f "${evidenceScript}" ]]; then
        return 0
    else
        return 1
    fi
}

# Check if conditions to run local metadata are met
runMetadata() {
    local isEnabled=
    getSystemValue "${METADATA_NAME}.enabled" "true"
    isEnabled="${YAML_VALUE}"

    if [[ "${isEnabled}" == "true" && -f "${metadataScript}" ]]; then
        return 0
    else
        return 1
    fi
}

# Check if conditions to run local frontend are met
runFrontend() {
    local isEnabled=
    getSystemValue "${FRONTEND_NAME}.enabled" "true"
    isEnabled="${YAML_VALUE}"

    if [[ "${isEnabled}" == "true" && -f "${frontendScript}" ]]; then
        return 0
    else
        return 1
    fi
}

# Check if conditions to run local jfconnect are met
runJFConnect() {
    local isEnabled=
    getSystemValue "${JFCONNECT_SERVICE_NAME}.enabled" "true"
    isEnabled="${YAML_VALUE}"

    if [[ "${isEnabled}" == "true" && -f "${jfconnectScript}" ]]; then
        return 0
    else
        return 1
    fi
}

# Check if conditions to run local access are met
runAccess() {
    if  [ -z "$JF_ACCESS_ENABLED" ] || [ "$JF_ACCESS_ENABLED" != "false" ]; then
        return 0
    else
        return 1
    fi
}

# Check if conditions to run local missionControl are met
runMissionControl() {
    if [[ $(isRunningInsideAContainer 2>/dev/null) == "$FLAG_Y" ]]; then
        local mcWarfolder=${JF_PRODUCT_HOME}/app/misc/tomcat/mc
    else
        local mcWar=${JF_PRODUCT_HOME}/app/misc/tomcat/mc.war
    fi

    local isEnabled=
    getSystemValue "mc.enabled" "false"
    isEnabled=$(echo "${YAML_VALUE}" | tr '[:upper:]' '[:lower:]')

    if [[ "${isEnabled}" == "true" && -f "${mcWar}" || "${isEnabled}" == "true" && -d "${mcWarfolder}" ]]; then
        return 0
    else
        return 1
    fi
}

setUserGroup(){
    local defaultUser=${1:-artifactory}
    local defaultGroup=${2:-${defaultUser}}
    local user=
    local group=
    local userKey="shared.user"
    local groupKey="shared.group"

    getSystemValue "${userKey}" "NOT_SET"
    user=$YAML_VALUE

    getSystemValue "${groupKey}" "NOT_SET"
    group=$YAML_VALUE

    # Consider user as group if ony user is set
    if [[ "$group" == "NOT_SET" && "$user" != "NOT_SET" ]]; then
        group="$user"
    fi

    [ "$user"  = "NOT_SET" ] && user=""  || true
    [ "$group" = "NOT_SET" ] && group="" || true

    # Default it to artifactory
    JF_ARTIFACTORY_USER=${user:-${defaultUser}}
    JF_ARTIFACTORY_GROUP=${group:-${defaultGroup}}
}

# Wait for DB port to be accessible
waitForDB () {
    local isPrimary=
    local dbType=
    local dbUrl=
    local dbHostPort=

    local dbTypeKey="shared.database.type"
    local primaryNodeKey="shared.node.primary"
    local dbUrlKey="shared.database.url"

    local TIMEOUT=30
    local COUNTER=0

    if [ "${SKIP_WAIT_FOR_EXTERNAL_DB}" == "true" ]; then
        logger "SKIP_WAIT_FOR_EXTERNAL_DB is set to true. Skipping wait for external database to come up"
        return 0
    fi

    getSystemValue "${primaryNodeKey}" "NOT_SET"
    isPrimary="${YAML_VALUE}"

    getSystemValue "${dbTypeKey}" "NOT_SET"
    dbType="${YAML_VALUE}"

    getSystemValue "${dbUrlKey}" "NOT_SET"
    dbUrl="${YAML_VALUE}"

    # Do not run on secondary nodes
    # Skip check if database type or url is not set
    if [[ "$isPrimary" =~ false ]] || [[ "${dbType}" == "NOT_SET" ]] || [[ "${dbType}" == "derby" ]]; then
        return 0
    fi

    if [[ "${dbUrl}" == "NOT_SET" ]]; then
        return 0
    fi

    # Extract DB host and port
    case "${dbType}" in
        postgresql|mysql|mariadb)
            dbHostPort=$(echo "${dbUrl}" | sed -e 's,^.*:\/\/\(.*\)\/.*,\1,g' | tr ':' '/')
        ;;
        oracle)
            dbHostPort=$(echo "${dbUrl}" | sed -e 's,.*@\(.*\):.*,\1,g' | tr ':' '/')
        ;;
        mssql)
            dbHostPort=$(echo "${dbUrl}" | sed -e 's,^.*:\/\/\(.*\);databaseName.*,\1,g' | tr ':' '/')
        ;;
        *)
            errorExit "Database type ${dbType} not supported"
        ;;
    esac

    # TODO : [Amith] Need a better solution to check if database is up and running
    logger "Waiting for DB ${dbType} to be ready on ${dbHostPort} for ${TIMEOUT} seconds"
    sleep ${TIMEOUT}
    return 0
    # This solution returns immediately on compose solution when network mode is host
    # while [ $COUNTER -lt $TIMEOUT ]; do
    #     (</dev/tcp/${dbHostPort}) 2>/dev/null
    #     if [ $? -eq 0 ]; then
    #         echo;
    #         logger "DB ${dbType} up in $COUNTER seconds"
    #         return 0
    #     else
    #         echo -n "."
    #         sleep 1
    #     fi
    #     let COUNTER=$COUNTER+1
    # done

    # return 1
}

# This needs to be run after a shut down is called on tomcat using its script (shutdown.sh)
# This will check if the process is still running and issue a process kill after a period of time
hardKillTomcat(){
    killed=false
    if [ ${RETVAL} -ne 0 ]; then
        warn "Artifactory Tomcat server shutdown script failed. Sending kill signal to $pidValue"
        if [ -n "$pidValue" ]; then
            killed=true
            kill ${pidValue}
            RETVAL=$?
        fi
    fi
    # Wait 2 seconds for process to die
    sleep 2
    findShutdownPort
    isAlive
    nbSeconds=1
    while [ ${SHUTDOWN_PORT} -ne 0 ] || [ -n "${javaPs}" ] && [ ${nbSeconds} -lt 30 ]; do
        if [ ${nbSeconds} -eq 10 ] && [ -n "$pidValue" ]; then
            # After 10 seconds try to kill the process
            warn "Artifactory Tomcat server shutdown not done after 10 seconds. Sending kill signal"
            kill ${pidValue}
            RETVAL=$?
        fi
        if [ ${nbSeconds} -eq 25 ] && [ -n "$pidValue" ]; then
            # After 25 seconds try to kill -9 the process
            warn "Artifactory Tomcat server shutdown not done after 25 seconds. Sending kill -9 signal"
            kill -9 ${pidValue}
            RETVAL=$?
        fi
        sleep 1
        let "nbSeconds = $nbSeconds + 1"
        findShutdownPort
        isAlive
    done
}

performActionOnScriptAsUser(){
    local script="$1"
    local action="${2}"

    [ ! -z "${script}" ] || "Script path and action is mandatory for method performActionOnScriptAsUser"
    [ ! -z "${action}" ] || "Action to be performed on ${script} is not passed for method performActionOnScriptAsUser"

    if [[ -f "${script}" ]] ; then
        chmod +x "${script}"
        su -m -s "/bin/sh" ${JF_ARTIFACTORY_USER} -c "${script} ${action}"
    fi
}

copyDerbyDataToAccess() {
    local changeOwnership=${1:-"false"}
    local artifactoryDerbyData=${JF_PRODUCT_HOME}/var/data/artifactory/derby
    local accessDerbyData=${JF_PRODUCT_HOME}/var/data/access/derby

    if [ -d "${artifactoryDerbyData}" ] && [ ! -d "${accessDerbyData}" ]; then
        logger "Access derby data does not exist, where as artifactory data does exist, copying this data from artifactory"
        mkdir -p "${accessDerbyData}"
        cp -fr "${artifactoryDerbyData}"/* "${accessDerbyData}"/ || \
        errorExit "Copying derby data from ${artifactoryDerbyData} to ${accessDerbyData} failed, copy the data manually to continue [ cp -fr \"${artifactoryDerbyData}\"/* \"${accessDerbyData}\"/ ]"
        if [[ -n "${changeOwnership}" ]] && [[ "${changeOwnership}" == "true" ]]; then
            changeArtOwnership "${accessDerbyData}"
        fi
    fi
}

runAccessScript(){
    local script="$1"
    local action="${2}"
    local accessSplitSystemYamlKey="access.runOnArtifactoryTomcat"
    if runAccessOnArtifactoryTomcat; then
        logger "Access split mode is disabled for this installation. Access will run in the same tomcat as Artifactory. \
                The following key in system.yaml can be used to modify this $accessSplitSystemYamlKey"
        return 0
    fi


    # run access in foreground
    if [[ -z "${action}" ]] ; then
        "${script}" &
    # run access in background
    else
        "${script}" "${action}"
    fi
}

performActionOnScript(){
    local script="$1"
    local action="${2}"

    [ ! -z "${script}" ] || "Script path and action is mandatory for method performActionOnScript"

   # If run router is not enabled, do not perform any action
    if [[ "${script}" == *${ROUTER_NAME}* ]] && ! runRouter ; then
        return 0
    fi

   # If run Observability is not enabled, do not perform any action
    if [[ "${script}" == *${OBSERVABILITY_NAME}* ]] && ! runObservability ; then
        return 0
    fi

    # If run event is not enabled, do not perform any action
    if [[ "${script}" == *${EVENT_NAME}* ]] && ! runEvent ; then
        return 0
    fi

    # If run metadata is not enabled, do not perform any action
    if [[ "${script}" == *${METADATA_NAME}* ]] && ! runMetadata ; then
        return 0
    fi

    # If run frontend is not enabled, do not perform any action
    if [[ "${script}" == *${FRONTEND_NAME}* ]] && ! runFrontend ; then
        return 0
    fi

    # If run JFConnect is not enabled, do not perform any action
    if [[ "${script}" == *${JFCONNECT_NAME}* ]] && ! runJFConnect ; then
        return 0
    fi

    # If run JFConnect is not enabled, do not perform any action
    if [[ "${script}" == *${EVIDENCE_NAME}* ]] && ! runEvidence ; then
        return 0
    fi

    if [[ -f "${script}" ]] ; then
        chmod +x "${script}"
        if [[ "${script}" == *${ACCESS_NAME}* ]]; then
            runAccessScript "${script}" "${action}"
        else
            . "${script}" "${action}"
        fi
    fi
}

createArtSvcPid(){
    # Create pid folder if needed
    if [ ! -d ${CATALINA_PID_FOLDER} ]; then
        logger "Creating ${CATALINA_PID_FOLDER}"
        createDir "${CATALINA_PID_FOLDER}" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}"
    fi

    # Get the PID from the CATALINA_PID generated by Tomcat and copy it to JF_ARTIFACTORY_PID
    if [ ! -f "${CATALINA_PID}" ]; then
        errorExit "Tomcat PID file (${CATALINA_PID}) not found. Unable to determine Artifactory java PID"
    fi

    cp -f ${CATALINA_PID} ${JF_ARTIFACTORY_PID}

    logger "Artifactory running with PID $(cat ${JF_ARTIFACTORY_PID})"
}

# NOTE : Move this to installer common once other products are ready for the change
# Set target directory to be owned by service
# This will expect JF_PRODUCT_HOME/var to be a link
setVarLinkOwnership(){
    local user=${1}
    local group=${2}
    local varLink=${3:-${JF_PRODUCT_HOME}/var}
    local defaultTargetVar=${4}
    local curTargetVar=
    local newTargetVar=
    local targetVar=
    local isCustomDataSet="no"
    local nonRecursiveFlag="yes"

    if [ ! -z "${JF_PRODUCT_VAR}" ]; then
        newTargetVar=${JF_PRODUCT_VAR}
        isCustomDataSet="yes"
    else
        newTargetVar=${defaultTargetVar}
    fi

    if [[ -z "${user}"  || -z "${group}" || -z "${varLink}" || -z "${defaultTargetVar}" ]]; then
        errorExit "A user, group, varLink and defaultTargetVar is mandatory to set ownership on JF_PRODUCT_HOME/var"
    fi

    # Handle if a non link exists as $varLink
    if [[ ! -L "${varLink}" && ( -f "${varLink}" || -d "${varLink}" ) ]]; then
        local timestamp=$(echo "$(date '+%T')" | tr -d ":")
        local currentTime="$(date '+%Y%m%d').${timestamp}"
        local backup="${varLink}.backup.${currentTime}"
        logger "Found a file/directory named var under ${JF_PRODUCT_HOME}, this needs to be a link pointing to data directory (default : ${defaultTargetVar}). A backup of this will be created with name ${backup}"
        mv -f "${varLink}" "${backup}" || errorExit "Could not move ${varLink}, command : mv -f ${varLink} ${varLink}.backup.${currentTime}"
    fi

    # Readlink will give the same path as response if it does not exist
    curTargetVar=$(readlink -f ${varLink} 2>/dev/null)

    if [[ "${curTargetVar}" == *"${varLink}"* ]]; then
        logger "Creating a symlink from ${varLink} pointing to directory ${newTargetVar}"
        createDir "${newTargetVar}" "${user}" "${group}"
        ln -s "${newTargetVar}" "${varLink}"                         || errorExit "Failed to link data directory to JF_PRODUCT_HOME/var, command : ln -s \"${newTargetVar}\" \"${varLink}\""
        io_setOwnership "${varLink}" "${user}" "${group}"
    else
        # If custom data is not set, use link that is read to create and change permission of target directory
        [[ "${isCustomDataSet}" == "no" ]] && targetVar="${curTargetVar}" || targetVar="${newTargetVar}"

        
        createDir "${targetVar}" "${user}" "${group}"

        if [[ "${isCustomDataSet}" == "yes" && "${curTargetVar}" != "${newTargetVar}" ]]; then
            bannerImportant "${varLink} is linked to ${curTargetVar}, this will be changed to point to new location ${newTargetVar}
Please move all files and folders from ${curTargetVar} to ${newTargetVar}
Data directory can be controlled using environment variable JF_PRODUCT_VAR"

            [ -L "${varLink}" ] && rm -f "${varLink}" || true
            ln -s "${newTargetVar}" "${varLink}"      || errorExit "Failed to link data directory to JF_PRODUCT_HOME/var, command : ln -s \"${newTargetVar}\" \"${varLink}\" "
            io_setOwnership "${varLink}" "${user}" "${group}"
        fi
    fi
}

rpmDebStartupActions() {
    checkULimits "${MIN_MAX_OPEN_FILES}" "${MIN_MAX_OPEN_PROCESSES}"
    validateSystemYaml
    validateDbconnection "${JF_PRODUCT_HOME}"
    addExtraJavaArgs
    setupNodeDetails
    if [ -L "${JF_PRODUCT_HOME}/var" ]; then
        local JF_PRODUCT_DATA_INTERNAL="/var/opt/jfrog/artifactory"
        setVarLinkOwnership "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}" "${JF_PRODUCT_HOME}/var" "${JF_PRODUCT_DATA_INTERNAL}" 
    fi
    configureServerXml
    prepareTomcat    
    syncEtc
    bootstrapJavaSecurityFile
    prioritizeCustomJoinKey
    changeArtOwnership "${JF_PRODUCT_HOME}/app"
    [ -d ${JF_PRODUCT_HOME}/var/etc ] && changeArtOwnership "${JF_PRODUCT_HOME}/var/etc" || true
    exportEnv "shared"
    exportEnv "${ARTIFACTORY_NAME}"
    exportEnv "${ACCESS_NAME}"
    addCertsToJavaKeystore
    if runAccessOnArtifactoryTomcat; then
        local changeOwnershipAfterCopy="true"
        copyDerbyDataToAccess "${changeOwnershipAfterCopy}"
    fi
    setRouterToplogy
    displayEnv
    [ -d ${JF_PRODUCT_HOME}/app/third-party/java ] && chmod -R 775 ${JF_PRODUCT_HOME}/app/third-party/java
    testOwnership "${JF_PRODUCT_HOME}/var" "${JF_ARTIFACTORY_USER}" "${JF_ARTIFACTORY_GROUP}"
}
