commit c6700ee096e2e278e95b9f9ee582997fd0214963 Author: Christoph Stahl Date: Fri Apr 19 15:52:01 2024 +0200 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c29439d --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +target/ + +.settings +.project +.classpath + +.idea +*.iml + +.metals +.bloop + +.gradle +build \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..334973c --- /dev/null +++ b/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'java' +apply plugin: 'idea' +apply plugin: 'application' + + +repositories { + mavenCentral() + mavenLocal() + maven { + url "https://repo.akka.io/maven" + } +} + +dependencies { + implementation 'com.typesafe.akka:akka-actor-typed_2.13:2.9.2' + implementation 'ch.qos.logback:logback-classic:1.2.3' + testImplementation 'com.typesafe.akka:akka-actor-testkit-typed_2.13:2.9.2' + testImplementation 'junit:junit:4.13.1' +} + +mainClassName = "com.example.AkkaQuickstart" + +run { + standardInput = System.in +} diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000..9b5b261 --- /dev/null +++ b/build.sbt @@ -0,0 +1,22 @@ +name := "akka-quickstart-java" + +version := "1.0" + +scalaVersion := "2.13.12" + +lazy val akkaVersion = "2.9.2" + +resolvers += "Akka library repository".at("https://repo.akka.io/maven") + +// Run in a separate JVM, to make sure sbt waits until all threads have +// finished before returning. +// If you want to keep the application running while executing other +// sbt tasks, consider https://github.com/spray/sbt-revolver/ +fork := true + +libraryDependencies ++= Seq( + "com.typesafe.akka" %% "akka-actor-typed" % akkaVersion, + "com.typesafe.akka" %% "akka-actor-testkit-typed" % akkaVersion, + "ch.qos.logback" % "logback-classic" % "1.2.3", + "junit" % "junit" % "4.13.1" % Test, + "com.novocode" % "junit-interface" % "0.11" % Test) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..d64cd49 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..1af9e09 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..1aa94a4 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c8c729f --- /dev/null +++ b/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + hello-akka-java + app + 1.0 + + + 2.9.2 + + + + + akka-repository + Akka library repository + https://repo.akka.io/maven + + + + + + com.typesafe.akka + akka-actor-typed_2.13 + ${akka.version} + + + ch.qos.logback + logback-classic + 1.2.13 + + + com.typesafe.akka + akka-actor-testkit-typed_2.13 + ${akka.version} + test + + + junit + junit + 4.13.2 + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 17 + 17 + + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + java + + -classpath + + com.example.AkkaQuickstart + + + + + + diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 0000000..04267b1 --- /dev/null +++ b/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.9.9 diff --git a/sbt b/sbt new file mode 100755 index 0000000..efdfda6 --- /dev/null +++ b/sbt @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +./sbt-dist/bin/sbt "$@" \ No newline at end of file diff --git a/sbt-dist/bin/sbt b/sbt-dist/bin/sbt new file mode 100755 index 0000000..a3f9443 --- /dev/null +++ b/sbt-dist/bin/sbt @@ -0,0 +1,605 @@ +#!/usr/bin/env bash + +set +e +declare -a residual_args +declare -a java_args +declare -a scalac_args +declare -a sbt_commands +declare -a sbt_options +declare -a print_version +declare -a print_sbt_version +declare -a print_sbt_script_version +declare java_cmd=java +declare java_version +declare init_sbt_version=_to_be_replaced +declare sbt_default_mem=1024 +declare -r default_sbt_opts="" +declare -r default_java_opts="-Dfile.encoding=UTF-8" +declare sbt_verbose= +declare sbt_debug= + +### ------------------------------- ### +### Helper methods for BASH scripts ### +### ------------------------------- ### + +# Bash reimplementation of realpath to return the absolute path +realpathish () { +( + TARGET_FILE="$1" + FIX_CYGPATH="$2" + + cd "$(dirname "$TARGET_FILE")" + TARGET_FILE=$(basename "$TARGET_FILE") + + COUNT=0 + while [ -L "$TARGET_FILE" -a $COUNT -lt 100 ] + do + TARGET_FILE=$(readlink "$TARGET_FILE") + cd "$(dirname "$TARGET_FILE")" + TARGET_FILE=$(basename "$TARGET_FILE") + COUNT=$(($COUNT + 1)) + done + + # make sure we grab the actual windows path, instead of cygwin's path. + if [[ "x$FIX_CYGPATH" != "x" ]]; then + echo "$(cygwinpath "$(pwd -P)/$TARGET_FILE")" + else + echo "$(pwd -P)/$TARGET_FILE" + fi +) +} + +# Uses uname to detect if we're in the odd cygwin environment. +is_cygwin() { + local os=$(uname -s) + case "$os" in + CYGWIN*) return 0 ;; + MINGW*) return 0 ;; + MSYS*) return 0 ;; + *) return 1 ;; + esac +} + +# TODO - Use nicer bash-isms here. +CYGWIN_FLAG=$(if is_cygwin; then echo true; else echo false; fi) + +# This can fix cygwin style /cygdrive paths so we get the +# windows style paths. +cygwinpath() { + local file="$1" + if [[ "$CYGWIN_FLAG" == "true" ]]; then #" + echo $(cygpath -w $file) + else + echo $file + fi +} + + +declare -r sbt_bin_dir="$(dirname "$(realpathish "$0")")" +declare -r sbt_home="$(dirname "$sbt_bin_dir")" + +echoerr () { + echo 1>&2 "$@" +} +vlog () { + [[ $sbt_verbose || $sbt_debug ]] && echoerr "$@" +} +dlog () { + [[ $sbt_debug ]] && echoerr "$@" +} + +jar_file () { + echo "$(cygwinpath "${sbt_home}/bin/sbt-launch.jar")" +} + +acquire_sbt_jar () { + sbt_jar="$(jar_file)" + + if [[ ! -f "$sbt_jar" ]]; then + echoerr "Could not find launcher jar: $sbt_jar" + exit 2 + fi +} + +rt_export_file () { + echo "${sbt_bin_dir}/java9-rt-export.jar" +} + +# execRunner should be called only once to give up control to java +execRunner () { + # print the arguments one to a line, quoting any containing spaces + [[ $sbt_verbose || $sbt_debug ]] && echo "# Executing command line:" && { + for arg; do + if printf "%s\n" "$arg" | grep -q ' '; then + printf "\"%s\"\n" "$arg" + else + printf "%s\n" "$arg" + fi + done + echo "" + } + + if [[ "$CYGWIN_FLAG" == "true" ]]; then + # In cygwin we loose the ability to re-hook stty if exec is used + # https://github.com/sbt/sbt-launcher-package/issues/53 + "$@" + else + exec "$@" + fi +} + +addJava () { + dlog "[addJava] arg = '$1'" + java_args=( "${java_args[@]}" "$1" ) +} +addSbt () { + dlog "[addSbt] arg = '$1'" + sbt_commands=( "${sbt_commands[@]}" "$1" ) +} +addResidual () { + dlog "[residual] arg = '$1'" + residual_args=( "${residual_args[@]}" "$1" ) +} +addDebugger () { + addJava "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$1" +} + +addMemory () { + dlog "[addMemory] arg = '$1'" + # evict memory related options + local xs=("${java_args[@]}") + java_args=() + for i in "${xs[@]}"; do + if ! [[ "${i}" == *-Xmx* ]] && ! [[ "${i}" == *-Xms* ]] && ! [[ "${i}" == *-XX:MaxPermSize* ]] && ! [[ "${i}" == *-XX:MaxMetaspaceSize* ]] && ! [[ "${i}" == *-XX:ReservedCodeCacheSize* ]]; then + java_args+=("${i}") + fi + done + local ys=("${sbt_options[@]}") + sbt_options=() + for i in "${ys[@]}"; do + if ! [[ "${i}" == *-Xmx* ]] && ! [[ "${i}" == *-Xms* ]] && ! [[ "${i}" == *-XX:MaxPermSize* ]] && ! [[ "${i}" == *-XX:MaxMetaspaceSize* ]] && ! [[ "${i}" == *-XX:ReservedCodeCacheSize* ]]; then + sbt_options+=("${i}") + fi + done + # a ham-fisted attempt to move some memory settings in concert + local mem=$1 + local codecache=$(( $mem / 8 )) + (( $codecache > 128 )) || codecache=128 + (( $codecache < 512 )) || codecache=512 + local class_metadata_size=$(( $codecache * 2 )) + if [[ -z $java_version ]]; then + java_version=$(jdk_version) + fi + + addJava "-Xms${mem}m" + addJava "-Xmx${mem}m" + addJava "-Xss4M" + addJava "-XX:ReservedCodeCacheSize=${codecache}m" + (( $java_version >= 8 )) || addJava "-XX:MaxPermSize=${class_metadata_size}m" +} + +addDefaultMemory() { + # if we detect any of these settings in ${JAVA_OPTS} or ${JAVA_TOOL_OPTIONS} we need to NOT output our settings. + # The reason is the Xms/Xmx, if they don't line up, cause errors. + if [[ "${java_args[@]}" == *-Xmx* ]] || \ + [[ "${java_args[@]}" == *-Xms* ]] || \ + [[ "${java_args[@]}" == *-XX:+UseCGroupMemoryLimitForHeap* ]] || \ + [[ "${java_args[@]}" == *-XX:MaxRAM* ]] || \ + [[ "${java_args[@]}" == *-XX:InitialRAMPercentage* ]] || \ + [[ "${java_args[@]}" == *-XX:MaxRAMPercentage* ]] || \ + [[ "${java_args[@]}" == *-XX:MinRAMPercentage* ]]; then + : + elif [[ "${JAVA_TOOL_OPTIONS}" == *-Xmx* ]] || \ + [[ "${JAVA_TOOL_OPTIONS}" == *-Xms* ]] || \ + [[ "${JAVA_TOOL_OPTIONS}" == *-XX:+UseCGroupMemoryLimitForHeap* ]] || \ + [[ "${JAVA_TOOL_OPTIONS}" == *-XX:MaxRAM* ]] || \ + [[ "${JAVA_TOOL_OPTIONS}" == *-XX:InitialRAMPercentage* ]] || \ + [[ "${JAVA_TOOL_OPTIONS}" == *-XX:MaxRAMPercentage* ]] || \ + [[ "${JAVA_TOOL_OPTIONS}" == *-XX:MinRAMPercentage* ]] ; then + : + elif [[ "${sbt_options[@]}" == *-Xmx* ]] || \ + [[ "${sbt_options[@]}" == *-Xms* ]] || \ + [[ "${sbt_options[@]}" == *-XX:+UseCGroupMemoryLimitForHeap* ]] || \ + [[ "${sbt_options[@]}" == *-XX:MaxRAM* ]] || \ + [[ "${sbt_options[@]}" == *-XX:InitialRAMPercentage* ]] || \ + [[ "${sbt_options[@]}" == *-XX:MaxRAMPercentage* ]] || \ + [[ "${sbt_options[@]}" == *-XX:MinRAMPercentage* ]] ; then + : + else + addMemory $sbt_default_mem + fi +} + +require_arg () { + local type="$1" + local opt="$2" + local arg="$3" + if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then + echo "$opt requires <$type> argument" + exit 1 + fi +} + +is_function_defined() { + declare -f "$1" > /dev/null +} + +# parses JDK version from the -version output line. +# 8 for 1.8.0_nn, 9 for 9-ea etc, and "no_java" for undetected +jdk_version() { + local result + local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n') + local IFS=$'\n' + for line in $lines; do + if [[ (-z $result) && ($line = *"version \""*) ]] + then + local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q') + # on macOS sed doesn't support '?' + if [[ $ver = "1."* ]] + then + result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q') + else + result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q') + fi + fi + done + if [[ -z $result ]] + then + result=no_java + fi + echo "$result" +} + +# Extracts the preloaded directory from either -Dsbt.preloaded or -Dsbt.global.base +# properties by looking at: +# - _JAVA_OPTIONS environment variable, +# - SBT_OPTS environment variable, +# - JAVA_OPTS environment variable and +# - properties set by command-line options +# in that order. The last one will be chosen such that `sbt.preloaded` is +# always preferred over `sbt.global.base`. +getPreloaded() { + local -a _java_options_array + local -a sbt_opts_array + local -a java_opts_array + read -a _java_options_array <<< "$_JAVA_OPTIONS" + read -a sbt_opts_array <<< "$SBT_OPTS" + read -a java_opts_array <<< "$JAVA_OPTS" + + local args_to_check=( + "${_java_options_array[@]}" + "${sbt_opts_array[@]}" + "${java_opts_array[@]}" + "${java_args[@]}") + local via_global_base="$HOME/.sbt/preloaded" + local via_explicit="" + + for opt in "${args_to_check[@]}"; do + if [[ "$opt" == -Dsbt.preloaded=* ]]; then + via_explicit="${opt#-Dsbt.preloaded=}" + elif [[ "$opt" == -Dsbt.global.base=* ]]; then + via_global_base="${opt#-Dsbt.global.base=}/preloaded" + fi + done + + echo "${via_explicit:-${via_global_base}}" +} + +syncPreloaded() { + local source_preloaded="$sbt_home/lib/local-preloaded/" + local target_preloaded="$(getPreloaded)" + if [[ "$init_sbt_version" == "" ]]; then + # FIXME: better $init_sbt_version detection + init_sbt_version="$(ls -1 "$source_preloaded/org/scala-sbt/sbt/")" + fi + [[ -f "$target_preloaded/org/scala-sbt/sbt/$init_sbt_version/" ]] || { + # lib/local-preloaded exists (This is optional) + [[ -d "$source_preloaded" ]] && { + command -v rsync >/dev/null 2>&1 && { + mkdir -p "$target_preloaded" + rsync --recursive --links --perms --times --ignore-existing "$source_preloaded" "$target_preloaded" || true + } + } + } +} + +# Detect that we have java installed. +checkJava() { + local required_version="$1" + # Now check to see if it's a good enough version + local good_enough="$(expr $java_version ">=" $required_version)" + if [[ "$java_version" == "" ]]; then + echo + echo "No Java Development Kit (JDK) installation was detected." + echo Please go to http://www.oracle.com/technetwork/java/javase/downloads/ and download. + echo + exit 1 + elif [[ "$good_enough" != "1" ]]; then + echo + echo "The Java Development Kit (JDK) installation you have is not up to date." + echo $script_name requires at least version $required_version+, you have + echo version $java_version + echo + echo Please go to http://www.oracle.com/technetwork/java/javase/downloads/ and download + echo a valid JDK and install before running $script_name. + echo + exit 1 + fi +} + +copyRt() { + local at_least_9="$(expr $java_version ">=" 9)" + if [[ "$at_least_9" == "1" ]]; then + rtexport=$(rt_export_file) + # The grep for java9-rt-ext- matches the filename prefix printed in Export.java + java9_ext=$("$java_cmd" "${sbt_options[@]}" "${java_args[@]}" \ + -jar "$rtexport" --rt-ext-dir | grep java9-rt-ext-) + java9_rt=$(echo "$java9_ext/rt.jar") + vlog "[copyRt] java9_rt = '$java9_rt'" + if [[ ! -f "$java9_rt" ]]; then + echo copying runtime jar... + mkdir -p "$java9_ext" + "$java_cmd" \ + "${sbt_options[@]}" \ + "${java_args[@]}" \ + -jar "$rtexport" \ + "${java9_rt}" + fi + addJava "-Dscala.ext.dirs=${java9_ext}" + fi +} + +run() { + java_args=($JAVA_OPTS) + sbt_options0=(${SBT_OPTS:-$default_sbt_opts}) + + # Split SBT_OPTS into options/commands + miniscript=$(map_args "${sbt_options0[@]}") && eval "${miniscript/options/sbt_options}" && \ + eval "${miniscript/commands/sbt_additional_commands}" + + # Combine command line options/commands and commands from SBT_OPTS + miniscript=$(map_args "$@") && eval "${miniscript/options/cli_options}" && eval "${miniscript/commands/cli_commands}" + args1=( "${cli_options[@]}" "${cli_commands[@]}" "${sbt_additional_commands[@]}" ) + + # process the combined args, then reset "$@" to the residuals + process_args "${args1[@]}" + vlog "[sbt_options] $(declare -p sbt_options)" + + addDefaultMemory + set -- "${residual_args[@]}" + argumentCount=$# + + # Copy preloaded repo to user's preloaded directory + syncPreloaded + + # no jar? download it. + [[ -f "$sbt_jar" ]] || acquire_sbt_jar "$sbt_version" || { + # still no jar? uh-oh. + echo "Download failed. Obtain the sbt-launch.jar manually and place it at $sbt_jar" + exit 1 + } + + # TODO - java check should be configurable... + checkJava "6" + + # Java 9 support + copyRt + + # If we're in cygwin, we should use the windows config, and terminal hacks + if [[ "$CYGWIN_FLAG" == "true" ]]; then #" + stty -icanon min 1 -echo > /dev/null 2>&1 + addJava "-Djline.terminal=jline.UnixTerminal" + addJava "-Dsbt.cygwin=true" + fi + + if [[ $print_sbt_version ]]; then + execRunner "$java_cmd" -jar "$sbt_jar" "sbtVersion" | tail -1 | sed -e 's/\[info\]//g' + elif [[ $print_sbt_script_version ]]; then + echo "$init_sbt_version" + elif [[ $print_version ]]; then + execRunner "$java_cmd" -jar "$sbt_jar" "sbtVersion" | tail -1 | sed -e 's/\[info\]/sbt version in this project:/g' + echo "sbt script version: $init_sbt_version" + else + # run sbt + execRunner "$java_cmd" \ + "${java_args[@]}" \ + "${sbt_options[@]}" \ + -jar "$sbt_jar" \ + "${sbt_commands[@]}" \ + "${residual_args[@]}" + fi + + exit_code=$? + + # Clean up the terminal from cygwin hacks. + if [[ "$CYGWIN_FLAG" == "true" ]]; then #" + stty icanon echo > /dev/null 2>&1 + fi + exit $exit_code +} + +declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" +declare -r sbt_opts_file=".sbtopts" +declare -r etc_sbt_opts_file="/etc/sbt/sbtopts" +# this allows /etc/sbt/sbtopts location to be changed +declare -r etc_file="${SBT_ETC_FILE:-$etc_sbt_opts_file}" +declare -r dist_sbt_opts_file="${sbt_home}/conf/sbtopts" +declare -r win_sbt_opts_file="${sbt_home}/conf/sbtconfig.txt" + +usage() { + cat < path to global settings/plugins directory (default: ~/.sbt) + --sbt-boot path to shared boot directory (default: ~/.sbt/boot in 0.11 series) + --ivy path to local Ivy repository (default: ~/.ivy2) + --mem set memory options (default: $sbt_default_mem) + --no-share use all local caches; no sharing + --no-global uses global caches, but does not use global ~/.sbt directory. + --jvm-debug Turn on JVM debugging, open at the given port. + --batch disable interactive mode + + # sbt version (default: from project/build.properties if present, else latest release) + --sbt-version use the specified version of sbt + --sbt-jar use the specified jar as the sbt launcher + + # java version (default: java from PATH, currently $(java -version 2>&1 | grep version)) + --java-home alternate JAVA_HOME + + # jvm options and output control + JAVA_OPTS environment variable, if unset uses "$default_java_opts" + .jvmopts if this file exists in the current directory, its contents + are appended to JAVA_OPTS + SBT_OPTS environment variable, if unset uses "$default_sbt_opts" + .sbtopts if this file exists in the current directory, its contents + are prepended to the runner args + /etc/sbt/sbtopts if this file exists, it is prepended to the runner args + -Dkey=val pass -Dkey=val directly to the java runtime + -J-X pass option -X directly to the java runtime + (-J is stripped) + -S-X add -X to sbt's scalacOptions (-S is stripped) + +In the case of duplicated or conflicting options, the order above +shows precedence: JAVA_OPTS lowest, command line options highest. +EOM +} + +process_my_args () { + while [[ $# -gt 0 ]]; do + case "$1" in + -batch|--batch) exec + + -sbt-create|--sbt-create) sbt_create=true && shift ;; + + new) sbt_new=true && addResidual "$1" && shift ;; + + *) addResidual "$1" && shift ;; + esac + done + + # Now, ensure sbt version is used. + [[ "${sbt_version}XXX" != "XXX" ]] && addJava "-Dsbt.version=$sbt_version" + + # Confirm a user's intent if the current directory does not look like an sbt + # top-level directory and neither the -sbt-create option nor the "new" + # command was given. + [[ -f ./build.sbt || -d ./project || -n "$sbt_create" || -n "$sbt_new" ]] || { + echo "[warn] Neither build.sbt nor a 'project' directory in the current directory: $(pwd)" + while true; do + echo 'c) continue' + echo 'q) quit' + + read -p '? ' || exit 1 + case "$REPLY" in + c|C) break ;; + q|Q) exit 1 ;; + esac + done + } +} + +## map over argument array. this is used to process both command line arguments and SBT_OPTS +map_args () { + local options=() + local commands=() + while [[ $# -gt 0 ]]; do + case "$1" in + -no-colors|--no-colors) options=( "${options[@]}" "-Dsbt.log.noformat=true" ) && shift ;; + -timings|--timings) options=( "${options[@]}" "-Dsbt.task.timings=true" "-Dsbt.task.timings.on.shutdown=true" ) && shift ;; + -traces|--traces) options=( "${options[@]}" "-Dsbt.traces=true" ) && shift ;; + --supershell=*) options=( "${options[@]}" "-Dsbt.supershell=${1:13}" ) && shift ;; + -supershell=*) options=( "${options[@]}" "-Dsbt.supershell=${1:12}" ) && shift ;; + --color=*) options=( "${options[@]}" "-Dsbt.color=${1:8}" ) && shift ;; + -color=*) options=( "${options[@]}" "-Dsbt.color=${1:7}" ) && shift ;; + -no-share|--no-share) options=( "${options[@]}" "$noshare_opts" ) && shift ;; + -no-global|--no-global) options=( "${options[@]}" "-Dsbt.global.base=$(pwd)/project/.sbtboot" ) && shift ;; + -sbt-boot|--sbt-boot) require_arg path "$1" "$2" && options=( "${options[@]}" "-Dsbt.boot.directory=$2" ) && shift 2 ;; + -sbt-dir|--sbt-dir) require_arg path "$1" "$2" && options=( "${options[@]}" "-Dsbt.global.base=$2" ) && shift 2 ;; + -debug|--debug) commands=( "${commands[@]}" "-debug" ) && shift ;; + -debug-inc|--debug-inc) options=( "${options[@]}" "-Dxsbt.inc.debug=true" ) && shift ;; + *) options=( "${options[@]}" "$1" ) && shift ;; + esac + done + declare -p options + declare -p commands +} + +process_args () { + while [[ $# -gt 0 ]]; do + case "$1" in + -h|-help|--help) usage; exit 1 ;; + -v|-verbose|--verbose) sbt_verbose=1 && shift ;; + -V|-version|--version) print_version=1 && shift ;; + --numeric-version) print_sbt_version=1 && shift ;; + --script-version) print_sbt_script_version=1 && shift ;; + -d|-debug|--debug) sbt_debug=1 && addSbt "-debug" && shift ;; + + -ivy|--ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; + -mem|--mem) require_arg integer "$1" "$2" && addMemory "$2" && shift 2 ;; + -jvm-debug|--jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;; + -batch|--batch) exec nul >nul + if !JVM_DEBUG_PORT! EQU 0 ( + rem next argument wasn't a port, set a default and process next arg + set /A JVM_DEBUG_PORT=5005 + goto args_loop + ) else ( + shift + goto args_loop + ) + ) +) + +if "%~0" == "-java-home" set _java_home_arg=true +if "%~0" == "--java-home" set _java_home_arg=true + +if defined _java_home_arg ( + set _java_home_arg= + if not "%~1" == "" ( + if exist "%~1\bin\java.exe" ( + set "_JAVACMD=%~1\bin\java.exe" + set "JAVA_HOME=%~1" + set "JDK_HOME=%~1" + shift + goto args_loop + ) else ( + echo Directory "%~1" for JAVA_HOME is not valid + goto error + ) + ) else ( + echo Second argument for --java-home missing + goto error + ) +) + +if "%~0" == "new" ( + if not defined SBT_ARGS ( + set sbt_new=true + ) +) + +if "%g:~0,2%" == "-D" ( + rem special handling for -D since '=' gets parsed away + for /F "tokens=1 delims==" %%a in ("%g%") do ( + rem make sure it doesn't have the '=' already + if "%g%" == "%%a" ( + if not "%~1" == "" ( + call :dlog [args_loop] -D argument %~0=%~1 + set "SBT_ARGS=!SBT_ARGS! %~0=%~1" + shift + goto args_loop + ) else ( + echo %g% is missing a value + goto error + ) + ) else ( + call :dlog [args_loop] -D argument %~0 + set "SBT_ARGS=!SBT_ARGS! %~0" + goto args_loop + ) + ) +) + +if not "%g:~0,5%" == "-XX:+" if not "%g:~0,5%" == "-XX:-" if "%g:~0,3%" == "-XX" ( + rem special handling for -XX since '=' gets parsed away + for /F "tokens=1 delims==" %%a in ("%g%") do ( + rem make sure it doesn't have the '=' already + if "%g%" == "%%a" ( + if not "%~1" == "" ( + call :dlog [args_loop] -XX argument %~0=%~1 + set "SBT_ARGS=!SBT_ARGS! %~0=%~1" + shift + goto args_loop + ) else ( + echo %g% is missing a value + goto error + ) + ) else ( + call :dlog [args_loop] -XX argument %~0 + set "SBT_ARGS=!SBT_ARGS! %~0" + goto args_loop + ) + ) +) + +rem the %0 (instead of %~0) preserves original argument quoting +set SBT_ARGS=!SBT_ARGS! %0 + +goto args_loop +:args_end + +rem Confirm a user's intent if the current directory does not look like an sbt +rem top-level directory and the "new" command was not given. + +if not defined sbt_args_sbt_create if not defined sbt_args_print_version if not defined sbt_args_print_sbt_version if not defined sbt_args_print_sbt_script_version if not exist build.sbt ( + if not exist project\ ( + if not defined sbt_new ( + echo [warn] Neither build.sbt nor a 'project' directory in the current directory: "%CD%" + setlocal +:confirm + echo c^) continue + echo q^) quit + + set /P reply=^? + if /I "!reply!" == "c" ( + goto confirm_end + ) else if /I "!reply!" == "q" ( + exit /B 1 + ) + + goto confirm +:confirm_end + endlocal + ) + ) +) + +call :process + +rem avoid bootstrapping/java version check for script version + +if !sbt_args_print_sbt_script_version! equ 1 ( + echo !init_sbt_version! + goto :eof +) + +call :checkjava + +call :copyrt + +if defined JVM_DEBUG_PORT ( + set _JAVA_OPTS=!_JAVA_OPTS! -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=!JVM_DEBUG_PORT! +) + +call :sync_preloaded + +call :run !SBT_ARGS! + +if ERRORLEVEL 1 goto error +goto end + +:run + +rem set arguments + +if defined sbt_args_debug_inc ( + set _SBT_OPTS=-Dxsbt.inc.debug=true !_SBT_OPTS! +) + +if defined sbt_args_no_colors ( + set _SBT_OPTS=-Dsbt.log.noformat=true !_SBT_OPTS! +) + +if defined sbt_args_no_global ( + set _SBT_OPTS=-Dsbt.global.base=project/.sbtboot !_SBT_OPTS! +) + +if defined sbt_args_no_share ( + set _SBT_OPTS=-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy !_SBT_OPTS! +) + +if defined sbt_args_supershell ( + set _SBT_OPTS=-Dsbt.supershell=!sbt_args_supershell! !_SBT_OPTS! +) + +if defined sbt_args_sbt_version ( + set _SBT_OPTS=-Dsbt.version=!sbt_args_sbt_version! !_SBT_OPTS! +) + +if defined sbt_args_sbt_dir ( + set _SBT_OPTS=-Dsbt.global.base=!sbt_args_sbt_dir! !_SBT_OPTS! +) + +if defined sbt_args_sbt_boot ( + set _SBT_OPTS=-Dsbt.boot.directory=!sbt_args_sbt_boot! !_SBT_OPTS! +) + +if defined sbt_args_ivy ( + set _SBT_OPTS=-Dsbt.ivy.home=!sbt_args_ivy! !_SBT_OPTS! +) + +if defined sbt_args_color ( + set _SBT_OPTS=-Dsbt.color=!sbt_args_color! !_SBT_OPTS! +) + +if defined sbt_args_mem ( + call :addMemory !sbt_args_mem! +) else ( + call :addDefaultMemory +) + +if defined sbt_args_timings ( + set _SBT_OPTS=-Dsbt.task.timings=true -Dsbt.task.timings.on.shutdown=true !_SBT_OPTS! +) + +if defined sbt_args_traces ( + set _SBT_OPTS=-Dsbt.traces=true !_SBT_OPTS! +) + +if defined sbt_args_sbt_jar ( + set "sbt_jar=!sbt_args_sbt_jar!" +) else ( + set "sbt_jar=!SBT_HOME!\bin\sbt-launch.jar" +) + +set sbt_jar=!sbt_jar:"=! + +rem TODO: _SBT_OPTS needs to be processed as args and diffed against SBT_ARGS + +if !sbt_args_print_sbt_version! equ 1 ( + call :set_sbt_version + echo !sbt_version! + goto :eof +) + +if !sbt_args_print_version! equ 1 ( + call :set_sbt_version + echo sbt version in this project: !sbt_version! + echo sbt script version: !init_sbt_version! + goto :eof +) + +if defined sbt_args_verbose ( + echo # Executing command line: + echo "!_JAVACMD!" + if defined _JAVA_OPTS ( call :echolist !_JAVA_OPTS! ) + if defined _SBT_OPTS ( call :echolist !_SBT_OPTS! ) + echo -cp + echo "!sbt_jar!" + echo xsbt.boot.Boot + if not "%~1" == "" ( call :echolist %* ) + echo. +) + +"!_JAVACMD!" !_JAVA_OPTS! !_SBT_OPTS! -cp "!sbt_jar!" xsbt.boot.Boot %* + +goto :eof + +rem for expression tries to interpret files, so simply loop over %* instead +rem fixes dealing with quotes after = args: -Dscala.ext.dirs="C:\Users\First Last\.sbt\0.13\java9-rt-ext-adoptopenjdk_11_0_3" +:echolist +rem call method is in first call of %0 +shift + +if "%~0" == "" goto echolist_end +set "p=%~0" + +if "%p:~0,2%" == "-D" ( + rem special handling for -D since '=' gets parsed away + for /F "tokens=1 delims==" %%a in ("%p%") do ( + rem make sure it doesn't have the '=' already + if "%p%" == "%%a" if not "%~1" == "" ( + echo %0=%1 + shift + goto echolist + ) + ) +) + +if not "%p:~0,5%" == "-XX:+" if not "%p:~0,5%" == "-XX:-" if "%p:~0,3%" == "-XX" ( + rem special handling for -XX since '=' gets parsed away + for /F "tokens=1 delims==" %%a in ("%p%") do ( + rem make sure it doesn't have the '=' already + if "%p%" == "%%a" if not "%~1" == "" ( + echo %0=%1 + shift + goto echolist + ) + ) +) + +if "%p:~0,14%" == "-agentlib:jdwp" ( + rem special handling for --jvm-debug since '=' and ',' gets parsed away + for /F "tokens=1 delims==" %%a in ("%p%") do ( + rem make sure it doesn't have the '=' already + if "%p%" == "%%a" if not "%~1" == "" if not "%~2" == "" if not "%~3" == "" if not "%~4" == "" if not "%~5" == "" if not "%~6" == "" if not "%~7" == "" if not "%~8" == "" ( + echo %0=%1=%2,%3=%4,%5=%6,%7=%8 + shift & shift & shift & shift & shift & shift & shift & shift + goto echolist + ) + ) +) + +echo %0 +goto echolist + +:echolist_end + +exit /B 0 + +:addJava + call :dlog [addJava] arg = '%*' + set "_JAVA_OPTS=!_JAVA_OPTS! %*" +exit /B 0 + +:addMemory + call :dlog [addMemory] arg = '%*' + + rem evict memory related options + set _new_java_opts= + set _old_java_opts=!_JAVA_OPTS! +:next_java_opt + if "!_old_java_opts!" == "" goto :done_java_opt + for /F "tokens=1,*" %%g in ("!_old_java_opts!") do ( + set "p=%%g" + if not "!p:~0,4!" == "-Xmx" if not "!p:~0,4!" == "-Xms" if not "!p:~0,15!" == "-XX:MaxPermSize" if not "!p:~0,20!" == "-XX:MaxMetaspaceSize" if not "!p:~0,25!" == "-XX:ReservedCodeCacheSize" ( + set _new_java_opts=!_new_java_opts! %%g + ) + set "_old_java_opts=%%h" + ) + goto :next_java_opt +:done_java_opt + set _JAVA_OPTS=!_new_java_opts! + + set _new_sbt_opts= + set _old_sbt_opts=!_SBT_OPTS! +:next_sbt_opt + if "!_old_sbt_opts!" == "" goto :done_sbt_opt + for /F "tokens=1,*" %%g in ("!_old_sbt_opts!") do ( + set "p=%%g" + if not "!p:~0,4!" == "-Xmx" if not "!p:~0,4!" == "-Xms" if not "!p:~0,15!" == "-XX:MaxPermSize" if not "!p:~0,20!" == "-XX:MaxMetaspaceSize" if not "!p:~0,25!" == "-XX:ReservedCodeCacheSize" ( + set _new_sbt_opts=!_new_sbt_opts! %%g + ) + set "_old_sbt_opts=%%h" + ) + goto :next_sbt_opt +:done_sbt_opt + set _SBT_OPTS=!_new_sbt_opts! + + rem a ham-fisted attempt to move some memory settings in concert + set mem=%1 + set /a codecache=!mem! / 8 + if !codecache! GEQ 512 set /a codecache=512 + if !codecache! LEQ 128 set /a codecache=128 + + set /a class_metadata_size=!codecache! * 2 + + call :addJava -Xms!mem!m + call :addJava -Xmx!mem!m + call :addJava -Xss4M + call :addJava -XX:ReservedCodeCacheSize=!codecache!m + + if /I !JAVA_VERSION! LSS 8 ( + call :addJava -XX:MaxPermSize=!class_metadata_size!m + ) + +exit /B 0 + +:addDefaultMemory + rem if we detect any of these settings in ${JAVA_OPTS} or ${JAVA_TOOL_OPTIONS} we need to NOT output our settings. + rem The reason is the Xms/Xmx, if they don't line up, cause errors. + + set _has_memory_args= + + if defined _JAVA_OPTS for /F %%g in ("!_JAVA_OPTS!") do ( + set "p=%%g" + if "!p:~0,4!" == "-Xmx" set _has_memory_args=1 + if "!p:~0,4!" == "-Xms" set _has_memory_args=1 + ) + + if defined JAVA_TOOL_OPTIONS for /F %%g in ("%JAVA_TOOL_OPTIONS%") do ( + set "p=%%g" + if "!p:~0,4!" == "-Xmx" set _has_memory_args=1 + if "!p:~0,4!" == "-Xms" set _has_memory_args=1 + ) + + if defined _SBT_OPTS for /F %%g in ("!_SBT_OPTS!") do ( + set "p=%%g" + if "!p:~0,4!" == "-Xmx" set _has_memory_args=1 + if "!p:~0,4!" == "-Xms" set _has_memory_args=1 + ) + + if not defined _has_memory_args ( + call :addMemory !sbt_default_mem! + ) +exit /B 0 + +:dlog + if defined sbt_args_debug ( + echo %* 1>&2 + ) +exit /B 0 + +:process +rem Parses x out of 1.x; for example 8 out of java version 1.8.0_xx +rem Otherwise, parses the major version; 9 out of java version 9-ea +set JAVA_VERSION=0 + +for /f "tokens=3 usebackq" %%g in (`CALL "!_JAVACMD!" -Xms32M -Xmx32M -version 2^>^&1 ^| findstr /i version`) do ( + set JAVA_VERSION=%%g +) + +rem removes all quotes from JAVA_VERSION +set JAVA_VERSION=!JAVA_VERSION:"=! + +for /f "delims=.-_ tokens=1-2" %%v in ("!JAVA_VERSION!") do ( + if /I "%%v" EQU "1" ( + set JAVA_VERSION=%%w + ) else ( + set JAVA_VERSION=%%v + ) +) + +exit /B 0 + +:checkjava +set /a required_version=6 +if /I !JAVA_VERSION! GEQ !required_version! ( + exit /B 0 +) +echo. +echo The Java Development Kit ^(JDK^) installation you have is not up to date. +echo sbt requires at least version !required_version!+, you have +echo version "!JAVA_VERSION!" +echo. +echo Please go to http://www.oracle.com/technetwork/java/javase/downloads/ and download +echo a valid JDK and install before running sbt. +echo. +exit /B 1 + +:copyrt +if /I !JAVA_VERSION! GEQ 9 ( + set "rtexport=!SBT_BIN_DIR!java9-rt-export.jar" + + "!_JAVACMD!" !_JAVA_OPTS! !_SBT_OPTS! -jar "!rtexport!" --rt-ext-dir > "%TEMP%.\rtext.txt" + set /p java9_ext= < "%TEMP%.\rtext.txt" + set "java9_rt=!java9_ext!\rt.jar" + + if not exist "!java9_rt!" ( + mkdir "!java9_ext!" + "!_JAVACMD!" !_JAVA_OPTS! !_SBT_OPTS! -jar "!rtexport!" "!java9_rt!" + ) + set _JAVA_OPTS=!_JAVA_OPTS! -Dscala.ext.dirs="!java9_ext!" +) +exit /B 0 + +:sync_preloaded +if not defined init_sbt_version ( + rem FIXME: better !init_sbt_version! detection + FOR /F "tokens=* usebackq" %%F IN (`dir /b "!SBT_HOME!\lib\local-preloaded\org\scala-sbt\sbt" /B`) DO ( + SET init_sbt_version=%%F + ) +) + +set PRELOAD_SBT_JAR="%UserProfile%\.sbt\preloaded\org\scala-sbt\sbt\!init_sbt_version!\" +if /I !JAVA_VERSION! GEQ 8 ( + where robocopy >nul 2>nul + if %ERRORLEVEL% EQU 0 ( + if not exist !PRELOAD_SBT_JAR! ( + if exist "!SBT_HOME!\lib\local-preloaded\" ( + robocopy "!SBT_HOME!\lib\local-preloaded" "%UserProfile%\.sbt\preloaded" /E >nul 2>nul + ) + ) + ) +) +exit /B 0 + +:usage + +for /f "tokens=3 usebackq" %%g in (`CALL "!_JAVACMD!" -Xms32M -Xmx32M -version 2^>^&1 ^| findstr /i version`) do ( + set FULL_JAVA_VERSION=%%g +) + +echo. +echo Usage: %~n0 [options] +echo. +echo -h ^| --help print this message +echo -v ^| --verbose this runner is chattier +echo -V ^| --version print sbt version information +echo --numeric-version print the numeric sbt version (sbt sbtVersion) +echo --script-version print the version of sbt script +echo -d ^| --debug set sbt log level to debug +echo -debug-inc ^| --debug-inc +echo enable extra debugging for the incremental debugger +echo --no-colors disable ANSI color codes +echo --color=auto^|always^|true^|false^|never +echo enable or disable ANSI color codes ^(sbt 1.3 and above^) +echo --supershell=auto^|always^|true^|false^|never +echo enable or disable supershell ^(sbt 1.3 and above^) +echo --traces generate Trace Event report on shutdown ^(sbt 1.3 and above^) +echo --timings display task timings report on shutdown +echo --sbt-create start sbt even if current directory contains no sbt project +echo --sbt-dir ^ path to global settings/plugins directory ^(default: ~/.sbt^) +echo --sbt-boot ^ path to shared boot directory ^(default: ~/.sbt/boot in 0.11 series^) +echo --ivy ^ path to local Ivy repository ^(default: ~/.ivy2^) +echo --mem ^ set memory options ^(default: %sbt_default_mem%^) +echo --no-share use all local caches; no sharing +echo --no-global uses global caches, but does not use global ~/.sbt directory. +echo --jvm-debug ^ enable on JVM debugging, open at the given port. +rem echo --batch disable interactive mode +echo. +echo # sbt version ^(default: from project/build.properties if present, else latest release^) +echo --sbt-version ^ use the specified version of sbt +echo --sbt-jar ^ use the specified jar as the sbt launcher +echo. +echo # java version ^(default: java from PATH, currently !FULL_JAVA_VERSION!^) +echo --java-home ^ alternate JAVA_HOME +echo. +echo # jvm options and output control +echo JAVA_OPTS environment variable, if unset uses "!default_java_opts!" +echo .jvmopts if this file exists in the current directory, its contents +echo are appended to JAVA_OPTS +echo SBT_OPTS environment variable, if unset uses "!default_sbt_opts!" +echo .sbtopts if this file exists in the current directory, its contents +echo are prepended to the runner args +echo !SBT_CONFIG! +echo if this file exists, it is prepended to the runner args +echo -Dkey=val pass -Dkey=val directly to the java runtime +rem echo -J-X pass option -X directly to the java runtime +rem echo ^(-J is stripped^) +rem echo -S-X add -X to sbt's scalacOptions ^(-S is stripped^) +echo. +echo In the case of duplicated or conflicting options, the order above +echo shows precedence: JAVA_OPTS lowest, command line options highest. +echo. + +@endlocal +exit /B 1 + +:set_sbt_version +rem set project sbtVersion +for /F "usebackq tokens=2" %%G in (`CALL "!_JAVACMD!" -jar "!sbt_jar!" "sbtVersion" 2^>^&1`) do set "sbt_version=%%G" +exit /B 0 + +:error +@endlocal +exit /B 1 + +:end +@endlocal +exit /B 0 diff --git a/sbt-dist/conf/sbtconfig.txt b/sbt-dist/conf/sbtconfig.txt new file mode 100644 index 0000000..a4da43e --- /dev/null +++ b/sbt-dist/conf/sbtconfig.txt @@ -0,0 +1,14 @@ +# Set the java args to high + +-Xmx512M + +-XX:MaxPermSize=256m + +-XX:ReservedCodeCacheSize=128m + + + +# Set the extra SBT options + +-Dsbt.log.format=true + diff --git a/sbt-dist/conf/sbtopts b/sbt-dist/conf/sbtopts new file mode 100644 index 0000000..f018465 --- /dev/null +++ b/sbt-dist/conf/sbtopts @@ -0,0 +1,49 @@ +# ------------------------------------------------ # +# The SBT Configuration file. # +# ------------------------------------------------ # + + +# Disable ANSI color codes +# +#-no-colors + +# Starts sbt even if the current directory contains no sbt project. +# +-sbt-create + +# Path to global settings/plugins directory (default: ~/.sbt) +# +#-sbt-dir /etc/sbt + +# Path to shared boot directory (default: ~/.sbt/boot in 0.11 series) +# +#-sbt-boot ~/.sbt/boot + +# Path to local Ivy repository (default: ~/.ivy2) +# +#-ivy ~/.ivy2 + +# set memory options +# +#-mem + +# Use local caches for projects, no sharing. +# +#-no-share + +# Put SBT in offline mode. +# +#-offline + +# Sets the SBT version to use. +#-sbt-version 0.11.3 + +# Scala version (default: latest release) +# +#-scala-home +#-scala-version + +# java version (default: java from PATH, currently $(java -version |& grep version)) +# +#-java-home + diff --git a/sbt.bat b/sbt.bat new file mode 100755 index 0000000..436eee2 --- /dev/null +++ b/sbt.bat @@ -0,0 +1,3 @@ +@REM SBT launcher script + +.\sbt-dist\bin\sbt.bat %* diff --git a/src/main/java/com/example/AkkaQuickstart.java b/src/main/java/com/example/AkkaQuickstart.java new file mode 100644 index 0000000..89db60a --- /dev/null +++ b/src/main/java/com/example/AkkaQuickstart.java @@ -0,0 +1,25 @@ +package com.example; + +import akka.actor.typed.ActorSystem; + +import java.io.IOException; +public class AkkaQuickstart { + public static void main(String[] args) { + //#actor-system + final ActorSystem greeterMain = ActorSystem.create(GreeterMain.create(), "helloakka"); + //#actor-system + + //#main-send-messages + greeterMain.tell(new GreeterMain.SayHello("Charles")); + greeterMain.tell(new GreeterMain.SayHello("Alice")); + //#main-send-messages + + try { + System.out.println(">>> Press ENTER to exit <<<"); + System.in.read(); + } catch (IOException ignored) { + } finally { + greeterMain.terminate(); + } + } +} diff --git a/src/main/java/com/example/Greeter.java b/src/main/java/com/example/Greeter.java new file mode 100644 index 0000000..850e279 --- /dev/null +++ b/src/main/java/com/example/Greeter.java @@ -0,0 +1,46 @@ +package com.example; + +import akka.actor.typed.ActorRef; +import akka.actor.typed.Behavior; +import akka.actor.typed.javadsl.*; + + +// #greeter +public class Greeter extends AbstractBehavior { + + public interface Message {} + public record Response(boolean are_messages_left, Greet msg) implements Message {} + public record Greet(String whom, ActorRef replyTo) implements Message {} + public record Greeted(String whom, ActorRef replyTo) {} + + public static Behavior create(ActorRef overseer) { + return Behaviors.setup(context -> new Greeter(context, overseer)); + } + + private final ActorRef overseer; + private Greeter(ActorContext context, ActorRef overseer) { + super(context); + this.overseer = overseer; + } + + @Override + public Receive createReceive() { + return newReceiveBuilder().onMessage(Greet.class, this::onGreet).onMessage(Response.class, this::onResponse).build(); + } + private Behavior onResponse(Response command) { + if (command.are_messages_left()) { + getContext().getLog().info("Hello {}!", command.msg().whom()); + //#greeter-send-message + command.msg().replyTo().tell(new Greeter.Greeted(command.msg().whom(), getContext().getSelf())); + //#greeter-send-message + } + return this; + } + + private Behavior onGreet(Greet command) { + overseer.tell(new Overseer.Request(command, getContext().getSelf())); + return this; + } +} +// #greeter + diff --git a/src/main/java/com/example/GreeterBot.java b/src/main/java/com/example/GreeterBot.java new file mode 100644 index 0000000..a431d1a --- /dev/null +++ b/src/main/java/com/example/GreeterBot.java @@ -0,0 +1,30 @@ +package com.example; + +import akka.actor.typed.Behavior; +import akka.actor.typed.javadsl.*; + +public class GreeterBot extends AbstractBehavior { + + + public static Behavior create() { + return Behaviors.setup(GreeterBot::new); + } + + public int greetingCounter; + + private GreeterBot(ActorContext context) { + super(context); + } + + @Override + public Receive createReceive() { + return newReceiveBuilder().onMessage(Greeter.Greeted.class, this::onGreeted).build(); + } + + private Behavior onGreeted(Greeter.Greeted message) { + greetingCounter++; + getContext().getLog().info("Greeting {} for {}", greetingCounter, message.whom()); + message.replyTo().tell(new Greeter.Greet(message.whom(), getContext().getSelf())); + return this; + } +} diff --git a/src/main/java/com/example/GreeterMain.java b/src/main/java/com/example/GreeterMain.java new file mode 100644 index 0000000..4201395 --- /dev/null +++ b/src/main/java/com/example/GreeterMain.java @@ -0,0 +1,45 @@ +package com.example; + +import akka.actor.typed.ActorRef; +import akka.actor.typed.Behavior; +import akka.actor.typed.javadsl.*; + +public class GreeterMain extends AbstractBehavior { + + public static class SayHello { + public final String name; + + public SayHello(String name) { + this.name = name; + } + } + + private final ActorRef greeter; + + public static Behavior create() { + return Behaviors.setup(GreeterMain::new); + } + + private GreeterMain(ActorContext context) { + super(context); + //#create-actors + ActorRef overseer = context.spawn(Overseer.create(200), "overseer"); + greeter = context.spawn(Greeter.create(overseer), "greeter"); + //#create-actors + } + + @Override + public Receive createReceive() { + return newReceiveBuilder().onMessage(SayHello.class, this::onSayHello).build(); + } + + private Behavior onSayHello(SayHello command) { + //#create-actors + + ActorRef replyTo = + getContext().spawn(GreeterBot.create(), command.name); + greeter.tell(new Greeter.Greet(command.name, replyTo)); + //#create-actors + return this; + } +} diff --git a/src/main/java/com/example/Overseer.java b/src/main/java/com/example/Overseer.java new file mode 100644 index 0000000..356b22d --- /dev/null +++ b/src/main/java/com/example/Overseer.java @@ -0,0 +1,41 @@ +package com.example; + +import akka.actor.typed.ActorRef; +import akka.actor.typed.Behavior; +import akka.actor.typed.javadsl.AbstractBehavior; +import akka.actor.typed.javadsl.ActorContext; +import akka.actor.typed.javadsl.Behaviors; +import akka.actor.typed.javadsl.Receive; + +// #greeter +public class Overseer extends AbstractBehavior { + + public record Request(Greeter.Greet msg, ActorRef replyTo) {} + + public static Behavior create(int max) { + return Behaviors.setup(context -> new Overseer(context, max)); + } + + private final int max; + private int current; + + private Overseer(ActorContext context, int max) { + super(context); + this.max = max; + } + + @Override + public Receive createReceive() { + return newReceiveBuilder().onMessage(Request.class, this::onRequest).build(); + } + + private Behavior onRequest(Request command) { + this.current++; + //#greeter-send-message + command.replyTo().tell(new Greeter.Response(this.current <= this.max, command.msg())); + //#greeter-send-message + return this; + } +} +// #greeter + diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..203596d --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,21 @@ + + + + + + [%date{ISO8601}] [%level] [%logger] [%thread] [%X{akkaSource}] - %msg%n + + + + + 1024 + true + + + + + + + +