Project

General

Profile

deploy_appcds.sh

Roger Borrello, 06/16/2026 07:20 PM

Download (7.2 KB)

 
1
#!/bin/bash
2

    
3
#set -x
4

    
5
# Default values
6
P2J_JAR="../lib/p2j.jar"
7
DIR_XML=""
8
APPCDS_DIR=""
9

    
10
show_usage()
11
{
12
   i=0;        usage[$i]="Usage: $(basename $0) [-f <directory.xml>] [-d <appcds_dir>] [path_to_p2j.jar]"
13
   i=$((i+1)); usage[$i]="Where:"
14
   i=$((i+1)); usage[$i]="path_to_p2j.jar \t= Path to p2j.jar (default=\"../lib/p2j.jar\")"
15
   i=$((i+1)); usage[$i]="-f | --file \t= Path to directory.xml (default=\"../server/directory.xml\")"
16
   i=$((i+1)); usage[$i]="-d | --dir \t= Path to output appcds folder (default=\"../appcds/client\")"
17
   i=$((i+1)); usage[$i]="-h | --help \t= Usage information"
18

    
19
   for i in "${usage[@]}"; do
20
      echo -e "$i"
21
   done
22
}
23

    
24
while [[ $# -gt 0 ]]; do
25
    case "$1" in
26
        -h|--help|-\?)
27
            show_usage
28
            exit 1
29
            ;;
30
        -f|--file)
31
            DIR_XML="$2"
32
            shift 2
33
            ;;
34
        -d|--dir)
35
            APPCDS_DIR="$2"
36
            shift 2
37
            ;;
38
        *)
39
            if [[ "$1" == -* ]]; then
40
                echo "Unknown option: $1"
41
                show_usage
42
                exit 1
43
            fi
44
            # Positional argument
45
            P2J_JAR="$1"
46
            shift
47
            ;;
48
    esac
49
done
50

    
51
# Resolve DEPLOY_HOME relative to this script
52
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
53
DEPLOY_HOME="$(cd "$SCRIPT_DIR/.." && pwd)"
54

    
55
# Ensure P2J_JAR is an absolute path if it exists
56
if [[ "$P2J_JAR" != /* ]]; then
57
    P2J_JAR="$PWD/$P2J_JAR"
58
fi
59

    
60
DIR_XML="${DIR_XML:-$DEPLOY_HOME/server/directory.xml}"
61
if [[ "$DIR_XML" != /* ]]; then
62
    DIR_XML="$PWD/$DIR_XML"
63
fi
64

    
65
APPCDS_DIR="${APPCDS_DIR:-$DEPLOY_HOME/appcds/client}"
66
if [[ "$APPCDS_DIR" != /* ]]; then
67
    APPCDS_DIR="$PWD/$APPCDS_DIR"
68
fi
69

    
70
if [ ! -f "$DIR_XML" ]; then
71
    echo "Error: $DIR_XML not found."
72
    exit 1
73
fi
74

    
75
TMP_PROPS=$(mktemp)
76
java -cp "$P2J_JAR" com.goldencode.util.JvmArgsExtractor -f "$DIR_XML" -o "$TMP_PROPS"
77

    
78
if [ $? -ne 0 ]; then
79
    echo "Error: Failed to extract JVM args."
80
    rm -f "$TMP_PROPS"
81
    exit 1
82
fi
83

    
84
# Read properties into dynamically named variables
85
while IFS='=' read -r key value; do
86
    if [[ $key == \#* ]] || [ -z "$key" ]; then
87
        continue
88
    fi
89
    key=$(echo "$key" | xargs)
90
    value="${value//\\:/:}"
91
    value="${value//\\=/=}"
92
    
93
    var_name="${key//./_}"
94
    var_name="${var_name//-/_}"
95
    declare "$var_name=$value"
96
done < "$TMP_PROPS"
97

    
98
rm -f "$TMP_PROPS"
99

    
100
# Remove existing appcds directory to prevent Java from reusing a stale .jsa archive.
101
# The JVM does not overwrite an existing SharedArchiveFile in-place; removing the
102
# directory guarantees a clean dump on every run.
103
if [ -d "$APPCDS_DIR" ]; then
104
    rm -rf "$APPCDS_DIR"
105
fi
106
mkdir -p "$APPCDS_DIR"
107

    
108
if [ -z "$appcds_clients" ]; then
109
    echo "No clients found for AppCDS."
110
    exit 0
111
fi
112

    
113
# Source the application name so getcp.sh can locate the application jar.
114
appname=""
115
[ -f "$DEPLOY_HOME/client/appname" ] && . "$DEPLOY_HOME/client/appname"
116

    
117
IFS=',' read -ra clients <<< "$appcds_clients"
118
for client_type in "${clients[@]}"; do
119
    client_type=$(echo "$client_type" | xargs)
120
    if [ -z "$client_type" ]; then
121
        continue
122
    fi
123
    
124
    echo "Processing client: $client_type"
125
    
126
    cp_var="appcds_classpath_$client_type"
127
    args_var="appcds_jvmargs_$client_type"
128
    
129
    client_args="${!args_var}"
130

    
131
    # JvmArgsExtractor only reports <libPath>/p2j.jar for the classpath. Build the
132
    # COMPLETE client runtime classpath the same way client.sh does -- via getcp.sh
133
    # run from the client dir -- and freeze it (below) to <type>.cpath. This makes
134
    # the classpath the archive is dumped against byte-for-byte identical to the one
135
    # the client replays (getcp.sh --appcds), so AppCDS's classpath check passes.
136
    # FWD_LIB points at the curated client deploy root (the parent of the lib dir
137
    # holding p2j.jar) so getcp.sh resolves the curated client library set.
138
    appcds_p2j="${!cp_var}"
139
    appcds_p2j="${appcds_p2j%%:*}"
140
    appcds_lib_dir="$(cd "$(dirname "$appcds_p2j")" 2>/dev/null && pwd)"
141
    appcds_fwd_root="$(dirname "$appcds_lib_dir")"
142
    client_cp="$(cd "$DEPLOY_HOME/client" && FWD_LIB="$appcds_fwd_root" "$DEPLOY_HOME/getcp.sh" "$appname" "$DEPLOY_HOME/client")"
143
    client_cp="${client_cp%:}"
144
    
145
    echo "JVM classpath for $client_type: $client_cp"
146
    echo "JVM args for $client_type: $client_args"
147
    
148
    base_lst=$(mktemp)
149
    runtime_lst=$(mktemp)
150
    
151
    # 1. LstExporter (run from the client dir so relative classpath entries resolve
152
    #    the same way they will at runtime)
153
    cd "$DEPLOY_HOME/client" || exit 1
154
    java -cp "$client_cp" com.goldencode.util.LstExporter \
155
        "com.goldencode.p2j.main.ClientDriver" \
156
        "com.goldencode.p2j.ui.client" \
157
        "-com.goldencode.p2j.persist" \
158
        "-com.goldencode.p2j.main.StandardServer" \
159
        "!com.goldencode.p2j.util" \
160
        "-o" "$base_lst"
161
        
162
    if [ $? -ne 0 ]; then
163
        echo "Error: LstExporter failed for $client_type"
164
        rm -f "$base_lst" "$runtime_lst"
165
        exit 1
166
    fi
167
    
168
    # 2. ClientDriver to dump runtime class list (also from the client dir)
169
    cd "$DEPLOY_HOME/client" || exit 1
170
    java -cp "$client_cp" \
171
        -Djava.library.path="$DEPLOY_HOME/lib" \
172
        -XX:DumpLoadedClassList="$runtime_lst" \
173
        com.goldencode.p2j.main.ClientDriver
174
        
175
    # 3. Concatenate. Add markers
176
    final_lst="$APPCDS_DIR/${client_type}.lst"
177
    sed -i '1i# This is base_lst' $base_lst
178
    sed -i '1i# This is runtime_lst' $runtime_lst
179
    cat "$base_lst" "$runtime_lst" > "$final_lst"
180

    
181
    # LstExporter copies SPI provider entries from META-INF/services/* verbatim, and
182
    # those files may carry inline comments that are legal per the ServiceLoader spec
183
    # (e.g. ecj's javax.tools.JavaCompiler lists
184
    #   org.eclipse.jdt...EclipseCompiler #Eclipse compiler).
185
    # The -Xshare:dump class-list parser rejects a class name followed by such a
186
    # trailing comment, so strip any inline "#..." while leaving full-line comments
187
    # (lines that begin with #) intact.
188
    sed -i 's/\([^[:space:]]\)[[:space:]]*#.*$/\1/' "$final_lst"
189
    
190
    # 4. Build JSA archive
191
    cd "$DEPLOY_HOME/client" || exit 1
192
    
193
    # We must split client_args on spaces properly without quotes
194
    # so that -Xmx512m -Dfoo=bar are treated as separate args
195
    java -cp "$client_cp" \
196
        -Djava.library.path="$DEPLOY_HOME/lib" \
197
        -Xshare:dump \
198
        -XX:SharedClassListFile="$APPCDS_DIR/${client_type}.lst" \
199
        -XX:SharedArchiveFile="$APPCDS_DIR/${client_type}.jsa" \
200
        $client_args \
201
        com.goldencode.p2j.main.ClientDriver
202
        
203
    if [ $? -ne 0 ]; then
204
        echo "Error: JSA archive generation failed for $client_type"
205
        rm -f "$base_lst" "$runtime_lst"
206
        exit 1
207
    fi
208

    
209
    # Record the exact classpath the archive was dumped against, alongside the
210
    # .jsa/.lst. The client runtime (getcp.sh --appcds) reads this file so its
211
    # classpath matches the archive. AppCDS requires the dumped classpath to be
212
    # a prefix of the runtime classpath, so these must stay in lock-step. The
213
    # client never has access to directory.xml, which is why this is published
214
    # here at prepare time instead.
215
    echo "$client_cp" > "$APPCDS_DIR/${client_type}.cpath"
216

    
217
    #rm -f "$base_lst" "$runtime_lst"
218
done
219

    
220
echo "AppCDS deployment completed successfully."