-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathbuild.xml
More file actions
457 lines (423 loc) · 19.3 KB
/
build.xml
File metadata and controls
457 lines (423 loc) · 19.3 KB
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
<?xml version="1.0" encoding="UTF-8"?>
<project default="phony" basedir="." name="Lucee-Script-runner" xmlns:if="ant:if" xmlns:unless="ant:unless" xmlns:artifact="antlib:org.apache.maven.artifact.ant">
<!-- Default target for property-only invocation -->
<target name="phony">
<antcall target="core"/>
</target>
<!-- Main entry point: orchestrates the build sequence -->
<!-- Resolve version first, then detect type to pick the right pom (javax vs jakarta) -->
<target name="core" depends="normalize-webroot,resolve-version-input,use-local-jar,use-version,query-version,detect-version-type,setEnv,set-unique-working-dir,check-lucee-jar,download-lucee-jar,run-cfml"/>
<path id="maven-ant-tasks.classpath" path="ant/lib/maven-ant-tasks-2.1.3.jar" />
<typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="antlib:org.apache.maven.artifact.ant" classpathref="maven-ant-tasks.classpath" />
<property name="cache" location="lucee-download-cache"/>
<property name="temp" location="temp"/>
<property name="uniqueWorkingDir" value="false"/>
<property name="ant" location="${rootDir}/ant"/>
<property name="webroot" location="sample"/>
<property name="execute" value="/index.cfm"/>
<property name="extensions" value=""/>
<!-- allow installing extensions from a directory, i.e. extension dist dir -->
<property name="extensionDir" value=""/>
<property name="compile" value=""/>
<!-- use .CFConfig.json file -->
<property name="luceeCFConfig" value=""/>
<!-- enable java debugging -->
<property name="debugger" value=""/>
<!-- add JFR module exports/opens for JFR API access -->
<property name="jfrExports" value=""/>
<!-- enable FlightRecording -->
<property name="FlightRecording" value=""/>
<!-- custom FlightRecording filename -->
<property name="FlightRecordingFilename" value=""/>
<!-- Java agent JAR path (e.g., for profiling agents, debuggers) -->
<property name="javaAgent" value=""/>
<!-- Java agent arguments (passed after = in -javaagent:path=args) -->
<property name="javaAgentArgs" value=""/>
<!-- Enable JDWP debugging agent (required for some agents like luceedebug) -->
<property name="jdwp" value=""/>
<!-- JDWP port (default 9999) -->
<property name="jdwpPort" value="9999"/>
<!-- custom FlightRecording settings file (default: profile) -->
<property name="FlightRecordingSettings" value="profile"/>
<!-- delete the Lucee working dir before -->
<property name="preCleanup" value="true"/>
<!-- delete the Lucee working dir afterwards -->
<!-- Show the value passed for webroot before normalization -->
<!-- Normalize webroot to absolute path early -->
<target name="normalize-webroot">
<!-- Normalize to absolute path, store in webroot.abs, relative to current working directory -->
<property environment="env"/>
<condition property="webroot.abs" value="${user.dir}">
<equals arg1="${webroot}" arg2="."/>
</condition>
<property name="webroot.abs" location="${webroot}"/>
<echo message="Webroot (used by Java): ${webroot.abs}"/>
<echo message="webroot.abs = ${webroot.abs}"/>
</target>
<property name="postCleanup" value="true"/>
<!-- additional jvm properties file -->
<property name="jvmProperties" value=""/>
<!-- additional raw jvm args (e.g. "-Xmx64m -Xms32m") -->
<property name="jvmArgs" value=""/>
<!-- scripts can be run as an include, or via internalRequest (default) which picks up any Application.cfc -->
<property name="executeScriptByInclude" value=""/>
<property name="luceeCdnUrl" value="https://cdn.lucee.org"/>
<property name="luceeUpdateProvider" value="https://update.lucee.org/rest/update/provider/latest/"/>
<property name="luceeVersion" value="7.0.1.100"/>
<property name="luceeVersionQuery" value=""/> <!-- i.e. 5.4/stable/jar -->
<property name="luceeJar" value=""/> <!-- full path to a local Lucee JAR file -->
<!-- Resolve which version input to use (luceeVersionQuery takes precedence over luceeVersion) -->
<target name="resolve-version-input">
<!-- Check if luceeVersionQuery is set (not empty) -->
<condition property="luceeVersionQuery.isset">
<and>
<isset property="luceeVersionQuery"/>
<not>
<equals arg1="${luceeVersionQuery}" arg2=""/>
</not>
</and>
</condition>
<!-- Set luceeVersionResolved from luceeVersionQuery if it's set, otherwise from luceeVersion -->
<condition property="luceeVersionResolved" value="${luceeVersionQuery}" else="${luceeVersion}">
<isset property="luceeVersionQuery.isset"/>
</condition>
<!-- Check if luceeVersionResolved is in version query format (string/string/string) -->
<condition property="use.version.query">
<matches pattern="^[^/]+/[^/]+/[^/]+$" string="${luceeVersionResolved}"/>
</condition>
<!-- Check if luceeJar is set for later targets -->
<condition property="use-local-jar">
<and>
<isset property="luceeJar"/>
<not>
<equals arg1="${luceeJar}" arg2=""/>
</not>
</and>
</condition>
</target>
<!-- Detect whether we need javax (Lucee 5/6) or jakarta (Lucee 7+) dependencies -->
<!-- Runs after version resolution so we only handle standard version formats -->
<target name="detect-version-type">
<!-- useLuceeVersion is already set by use-local-jar/use-version/query-version -->
<property name="version.for.detection" value="${useLuceeVersion}"/>
<!-- Extract major version number from version string -->
<!-- Handles: 7.0.0.1, lucee-7.0.jar, 7/snapshot/zero, D:/path/lucee-zero-7.0.jar -->
<loadresource property="version.major.extracted">
<propertyresource name="version.for.detection"/>
<filterchain>
<tokenfilter>
<!-- Extract number after last dash or slash, or at start if no dash/slash -->
<replaceregex pattern="^(?:.*[-/])?([0-9]+)\..*$" replace="\1" flags="s"/>
</tokenfilter>
</filterchain>
</loadresource>
<!-- Check if major version is 5 or 6 (use javax), otherwise use jakarta (7+) -->
<condition property="usesJavax">
<or>
<equals arg1="${version.major.extracted}" arg2="5"/>
<equals arg1="${version.major.extracted}" arg2="6"/>
</or>
</condition>
<!-- Select pom file based on version -->
<condition property="pom.file" value="pom-javax.xml" else="pom-jakarta.xml">
<isset property="usesJavax"/>
</condition>
<condition property="servlet.type" value="javax" else="jakarta">
<isset property="usesJavax"/>
</condition>
<echo message="Detected ${servlet.type} servlet API for Lucee ${version.major.extracted} (from: ${version.for.detection})"/>
</target>
<target name="setEnv" depends="detect-version-type">
<artifact:pom id="pom" file="${pom.file}"/>
<artifact:dependencies filesetId="mydeps" pomRefId="pom" />
<pathconvert property="dependencies" refid="mydeps"/>
<property name="runtime_classpath" value="${java.class.path}:${dependencies}"/>
<condition property="javaAgent.isset">
<and>
<isset property="javaAgent"/>
<not>
<equals arg1="${javaAgent}" arg2=""/>
</not>
</and>
</condition>
<condition property="jvmProperties.isset">
<and>
<isset property="jvmProperties"/>
<not>
<equals arg1="${jvmProperties}" arg2=""/>
</not>
</and>
</condition>
<condition property="jvmArgs.isset">
<and>
<isset property="jvmArgs"/>
<not>
<equals arg1="${jvmArgs}" arg2=""/>
</not>
</and>
</condition>
</target>
<target name="use-local-jar" if="use-local-jar">
<available file="${luceeJar}" property="local.jar.exists"/>
<fail message="Local Lucee JAR not found: ${luceeJar}" unless="local.jar.exists"/>
<basename property="luceeFilename" file="${luceeJar}"/>
<property name="useLuceeVersion" value="${luceeFilename}"/>
<property name="luceeJarPath" value="${luceeJar}"/>
<echo message="Using local Lucee JAR: ${luceeJar}"/>
<!-- Set flag to skip download -->
<property name="skip.download" value="true"/>
</target>
<target name="set-unique-working-dir" depends="use-version,query-version">
<!-- Check if uniqueWorkingDir is set and not "false" -->
<condition property="use.unique.dir">
<and>
<isset property="uniqueWorkingDir"/>
<not>
<equals arg1="${uniqueWorkingDir}" arg2="false"/>
</not>
</and>
</condition>
<sequential if:true="${use.unique.dir}">
<!-- Check if uniqueWorkingDir is "true" (auto-generate) or a custom path -->
<condition property="is.auto.unique">
<equals arg1="${uniqueWorkingDir}" arg2="true"/>
</condition>
<!-- Auto-generate unique directory if uniqueWorkingDir="true" -->
<sequential if:true="${is.auto.unique}">
<tstamp>
<format property="timestamp" pattern="yyyyMMdd-HHmmss"/>
<format property="randomId" pattern="SSS" offset="0" unit="millisecond"/>
</tstamp>
<!-- Remove 'lucee-' prefix and '.jar' suffix from useLuceeVersion for temp dir name -->
<basename property="luceeBaseName" file="${useLuceeVersion}" suffix=".jar"/>
<property name="luceeVersionOnly" value="${luceeBaseName}"/>
<property name="uniqueTempDir" location="temp-unique/${luceeVersionOnly}-${timestamp}-${randomId}"/>
<echo message="Using auto-generated unique working directory: ${uniqueTempDir}"/>
</sequential>
<!-- Use custom path if uniqueWorkingDir is not "true" -->
<sequential unless:true="${is.auto.unique}">
<property name="uniqueTempDir" location="${uniqueWorkingDir}"/>
<echo message="Using custom working directory: ${uniqueTempDir}"/>
</sequential>
<!-- Race condition check: fail if directory already exists (only when preCleanup is true) -->
<fail message="Race condition detected: Working directory ${uniqueTempDir} already exists!">
<condition>
<and>
<istrue value="${preCleanup}"/>
<available file="${uniqueTempDir}" type="dir"/>
</and>
</condition>
</fail>
</sequential>
</target>
<target name="use-version" unless="use.version.query">
<sequential unless:set="use-local-jar">
<property name="useLuceeVersion" value="${luceeVersionResolved}"/>
<property name="luceeVersionUrl" value="${luceeCdnUrl}/lucee-${useLuceeVersion}.jar"/>
<property name="luceeFilename" value="lucee-${useLuceeVersion}.jar"/>
</sequential>
</target>
<target name="query-version" if="use.version.query">
<!-- Validate version query format: must be string/string/string -->
<fail message="Version query must be in the format string/string/string (e.g. 7/all/zero). Got: '${luceeVersionResolved}'">
<condition>
<not>
<matches pattern="^[^/]+/[^/]+/[^/]+$" string="${luceeVersionResolved}"/>
</not>
</condition>
</fail>
<sequential unless:set="use-local-jar">
<echo message="Getting latest Lucee version for ${luceeVersionResolved}" />
<tstamp>
<format property="temp.timestamp" pattern="yyyyMMddHHmmssSSS"/>
</tstamp>
<property name="temp.file" value="${java.io.tmpdir}/lucee-version-query-${temp.timestamp}.txt"/>
<get src="${luceeUpdateProvider}${luceeVersionResolved}/filename" dest="${temp.file}" verbose="true"/>
<loadfile property="luceeFilename" srcFile="${temp.file}">
<filterchain>
<tokenfilter>
<replaceregex pattern='"' replace="" flags="g"/>
</tokenfilter>
</filterchain>
</loadfile>
<property name="luceeVersionUrl" value="${luceeCdnUrl}/${luceeFilename}"/>
<property name="useLuceeVersion" value="${luceeFilename}"/>
<echo message="Lucee version: ${useLuceeVersion}" />
<delete file="${temp.file}"/>
</sequential>
</target>
<target name="check-lucee-jar">
<condition property="lucee.jar.present">
<or>
<isset property="use-local-jar"/>
<available file="${cache}/${luceeFilename}"/>
</or>
</condition>
</target>
<target name="download-lucee-jar" unless="lucee.jar.present">
<sequential unless:set="use-local-jar">
<mkdir dir="${cache}"/>
<get src="${luceeVersionUrl}" dest="${cache}/${luceeFilename}" verbose="true"/>
</sequential>
</target>
<target name="run-cfml">
<condition property="tempDir" value="${uniqueTempDir}" else="${temp}">
<isset property="uniqueTempDir"/>
</condition>
<!-- Check for Windows trailing backslash issue -->
<condition property="isWindows">
<os family="windows"/>
</condition>
<fail message="Webroot path '${webroot}' ends with backslash (\) which causes escape character issues on Windows. Please remove the trailing backslash or use forward slash (/)." if:true="${isWindows}">
<condition>
<matches pattern=".*\\$" string="${webroot}"/>
</condition>
</fail>
<!-- Build proper file path for execute script validation -->
<!-- Normalize execute path: remove any leading slashes from execute -->
<loadresource property="execute.nolead">
<propertyresource name="execute"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="^[/\\]+" replace="" flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<!-- If webroot.abs ends with / or \, don't add extra separator -->
<condition property="webroot.abs.ends.with.sep">
<matches pattern=".*[/\\]$" string="${webroot.abs}"/>
</condition>
<condition property="execute.fullpath" value="${webroot.abs}${execute.nolead}" else="${webroot.abs}/${execute.nolead}">
<isset property="webroot.abs.ends.with.sep"/>
</condition>
<!-- Improved error message with resolved paths -->
<fail message="Execute script not found. webroot=${webroot} script=${execute.fullpath}. Use absolute or relative paths for -Dwebroot. Both are supported.">
<condition>
<and>
<not>
<available file="${execute.fullpath}" type="file"/>
</not>
<not>
<equals arg1="${execute}" arg2=""/>
</not>
</and>
</condition>
</fail>
<!-- Extract basename of webroot for JFR filename -->
<basename property="webroot.name" file="${webroot}"/>
<!-- Clean execute path (remove leading slash/backslash) for JFR filename -->
<loadresource property="execute.clean">
<propertyresource name="execute"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="^[/\\]" replace="" flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<!-- Ensure we have timestamp for JFR filename (may already be set from unique dir logic) -->
<tstamp unless:set="timestamp">
<format property="timestamp" pattern="yyyyMMdd-HHmmss"/>
</tstamp>
<!-- Set JFR log filename -->
<condition property="jfrLogname" value="${FlightRecordingFilename}" else="${basedir}/logs/${timestamp}-j${ant.java.version}.jfr">
<and>
<isset property="FlightRecordingFilename"/>
<not>
<equals arg1="${FlightRecordingFilename}" arg2=""/>
</not>
</and>
</condition>
<echo message="Java: ${java.version}, ${java.home}" />
<echo message="Lucee: ${useLuceeVersion}" />
<echo message="luceeJar: ${luceeJar}" />
<echo message="Working Dir: ${tempDir}" />
<echo message="Webroot: ${webroot}" />
<echo message="Webroot (normalized): ${webroot.abs}" />
<echo message="Execute: ${execute}" />
<echo message="ExtensionDir: ${extensionDir}" />
<echo message="Extensions: ${extensions}" />
<echo message="executeScriptByInclude: ${executeScriptByInclude}" />
<echo message="luceeCFConfig: ${luceeCFConfig}" />
<echo message="javaDebugger: ${debugger}" />
<echo message="jvmProperties: ${jvmProperties}" if:set="jvmProperties.isset" />
<echo message="jvmArgs: ${jvmArgs}" if:set="jvmArgs.isset" />
<echo message="javaAgent: ${javaAgent}" if:set="javaAgent.isset" />
<echo message="jdwp: ${jdwp} (port ${jdwpPort})" if:true="${jdwp}" />
<echo message="JFR log: ${jfrLogname}" if:true="${FlightRecording}" />
<echo message="" />
<!-- execute CFML testcases -->
<delete dir="${tempDir}" if:true="${preCleanup}"/>
<mkdir dir="${tempDir}"/>
<mkdir dir="${tempDir}/lucee"/>
<mkdir dir="${tempDir}/lucee/web"/>
<mkdir dir="${tempDir}/lucee/lucee-server/context"/>
<mkdir dir="${tempDir}/lucee/lucee-server/deploy"/>
<!-- create logs directory for JFR files -->
<mkdir dir="${basedir}/logs"/>
<!-- set a default admin password
<echo file="${temp}/lucee/lucee-server/context/password.txt" append="false">admin</echo>
-->
<!--
<echoproperties destFile="${temp}/lucee/ant_args.properties"/>
-->
<!-- Determine JAR path: use local JAR if provided, otherwise use cached JAR -->
<condition property="lucee.jar.path" value="${luceeJar}" else="${cache}/${luceeFilename}">
<isset property="use-local-jar"/>
</condition>
<java classname="org.apache.tools.ant.launch.Launcher" dir="${tempDir}/lucee" fork="true" failonerror="true" errorproperty="errorOut" resultproperty="resultOut">
<classpath path="${java.class.path}">
<pathelement location="${lucee.jar.path}"/>
<pathelement path="${runtime_classpath}"/>
</classpath>
<arg value="-f"/>
<arg value="${basedir}/build-run-cfml.xml"/>
<jvmarg value="-Dlucee.base.dir=${tempDir}/lucee"/>
<jvmarg value="-Dlucee.web.dir=${tempDir}/lucee/web"/>
<jvmarg value="-Dlucee.cli.contextRoot=${webroot.abs}"/>
<jvmarg value="-Dwebroot=${webroot.abs}"/>
<jvmarg value="-Dexecute=${execute}"/>
<jvmarg value="-DexecuteScriptByInclude=${executeScriptByInclude}"/>
<jvmarg value="-DextensionDir=${extensionDir}"/>
<jvmarg value="-Dlucee.extensions=${extensions}"/>
<jvmarg value="-Dlucee.mapping.first=true"/>
<jvmarg value="-Dcompile=${compile}"/>
<!--
<jvmarg value="-Dlucee.cli.printExceptions=true"/>
-->
<jvmarg value="-Dlucee.base.config=${luceeCFConfig}"/>
<jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5000" if:true="${debugger}"/>
<jvmarg value="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=localhost:${jdwpPort}" if:true="${jdwp}"/>
<jvmarg value="--add-opens=java.base/java.lang=ALL-UNNAMED" if:set="javaAgent.isset"/>
<jvmarg value="-javaagent:${javaAgent}" if:set="javaAgent.isset" unless:set="javaAgentArgs.isset"/>
<jvmarg value="-javaagent:${javaAgent}=${javaAgentArgs}" if:set="javaAgentArgs.isset"/>
<jvmarg value="-XX:+UnlockExperimentalVMOptions" if:true="${UseEpsilonGC}"/>
<jvmarg value="-XX:+UseEpsilonGC" if:true="${UseEpsilonGC}"/>
<jvmarg value="-XX:+AlwaysPreTouch" if:true="${UseEpsilonGC}"/>
<jvmarg value="-XX:StartFlightRecording=disk=true,dumponexit=true,filename=${jfrLogname},maxsize=1024m,maxage=1d,settings=${FlightRecordingSettings},path-to-gc-roots=true" if:true="${FlightRecording}"/>
<jvmarg value="-XX:FlightRecorderOptions=stackdepth=128" if:true="${FlightRecording}"/>
<jvmarg value="--add-exports=jdk.jfr/jdk.jfr=ALL-UNNAMED" if:true="${jfrExports}"/>
<jvmarg value="--add-opens=jdk.jfr/jdk.jfr=ALL-UNNAMED" if:true="${jfrExports}"/>
<jvmarg value="-XX:+PrintGCDetails" if:true="${PrintGCDetails}"/>
<jvmarg value="-Dproperties.filename=${jvmProperties}" if:set="jvmProperties.isset"/>
<jvmarg line="${jvmArgs}" if:set="jvmArgs.isset"/>
<jvmarg value="-XX:+UnlockDiagnosticVMOptions" if:true="${PrintInlining}"/>
<jvmarg value="-XX:+PrintInlining" if:true="${PrintInlining}"/>
<jvmarg value="-XX:+PrintCompilation" if:true="${PrintInlining}"/>
<jvmarg value="-XX:+HeapDumpOnOutOfMemoryError" />
<!--
<jvmarg value="-XX:+UseCompactObjectHeaders" />
<jvmarg value="-Xdebug"/>
<jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"/>
<jvmarg value="-Djava.net.useSystemProxies=true"/>
<jvmarg value="-Dhttps.proxyHost=127.0.0.1"/>
<jvmarg value="-Dhttps.proxyPort=8188"/>
<jvmarg value="-Dhttp.proxyHost=127.0.0.1"/>
<jvmarg value="-Dhttp.proxyPort=8188"/>
-->
</java>
<echo>${errorOut}</echo>
<delete dir="${tempDir}" if:true="${postCleanup}"/>
<echo message="JFR log: ${jfrLogname}" if:true="${FlightRecording}" />
<echo message="Finished!" />
</target>
</project>