#!/usr/bin/env ash

# ============LICENSE_START=======================================================
# ONAP
# ================================================================================
# Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved.
# Modifications Copyright (C) 2020 Bell Canada.
# ================================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============LICENSE_END=========================================================

source ${POLICY_HOME}/etc/profile.d/env.sh

##############################################################################
# Usage: usage
##############################################################################

function usage() {
    echo
    echo -e "syntax: $(basename "$0") "
    echo -e "\t [-f|-l|-d]"
    echo -e "\t -s <custom-settings> "
    echo -e "\t -a <artifact> "
    echo
    echo -e "Options:"
    echo -e "\t -f|--file-repo: deploy in the file repository"
    echo -e "\t -l|--local-repo: install in the local repository"
    echo -e "\t -d|--dependencies: install dependencies in the local repository"
    echo -e "\t -s|--settings: custom settings.xml"
    echo -e "\t -a|--artifact: file artifact (jar or pom) to deploy and/or install"
    echo
    echo
}

##############################################################################
# Usage: init <artifact>
#
# If the artifact is a jar, this function extracts the maven metadata for
# consumption in this script.
#
# As a result the global variables will be set:
# WORKING_DIR: working directory with extracted files.
# WORKING_POM: pom file location
# WORKING_POM_PROPERTIES: pom properties file location
##############################################################################

function init
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- init $* --"
        set -x
    fi

    local artifact="${1}"
    if [ ! -f "${artifact}" ]; then
        echo "${artifact}: artifact does not exist"
        return 1
    fi

    if [ "${artifact}" = "${artifact%.jar}" ]; then
        return 0
    fi

    local dir=$(mktemp -d)
    local jar="${artifact##*/}"

    CURRENT_DIR=$PWD
    WORKING_DIR=$(realpath "${dir}")

    cp -p "${artifact}" "${WORKING_DIR}/${jar}"
    cd "${WORKING_DIR}"

    local rc=0

    # determine name of 'pom' file within JAR
    local pom=$(jar tf "${jar}" META-INF | grep '/pom\.xml$' | head -1)
    if [ -n "${pom}" ] ; then
        jar xf "${jar}" "${pom}"
        WORKING_POM=$(realpath "${pom}")
    else
        echo "${artifact}: pom not found"
    fi

    local pomProperties=$(jar tf "${jar}" META-INF | grep '/pom\.properties$' | head -1)
    if [ -n "${pomProperties}" ]; then
        jar xf "${jar}" "${pomProperties}"
        WORKING_POM_PROPERTIES=$(realpath ${pomProperties})
        sed -i 's/\r$//' "${WORKING_POM_PROPERTIES}"
        source "${WORKING_POM_PROPERTIES}"
        echo "${artifact}: sourcing in ${WORKING_POM_PROPERTIES}"
    else
        echo "${artifact}: pom.properties not found"
        if [ -n "${WORKING_POM}" ]; then
            if ! getPomAttributes "${WORKING_POM}" artifactId groupId version ; then
                echo "${WORKING_POM}: cannot extract maven coordinates"
                rc=1
            fi
        else
            echo "${artifact}: cannot extract maven coordinates"
            rc=1
        fi
    fi
    if [ -z "${version}" ] || [ -z "${groupId}" ] || [ -z "${artifactId}" ]; then
        echo "${artifact}: some coordinates cannot be extracted"
        rc=1
    fi

    echo "${artifact}: coordinates ${groupId}:${artifactId}:${version}"
    cd ${CURRENT_DIR}

    return ${rc}
}

##############################################################################
# Usage: cleanup
#
# Clean up temporary resources.
##############################################################################

function cleanup
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- cleanup $* --"
        set -x
    fi

    if [ -n "${WORKING_DIR}" ]; then
        rm -rf "${WORKING_DIR}"
    fi
}

##############################################################################
# Usage: getPomAttributes <pom-file> <attribute> ...
#
# This function performs simplistic parsing of a 'pom.xml' file, extracting
# the specified attributes (e.g. 'groupId', 'artifactId', 'version'). The
# attributes are returned as environment variables with the associated name
##############################################################################

function getPomAttributes
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- getPomAttributes $* --"
        set -x
    fi

    local file="$1"
    if [ ! -f "${file}" ]; then
        echo "${file}: file does not exist"
        return 1
    fi

    local rval=0 attr value
    shift

    for attr in "$@" ; do
        # Try to fetch the parameter associated with the 'pom.xml' file.
        # Initially, the 'parent' element is excluded. If the desired
        # parameter is not found, the 'parent' element is included in the
        # second attempt.
        value=$(sed -n \
            -e '/<parent>/,/<\/parent>/d' \
            -e '/<dependencies>/,/<\/dependencies>/d' \
            -e '/<build>/,/<\/build>/d' \
            -e '/<profiles>/,/<\/profiles>/d' \
            -e '/<description>/,/<\/description>/d' \
            -e '/<packaging>/,/<\/packaging>/d' \
            -e '/<modelVersion>/,/<\/modelVersion>/d' \
            -e '/<properties>/,/<\/properties>/d' \
            -e "/^[ \t]*<${attr}>\([^<]*\)<\/${attr}>.*/{s//\1/p;}" \
            <"${file}")

        if [ -z "${value}" ]; then
            # need to check parent for parameter
            value=$(sed -n \
                -e '/<dependencies>/,/<\/dependencies>/d' \
                -e '/<build>/,/<\/build>/d' \
                -e '/<profiles>/,/<\/profiles>/d' \
                -e '/<description>/,/<\/description>/d' \
                -e '/<packaging>/,/<\/packaging>/d' \
                -e '/<modelVersion>/,/<\/modelVersion>/d' \
                -e '/<properties>/,/<\/properties>/d' \
                -e "/^[ \t]*<${attr}>\([^<]*\)<\/${attr}>.*/{s//\1/p;}" \
                <"${file}")

            if [ -z "${value}" ] ; then
                echo "${file}: Can't determine ${attr}"
                rval=1
            fi
        fi

        # the following sets an environment variable with the name referred
        # to by ${attr}
        export ${attr}="${value}"
    done
    return ${rval}
}

##############################################################################
# Usage: setMavenProxyArgs
#
# This function performs parsing of http proxy environment variable if provided,
# extracting the attributes such as proxy host, port, username and password.
# These proxy attributes are set into the global variable for maven proxy
# settings to be used as build arguments with maven commands.
# The http proxy format is: http_proxy="http://username:password@proxy.thing.com:8080"
##############################################################################

function setMavenProxyArgs
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- setMavenProxyArgs $* --"
        set -x
    fi

    if [ -z "${http_proxy}" ]; then
        return 0
    fi

    local proxy_creds="${http_proxy#*//}"
    local proxy="${proxy_creds#*@}"
    local host="${proxy%:*}"
    local port="${proxy#*:}"
    MVN_PROXY_SETTINGS="-DproxyHost=${host} -DproxyPort=${port}"

    if echo "$proxy_creds" | egrep -s '@'; then
        local creds="${proxy_creds%%@*}"
        local username="${creds%:*}"
        local password="${creds#*:}"
        MVN_PROXY_SETTINGS=${MVN_PROXY_SETTINGS}" -DproxyUsername=${username} -DproxyPassword=${password}"
    fi
}

##############################################################################
# Usage: deployJar <jar-file>
#
# This function deploys a JAR file in a repository, as well as
# the 'pom.xml' member it contains.
#################################################################

function deployJar
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- deployJar $* --"
        set -x
    fi

    local file="${1}"

    if [ ! -f "${file}" ]; then
        return 1
    fi

    local repoId repoUrl
    if echo "$version" | egrep -s 'SNAPSHOT'; then
        repoId=${SNAPSHOT_REPOSITORY_ID}
        repoUrl=${SNAPSHOT_REPOSITORY_URL}
    else
        repoId=${RELEASE_REPOSITORY_ID}
        repoUrl=${RELEASE_REPOSITORY_URL}
    fi

    if [ -z "${repoUrl}" ] || [ -z "${repoId}" ]; then
        echo "{file}: no repository id/url to deploy jar"
        return 1
    fi

    echo "${file}: deploying jar artifact to repository ${repoId}: ${repoUrl}"
    echo "${file}: coordinates ${groupId} ${artifactId} ${version}"

    mvn ${CUSTOM_SETTINGS} ${MVN_PROXY_SETTINGS} deploy:deploy-file \
        -Dfile="${file}" \
        -Dversion="${version}" \
        -Dpackaging=jar \
        -DgeneratePom=false \
        -DpomFile="${WORKING_POM}" \
        -DrepositoryId="${repoId}" \
        -Durl="${repoUrl}" \
        -DupdateReleaseInfo=true

    return ${?}
}

##############################################################################
# Usage: deployPom <pom-file>
#
# This function deploys a 'pom.xml' file in the local repository
##############################################################################

function deployPom
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- deployPom $* --"
        set -x
    fi

    local file="${1}"

    if [ ! -f "${file}" ]; then
        return 1
    fi

    if ! getPomAttributes "${file}" artifactId groupId version ; then
        echo "${file}: cannot deploy pom due to missing attributes"
        return 1
    fi

    local repoId repoUrl
    if echo "$version" | egrep -s 'SNAPSHOT'; then
        repoId=${SNAPSHOT_REPOSITORY_ID}
        repoUrl=${SNAPSHOT_REPOSITORY_URL}
    else
        repoId=${RELEASE_REPOSITORY_ID}
        repoUrl=${RELEASE_REPOSITORY_URL}
    fi

    echo "${file}: deploying pom artifact to repository ${repoId}: ${repoUrl}"
    echo "${file}: coordinates ${groupId} ${artifactId} ${version}"

    mvn ${CUSTOM_SETTINGS} ${MVN_PROXY_SETTINGS} deploy:deploy-file \
        -Dfile="${file}" \
        -Dpackaging=pom \
        -DgeneratePom=false \
        -DgroupId="${groupId}" \
        -DartifactId="${artifactId}" \
        -Dversion="${version}" \
        -DrepositoryId="${repoId}" \
        -Durl="${repoUrl}" \
        -DupdateReleaseInfo=true

    return ${?}
}

##############################################################################
# Usage: deployArtifact
#
# This function deploys a maven artifact in a repository
##############################################################################

function deployArtifact
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- deployArtifact $* --"
        set -x
    fi

    local file="${1}"
    if [ -z "${file}" ]; then
        echo "${file}: artifact file not provided"
        return 1
    fi

    if [ ! -f "${file}" ]; then
        echo "${file}: artifact file does not exist"
        return 1
    fi

    case "${file}" in
        *pom.xml|*.pom)
            deployPom "${file}"
            return ${?}
            ;;
        *.jar)
            deployJar "${file}"
            return ${?}
            ;;
        *)  echo "${file}: Don't know how to deploy artifact"
            return 1
            ;;
    esac
}

##############################################################################
# Usage: installJar <artifact-file>
#
# This function installs a jar packaged artifact in the local repository
##############################################################################

function installJar
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- installJar $* --"
        set -x
    fi

    local file="${1}"

    if [ ! -f "${file}" ]; then
        return 1
    fi

    mvn ${CUSTOM_SETTINGS} ${MVN_PROXY_SETTINGS} \
    org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=${file}

    return $?
}

##############################################################################
# Usage: installPom <pom-file>
#
# This function installs a pom file in the local repository
##############################################################################

function installPom
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- installPom $* --"
        set -x
    fi

    local file="${1}"

    if [ ! -f "${file}" ]; then
        return 1
    fi

    mvn ${CUSTOM_SETTINGS} ${MVN_PROXY_SETTINGS} \
        org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file \
        -Dpackaging=pom \
        -Dfile="${file}" \
        -DpomFile="${file}"

    return $?
}

##############################################################################
# Usage: installArtifact
#
# This function installs a maven artifacts in the local repository
##############################################################################

function installArtifact
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- installArtifact $* --"
        set -x
    fi

    local file="${1}"
    if [ -z "${file}" ]; then
        echo "${file}: artifact file not provided"
        return 1
    fi

    if [ ! -f "${file}" ]; then
        echo "${file}: artifact file does not exist"
        return 1
    fi
    case "${file}" in
        *pom.xml|*.pom)
            installPom "${file}"
            return ${?}
            ;;
        *.jar)
            installJar "${file}"
            return ${?}
            ;;
        *)  echo "${file}: Don't know how to install the artifact"
            return 1
            ;;
    esac
}

##############################################################################
# Usage: installDependencies <pom-file>
#
# This function installs the dependencies of an artifact in the file or
# local repository
##############################################################################

function installDependencies
{
    if [ "${DEBUG}" = "y" ]; then
        echo "-- installDependencies $* --"
        set -x
    fi

    local file="${1}"

    if [ ! -f "${file}" ]; then
        return 1
    fi

    if [ -z "${DEPENDENCY_REPO_URL}" ]; then
        echo "${file}: no repo url to install dependencies"
        return 1
    fi

    echo "${file}: deploying dependencies from repository ${DEPENDENCY_REPO_URL}"
    echo "${file}: coordinates ${groupId} ${artifactId} ${version}"

    mvn ${CUSTOM_SETTINGS} ${MVN_PROXY_SETTINGS} \
        org.apache.maven.plugins:maven-dependency-plugin:3.1.1:get \
        -DartifactId="${artifactId}" \
        -DgroupId="${groupId}" \
        -Dversion="${version}" \
        -DremoteRepositories="${DEPENDENCY_REPO_URL}"

    return ${?}
}

##############################################################################
# MAIN
##############################################################################

if [ "${DEBUG}" = "y" ]; then
    echo "-- $0 $* --"
    set -x
fi

# reset globals

unset ARTIFACT_FILE
unset LOCAL_INSTALL
unset INSTALL_DEPS
unset FILE_REPO_INSTALL
unset WORKING_DIR
unset WORKING_POM
unset WORKING_POM_PROPERTIES
unset DEPENDENCY_REPO_URL
unset SETTINGS_FILE
unset CUSTOM_SETTINGS
unset MVN_PROXY_SETTINGS

# process input

until [ -z "$1" ]; do
    case $1 in
        -a|--artifact)     shift
                           ARTIFACT_FILE=$1
                           ;;
        -s|--settings)     shift
                           SETTINGS_FILE=$1
                           ;;
        -l|--local-repo)   LOCAL_INSTALL="true"
                           ;;
        -d|--dependencies) INSTALL_DEPS="true"
                           ;;
        -f|--file-repo)    FILE_REPO_INSTALL="true"
                           ;;
        *)                 usage
                           exit 1
                           ;;
    esac
    shift
done

if [ -z "${ARTIFACT_FILE}" ]; then
    echo "No artifact file provided: $*"
    usage
    exit 1
fi

if [ -n "${SETTINGS_FILE}" ]; then
    CUSTOM_SETTINGS="--settings=${SETTINGS_FILE}"
fi

# Set proxy attributes into MVN_PROXY_SETTINGS variable
setMavenProxyArgs

# retval has the count of failed operations

retval=0

# initialize

init "${ARTIFACT_FILE}"
retval=$?
if [ ${retval} -ne 0 ]; then
    cleanup
    exit ${retval}
fi

# remote repo deploy operation
#
# SNAPSHOT_REPOSITORY_URL and RELEASE_REPOSITORY_URL
# are pre-existing environmental variables (base.conf)

if [ -n "${SNAPSHOT_REPOSITORY_URL}" ] || [ -n "${RELEASE_REPOSITORY_URL}" ]; then
    deployArtifact "${ARTIFACT_FILE}"
    retval=$(( retval + ${?} ))
fi

# deploy in file repository

if [ -n "${FILE_REPO_INSTALL}" ]; then
    FILE_REPO_ID="file-repository"
    FILE_REPO_URL="file:${HOME}/.m2/file-repository"

    SNAPSHOT_REPOSITORY_ID="${FILE_REPO_ID}"
    SNAPSHOT_REPOSITORY_URL="${FILE_REPO_URL}"
    RELEASE_REPOSITORY_ID="${FILE_REPO_ID}"
    RELEASE_REPOSITORY_URL="${FILE_REPO_URL}"

    mkdir -p "${FILE_REPO_URL#file:}" 2> /dev/null
    deployArtifact "${ARTIFACT_FILE}"
    retval=$(( retval + ${?} ))
fi

# install in local repository

if [ -n "${LOCAL_INSTALL}" ]; then
    installArtifact "${ARTIFACT_FILE}"
    retval=$(( retval + ${?} ))
fi

# install dependencies in local and/or file repositories

if [ -n "${INSTALL_DEPS}" ]; then
    if [ -n "${FILE_REPO_INSTALL}" ]; then
        DEPENDENCY_REPO_URL="${FILE_REPO_URL}"
        installDependencies "${ARTIFACT_FILE}"
        retval=$(( retval + ${?} ))
    fi

    if [ -n "${LOCAL_INSTALL}" ]; then
        DEPENDENCY_REPO_URL="file:${HOME}/.m2/repository"
        installDependencies "${ARTIFACT_FILE}"
        retval=$(( retval + ${?} ))
    fi
fi

cleanup

exit ${retval}