#!/bin/bash if [[ $APPSH_HOME == "" ]] then APPSH_HOME=`dirname "$0"` APPSH_HOME=`cd "$APPSH_HOME/.." && pwd` fi if [ -n "$APPSH_REPO" ] then repo="$APPSH_REPO" else repo="http://repo1.maven.org" fi calculate_md5() { local file="$1"; shift md5sum "$file" | cut -c 1-32 } # TODO: support file:// repositories # TODO: look in the local repository first get() { local url=$1 local file=$2 local exit curl -o $file $url -D curl.tmp exit=`grep "^HTTP/[0-9]\.[0-9] 200 .*" curl.tmp >/dev/null; echo $?` head=`head -n 1 curl.tmp` rm -f curl.tmp if [ "$exit" != 0 ] then echo "Unable to download $url: $head" >&2 exit 1 fi } resolve_snapshot() { local groupId=$1; shift local groupIdSlash=$1; shift local artifactId=$1; shift local version=$1; shift local metadata=$apps/.app/var/download/$groupId-$artifactId-$version-metadata.xml local base_url=$repo/$groupIdSlash/$artifactId/$version get $base_url/maven-metadata.xml $metadata local resolved_version=`xmlstarlet sel -t -m '//snapshotVersion[extension[text()="zip"]]' -v value $metadata` echo $resolved_version } download_artifact() { local file="$1"; shift local url="$1"; shift echo "Downloading $url.md5" get $url.md5 $file.md5 local expected_md5="`cat $file.md5`" if [ -r $file ] then if [ "$expected_md5" == "`calculate_md5 $file`" ] then echo "Artifact already downloaded." else rm -f "$file" fi return 0 fi echo "Downloading artifact: $url" get $url $file local actual_md5="`calculate_md5 $file`" if [ "$expected_md5" == "$actual_md5" ] then echo "Artifact downloaded." else echo "Invalid checksum. Expected $expected_md5, got $actual_md5" >&2 exit 1 fi } method_install_usage() { if [ -n "$1" ] then echo "Error:" "$@" >&2 fi echo "usage: install <-r resolver> -u " >&2 echo "" >&2 echo "Install package from a Maven repository:" >&2 echo " $0 [-n name] [-i instance] instance install -r maven -u groupId:artifactId:version" >&2 echo "" >&2 echo "Install package from a file:" >&2 echo " $0 [-n name] [-i instance] instance install -r file -u file [-v version]" >&2 echo "The version defaults to the current timestamp" >&2 exit 1 } method_install() { local name="$1"; shift local instance="$1"; shift local version local resolver local url local groupId local artifactId local zip_file if [ $# -eq 0 ] then method_install_usage fi while getopts "n:i:v:r:u:" opt do case $opt in n) name=$OPTARG ;; i) instance=$OPTARG ;; v) version=$OPTARG ;; r) resolver=$OPTARG ;; u) url=$OPTARG ;; \?) method_install_usage "Invalid option: -$OPTARG" ;; esac done if [ -z "$name" ] then method_install_usage "Missing required argument: -i name." fi if [ -z "$instance" ] then method_install_usage "Missing required argument: -i instance." fi if [ -z "$resolver" ] then method_install_usage "Missing required option: -r resolver" fi if [ -z "$url" ] then method_install_usage "Missing required option: -u url" fi case "$resolver" in maven) url=`echo $url | tr ":" " "`; set -- $url groupId=$1 artifactId=$2 version=$3 if [ -z "$groupId" -o -z "$artifactId" -o -z "$version" ] then method_install_usage "Invalid Maven url." fi local groupIdSlash=$(echo $groupId | sed "s,\.,/,g") if [ "`echo $version | sed -n s,.*-SNAPSHOT$,SNAPSHOT,p`" == "SNAPSHOT" ] then echo "Resolving version $version..." local resolved_version=`resolve_snapshot $groupId $groupIdSlash $artifactId $version` if [ -z "$resolved_version" ] then echo "Unable to resolve version." exit 1 fi echo "Resolved version $version to $resolved_version" else resolved_version=$version fi zip_file=$apps/.app/var/download/$groupId-$artifactId-$resolved_version.zip artifact_url=$repo/$groupIdSlash/$artifactId/$version/$artifactId-$resolved_version.zip download_artifact "$zip_file" "$artifact_url" ;; file) if [ ! -r "$url" ] then echo "Could not read file: $url" >&2 exit 1 fi # TODO: should the zip file be copied into download/ so that # there's always a local copy? zip_file=$url if [ -z "$version" ] then version=`TZ=UTC date +"%Y%m%d-%H%M%S"` fi resolved_version=$version ;; *) method_install_usage "Invalid resolver type: $resolver" ;; esac if [ -d $name/$instance/versions/$resolved_version ] then echo "Version $resolved_version is already installed" exit 1 fi if [ ! -d $name/$instance ] then echo "Creating instance '$instance' for '$name'" mkdir -p $name/$instance fi mkdir -p $name/$instance/versions/$resolved_version echo "Unpacking..." unzip -q -d $name/$instance/versions/$resolved_version $zip_file if [ ! -d $name/$instance/versions/$resolved_version/root ] then echo "Invalid zip file, did not contain a ./root directory." >&2 exit 1 fi echo "Changing current symlink" rm -f $apps/$name/$instance/current ln -s versions/$resolved_version/root $apps/$name/$instance/current if [ -d $name/$instance/current/bin ] then ( cd $name/$instance/current find bin -type f | xargs chmod +x ) fi ( cd $name/$instance/versions/$resolved_version if [ -d scripts ] then find scripts | xargs chmod +x fi if [ -x scripts/postinstall ] then echo "Running postinstall..." cd root set +e env -i \ PATH=/bin:/usr/bin \ APPSH_APPS=$apps \ APPSH_HOME=$APPSH_HOME \ APPSH_NAME=$name \ APPSH_INSTANCE=$instance \ APPSH_VERSION=$resolved_version \ ../scripts/postinstall set -e ret=`echo $?` if [ "$ret" != 0 ] then echo "Postinstall failed!" exit 1 fi echo "Postinstall completed successfully" fi ) if [ -r $apps/.app/var/list ] then sed "/^$name:$instance/d" $apps/.app/var/list > $apps/.app/var/list.new fi echo "$name:$instance:$version:$url" >> $apps/.app/var/list.new mv $apps/.app/var/list.new $apps/.app/var/list } method_set_current_usage() { if [ -n "$1" ] then echo "Error:" "$@" >&2 fi echo "usage: set-current -v version" >&2 exit 1 } method_set_current() { local name="$1"; shift local instance="$1"; shift local version if [ $# -eq 0 ] then method_set_current_usage fi while getopts "n:i:v:" opt do case $opt in n) name=$OPTARG ;; i) instance=$OPTARG ;; v) version=$OPTARG ;; \?) method_set_current_usage "Invalid option: -$OPTARG" ;; esac done if [ -z "$version" ] then echo "Missing required option -v version." >&2 exit 1 fi assert_is_instance method_set_current_usage "$name" "$instance" "no" if [ ! -d $apps/$name/$instance/versions/$version ] then echo "Invalid version: $version." exit 1 fi rm -f $apps/$name/$instance/current ln -s versions/$version/root $apps/$name/$instance/current return 0 } method_list_usage() { if [ -n "$1" ] then echo "Error:" "$@" >&2 fi echo "usage: list [-n name] [-P field]" >&2 echo "" echo "List all installed applications:" >&2 echo " list" >&2 echo "" echo "List all applications with the selected fields with parseable output:" >&2 echo " list -P instance -P version -n foo" >&2 exit 1 } method_list() { local filter_name="$1"; shift local filter_instance="$1"; shift local mode="pretty" local vars local filter_name while getopts "P:n:i:" opt do case $opt in P) mode="parseable" vars="$vars $OPTARG" ;; n) filter_name=$OPTARG ;; i) filter_instance=$OPTARG ;; \?) method_list_usage "Invalid option: -$OPTARG" ;; esac done if [ ! -r $apps/.app/var/list ] then return fi if [ $mode = "pretty" ] then printf "%-20s %-20s %-20s\n" "Name" "Instance" "Version" list_apps "$filter_name" "$filter_instance" name instance version | (IFS=:; while read name instance version do printf "%-20s %-20s %-20s\n" "$name" "$instance" "$version" done) else list_apps "$filter_name" "$filter_instance" $vars fi } method_list_versions_usage() { if [ -n "$1" ] then echo "Error:" "$@" >&2 fi echo "usage: list-versions -n name -i instance [-P]" >&2 exit 1 } method_list_versions() { local filter_name="$1"; shift local instance="$1"; shift local version local mode="pretty" if [ $# -eq 0 ] then method_list_versions_usage fi while getopts "n:i:P" opt do case $opt in n) name=$OPTARG ;; i) instance=$OPTARG ;; v) version=$OPTARG ;; P) mode="parseable" ;; \?) method_list_versions_usage "Invalid option: -$OPTARG" ;; esac done assert_is_instance method_list_versions_usage "$name" "$instance" "no" if [ $mode = "pretty" ] then echo "Available versions for $name/$instance:" fi find_versions $name $instance return 0 } method_instance_usage() { if [ -n "$1" ] then echo "Error:" $@ >&2 fi echo "usage: $0 instance " >&2 echo "" >&2 echo "Available methods:" >&2 echo " install - Installs an application" >&2 echo " list - List all installed applications" >&2 echo " list-versions - List all available versions for a single application" >&2 echo " set-current - Set the current version" >&2 } method_instance() { local name="$1"; shift local instance="$1"; shift local method="$1" if [ $# -gt 0 ] then shift fi case "$method" in install) method_install "$name" "$instance" "$@" ;; list) method_list "$name" "$instance" "$@" ;; list-versions) method_list_versions "$name" "$instance" "$@" ;; set-current) method_set_current "$name" "$instance" "$@" ;; *) if [ -z "$method" ] then method_instance_usage else method_instance_usage "Unknown method $method" fi ;; esac exit $? }