|
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."
|