summarylogtreecommitdiffstats
path: root/metals-client.sh
blob: 956f30c373f79b926d3205513578fba6e0d7cbd6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/bin/bash

set -e

declare -r _INSTALL_DIR='/usr/share/java/metals'
declare -r _UTIL_DIR="${_INSTALL_DIR}/util"
declare _CP="$_INSTALL_DIR/lib:$_INSTALL_DIR/metals"

# This is an ordered array of JDK paths to attempt to use if
# METALS_JDK_PATH is unset. They are based off of the default
# installation locations of the various JDKs in Arch Linux.
#
# We only explicitly try known working versions, at the time of
# writing that is >= 8 and <= 17. We prefer newer versions to older
# ones.
declare -r -a _JAVA_ARCH_PACKAGE_PATHS=('/usr/lib/jvm/java-17-openjdk/bin'
                                        '/usr/lib/jvm/java-16-openjdk/bin'
                                        '/usr/lib/jvm/java-15-openjdk/bin'
                                        '/usr/lib/jvm/java-14-openjdk/bin'
                                        '/usr/lib/jvm/java-13-openjdk/bin'
                                        '/usr/lib/jvm/java-12-openjdk/bin'
                                        '/usr/lib/jvm/java-11-openjdk/bin'
                                        '/usr/lib/jvm/java-10-openjdk/bin'
                                        '/usr/lib/jvm/java-8-openjdk/jre/bin'
                                       )
declare -r -a _DEFAULT_METALS_JAVA_OPTS=('-XX:MaxHeapFreeRatio=20' '-XX:MinHeapFreeRatio=5' '-XX:MaxRAMPercentage=25.0')

# The _actual_ metals options will be put here after
# setup_metals_java_opts is run.
declare -a _METALS_JAVA_OPTS

# Used in conjunction with _DEFAULT_METALS_JAVA_OPTS to determine
# which java options to are supported. Not used or set if
# METALS_JAVA_OPTS is explicitly set.
declare _JRE_VERSION

function ensure_comaptible_jdk {
    local -r _LEN="${#_JAVA_ARCH_PACKAGE_PATHS[@]}"
    local _INDEX=0
    local _PACKAGE_PATH

    if [ -n "$METALS_JDK_PATH" ]
    then
        if [ -d "$METALS_JDK_PATH" ]
        then
            if [ -x "${METALS_JDK_PATH}/java" ]
            then
                export PATH="$METALS_JDK_PATH:$PATH"
                return 0
            else
                echo "Directory specified at METALS_JDK_PATH=${METALS_JDK_PATH} does not contain an executable file named \"java\"." 1>&2
                exit 1
            fi
        else
            echo "METALS_JDK_PATH value set in environment, but $METALS_JDK_PATH is not a directory." 1>&2
            exit 2
        fi
    else
        while [ $_INDEX -lt "$_LEN" ]
        do
            _PACKAGE_PATH="${_JAVA_ARCH_PACKAGE_PATHS[$_INDEX]}"
            if [ -d "$_PACKAGE_PATH" ]
            then
                export PATH="$_PACKAGE_PATH:$PATH"
                return 0
            else
                _INDEX=$((_INDEX + 1))
                continue
            fi
        done
        echo 'Unable to find a Java >=8 and <=11 environment to use with certainty. To use Metals you should have a JDK >=8 and <=11 installed. Attempting to use the current environment.' 1>&2
    fi
}

function build_cp {
    while read -r name
    do
        _CP="$name:$_CP"
    done <<< "$(find "$_INSTALL_DIR"/jars -regex '.*\.jar')"
}

function determine_jre_version {
    pushd "$_UTIL_DIR" &>/dev/null
    _JRE_VERSION="$(java JREMajorVersion)"
    popd &>/dev/null
    readonly _JRE_VERSION
    echo "JRE version determined to be ${_JRE_VERSION}" 1>&2
}

function setup_metals_java_opts {
    if [ -n "$METALS_JAVA_OPTS" ]
    then
        read -r -a _METALS_JAVA_OPTS <<< "$METALS_JAVA_OPTS"
        echo "Found METALS_JAVA_OPTS: ${_METALS_JAVA_OPTS[*]}" 1>&2
    else
        _METALS_JAVA_OPTS+=("${_DEFAULT_METALS_JAVA_OPTS[@]}")

        determine_jre_version

        if [ "$_JRE_VERSION" -gt 9 ]
        then
            _METALS_JAVA_OPTS+=("${_DEFAULT_JDK_10_PLUS_OPTS[@]}")
        fi

        echo "Using default METALS_JAVA_OPTS: ${_METALS_JAVA_OPTS[*]}" 1>&2
    fi

    readonly -a _METALS_JAVA_OPTS
}

function main {
    ensure_comaptible_jdk

    build_cp

    # Echo out the full path to the Java binary we will use.
    echo "Java binary selected: $(command -v java)" 1>&2

    setup_metals_java_opts

    if [ -z "$_METALS_CLIENT" ]
    then
        exec java "${_METALS_JAVA_OPTS[@]}" -cp "$_CP" scala.meta.metals.Main "$@"
    else
        exec java "${_METALS_JAVA_OPTS[@]}" -Dmetals.client="$_METALS_CLIENT" -cp "$_CP" scala.meta.metals.Main "$@"
    fi
}

main "$@"