hotel_gui_win.patch
| new/bootstrap_conversion.cmd 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 4 | 4 |
:: Determine script directory |
| 5 | 5 |
set scriptdir=%~dp0 |
| 6 | 6 |
|
| 7 |
:: Pass all arguments to PowerShell script |
|
| 8 |
pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "%scriptdir%bootstrap_conversion.ps1" %* |
|
| 7 |
:: Pass all arguments to PowerShell script, run_powershell.cmd picks the PowerShell which is installed |
|
| 8 |
call "%scriptdir%run_powershell.cmd" "%scriptdir%bootstrap_conversion.ps1" %* |
|
| 9 |
exit /b %ERRORLEVEL% |
|
| new/build.xml 2026-08-07 14:12:06 +0000 | ||
|---|---|---|
| 110 | 110 |
<os family="unix" /> |
| 111 | 111 |
</condition> |
| 112 | 112 | |
| 113 |
<!-- The PowerShell to run the .ps1 scripts with: PowerShell Core when it is installed, otherwise the |
|
| 114 |
Windows PowerShell which is preinstalled with Windows. A .cmd wrapper is not used here, ant |
|
| 115 |
cannot exec a batch file (CreateProcess only runs a real executable), which is also why the .ps1 |
|
| 116 |
scripts are passed to the interpreter instead of being exec'd directly. Should neither spelling |
|
| 117 |
of the variable resolve, this falls back to powershell, the one always present on Windows. |
|
| 118 | ||
| 119 |
Both env.PATH and env.Path are looked at: ant names these properties after the environment |
|
| 120 |
variables as the OS reports them, and Windows spells that one "Path". Checking only the |
|
| 121 |
uppercase name would silently build on the Windows PowerShell on a machine which does have |
|
| 122 |
PowerShell Core installed. --> |
|
| 123 |
<property environment="env" /> |
|
| 124 |
<available file="pwsh.exe" filepath="${env.PATH}" property="havePowerShellCore" />
|
|
| 125 |
<available file="pwsh.exe" filepath="${env.Path}" property="havePowerShellCore" />
|
|
| 126 |
<condition property="ps.executable" value="pwsh" else="powershell"> |
|
| 127 |
<isset property="havePowerShellCore" /> |
|
| 128 |
</condition> |
|
| 129 | ||
| 113 | 130 |
<condition property="escaped.quotes" value=""""" else="""> |
| 114 | 131 |
<isset property="isWindows" /> |
| 115 | 132 |
</condition> |
| ... | ... | |
| 139 | 156 | |
| 140 | 157 |
<!-- path used when running application related tasks --> |
| 141 | 158 |
<path id="app.classpath"> |
| 142 |
<fileset dir="${fwd.lib.home}" includes="*.jar"/>
|
|
| 143 |
<fileset dir="${deploy.home}/lib" includes="*.jar"/>
|
|
| 159 |
<pathelement location="${fwd.lib.home}/p2j.jar"/>
|
|
| 160 |
<pathelement location="${fwd.lib.home}/fwdspi.jar"/>
|
|
| 161 |
<pathelement location="${fwd.lib.home}/fwdaopltw.jar"/>
|
|
| 162 |
<pathelement location="${deploy.home}/lib/${appname}.jar"/>
|
|
| 144 | 163 |
</path> |
| 145 | 164 | |
| 146 | 165 |
<!-- path used when running database import tasks --> |
| 147 | 166 |
<path id="import.classpath"> |
| 148 |
<fileset dir="${fwd.lib.home}" includes="*.jar"/>
|
|
| 149 |
<fileset dir="${deploy.home}/lib" includes="*.jar"/>
|
|
| 150 |
<fileset dir="${build.home}/lib" includes="*.jar"/>
|
|
| 167 |
<pathelement location="${fwd.lib.home}/p2j.jar"/>
|
|
| 168 |
<pathelement location="${fwd.lib.home}/fwdspi.jar"/>
|
|
| 169 |
<pathelement location="${fwd.lib.home}/fwdaopltw.jar"/>
|
|
| 170 |
<pathelement location="${deploy.home}/lib/${appname}.jar"/>
|
|
| 171 |
<pathelement location="${build.home}/lib/${appname}.jar"/>
|
|
| 151 | 172 |
</path> |
| 152 |
|
|
| 173 | ||
| 174 |
<target name="show.classpath" description="Print the classpaths used by the java tasks."> |
|
| 175 |
<echo message="fwd.lib.home = ${fwd.lib.home}"/>
|
|
| 176 |
<echo message="deploy lib = ${deploy.home}/lib"/>
|
|
| 177 |
<echo message="compile.classpath = ${toString:compile.classpath}"/>
|
|
| 178 |
<echo message="app.classpath = ${toString:app.classpath}"/>
|
|
| 179 |
<echo message="import.classpath = ${toString:import.classpath}"/>
|
|
| 180 |
</target> |
|
| 181 | ||
| 153 | 182 |
<tstamp> |
| 154 | 183 |
<format property="DSTAMP" pattern="yyyyMMdd" /> |
| 155 | 184 |
</tstamp> |
| ... | ... | |
| 172 | 201 |
<target name="init-standard-df" depends="init-ant-contrib" |
| 173 | 202 |
description="Determine correct standard.df based on p2j build"> |
| 174 | 203 | |
| 175 |
<!-- Define script path --> |
|
| 204 |
<!-- Define script path. Windows cannot execute the bash script, it uses the .ps1 counterpart. --> |
|
| 205 |
<condition property="standard.selector.name" |
|
| 206 |
value="select_standard.ps1" else="select_standard.sh"> |
|
| 207 |
<isset property="isWindows"/> |
|
| 208 |
</condition> |
|
| 176 | 209 |
<property name="standard.selector.script" |
| 177 |
location="${data.rel}/select_standard.sh"/>
|
|
| 210 |
location="${data.rel}/${standard.selector.name}"/>
|
|
| 178 | 211 | |
| 179 | 212 |
<!-- Check if script exists --> |
| 180 | 213 |
<available file="${standard.selector.script}"
|
| ... | ... | |
| 187 | 220 |
<echo message="Using selector script: ${standard.selector.script}"/>
|
| 188 | 221 |
<exec executable="${standard.selector.script}"
|
| 189 | 222 |
outputproperty="standard.selector.result" |
| 190 |
failonerror="true"> |
|
| 223 |
failonerror="true" |
|
| 224 |
osfamily="unix"> |
|
| 225 |
<arg value="${data.rel}"/>
|
|
| 226 |
<arg value="${fwd.lib.home}/p2j.jar"/>
|
|
| 227 |
</exec> |
|
| 228 | ||
| 229 |
<!-- CreateProcess cannot run a .ps1 either, the interpreter is launched explicitly --> |
|
| 230 |
<exec executable="${ps.executable}"
|
|
| 231 |
outputproperty="standard.selector.result" |
|
| 232 |
failonerror="true" |
|
| 233 |
osfamily="windows"> |
|
| 234 |
<arg value="-NoProfile"/> |
|
| 235 |
<arg value="-ExecutionPolicy"/> |
|
| 236 |
<arg value="Bypass"/> |
|
| 237 |
<arg value="-File"/> |
|
| 238 |
<arg value="${standard.selector.script}"/>
|
|
| 191 | 239 |
<arg value="${data.rel}"/>
|
| 192 | 240 |
<arg value="${fwd.lib.home}/p2j.jar"/>
|
| 193 | 241 |
</exec> |
| ... | ... | |
| 209 | 257 |
<condition property="standard.source" |
| 210 | 258 |
value="${data.rel}/standard_post9950.df"
|
| 211 | 259 |
else="${data.rel}/standard_pre9950.df">
|
| 212 |
<equals arg1="${standard.selector.result}" arg2="post9950"/>
|
|
| 260 |
<!-- trim, the PowerShell selector terminates its output with a CRLF --> |
|
| 261 |
<equals arg1="${standard.selector.result}" arg2="post9950" trim="true"/>
|
|
| 213 | 262 |
</condition> |
| 214 | 263 | |
| 215 | 264 |
<!-- Perform copy only if not skip --> |
| 216 | 265 |
<if> |
| 217 | 266 |
<not> |
| 218 |
<equals arg1="${standard.selector.result}" arg2="skip"/>
|
|
| 267 |
<equals arg1="${standard.selector.result}" arg2="skip" trim="true"/>
|
|
| 219 | 268 |
</not> |
| 220 | 269 |
<then> |
| 221 | 270 |
<echo message="Copying ${standard.source} to ${data.rel}/standard.df"/>
|
| ... | ... | |
| 633 | 682 |
<arg value="deploy_appcds.sh"/> |
| 634 | 683 |
<arg value="${deploy.home}/lib/p2j.jar"/>
|
| 635 | 684 |
</exec> |
| 636 |
<exec executable="pwsh" dir="${deploy.home}/server" failonerror="true" osfamily="windows">
|
|
| 685 |
<exec executable="${ps.executable}" dir="${deploy.home}/server" failonerror="true" osfamily="windows">
|
|
| 637 | 686 |
<arg value="-ExecutionPolicy"/> |
| 638 | 687 |
<arg value="Bypass"/> |
| 639 | 688 |
<arg value="-File"/> |
| ... | ... | |
| 697 | 746 |
<arg value="-no"/> |
| 698 | 747 |
</exec> |
| 699 | 748 | |
| 700 |
<exec executable="pwsh" dir="." failonerror="true" osfamily="windows">
|
|
| 749 |
<exec executable="${ps.executable}" dir="." failonerror="true" osfamily="windows">
|
|
| 701 | 750 |
<arg value="-ExecutionPolicy"/> |
| 702 | 751 |
<arg value="Bypass"/> |
| 703 | 752 |
<arg value="-File"/> |
| ... | ... | |
| 987 | 1036 |
<arg value="find ${app.4gl.src} -type f -name '*.w' ${e4gl-noclean} -exec grep -l ${e4gl.pattern} {} \; -exec rm -f {} +" />
|
| 988 | 1037 |
</exec> |
| 989 | 1038 | |
| 990 |
<exec executable="powershell" failonerror="true" osfamily="windows">
|
|
| 1039 |
<exec executable="${ps.executable}" failonerror="true" osfamily="windows">
|
|
| 991 | 1040 |
<arg value="-Command"/> |
| 992 | 1041 |
<arg value="Get-ChildItem -Path '${app.4gl.src}' -Filter '*.w' -Recurse | Select-String -Pattern ${e4gl-ps1.pattern} | ForEach-Object { Remove-Item $_.Path -Force }"/>
|
| 993 | 1042 |
</exec> |
| new/build_db.xml 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 14 | 14 |
<condition property="java.locale.providers.param" else="-Djava.locale.providers=SPI,JRE" value="-Djava.locale.providers=SPI,CLDR,COMPAT"> |
| 15 | 15 |
<javaversion atleast="11"/> |
| 16 | 16 |
</condition> |
| 17 |
<!-- Run with -Dclasspath.debug=true to have the forked JVMs report every class they load together |
|
| 18 |
with the jar it came from. The output is captured by the <record> log of the target. This is |
|
| 19 |
the only way to see the jars which the Class-Path manifest of p2j.jar contributes, those are |
|
| 20 |
resolved by the JVM and never appear in the classpath itself. --> |
|
| 21 |
<condition property="classpath.log.param" value="-verbose:class" else="-Dignorethis"> |
|
| 22 |
<isset property="classpath.debug"/> |
|
| 23 |
</condition> |
|
| 17 | 24 |
<if> |
| 18 | 25 |
<and> |
| 19 | 26 |
<isset property="db.sql.shared" /> |
| ... | ... | |
| 47 | 54 |
description="Creates an empty H2 database instance using the DDL generated during conversion." |
| 48 | 55 |
if="${db.h2}">
|
| 49 | 56 |
<record name="create_db_h2_${db.name}_${LOG_STAMP}.log" action="start"/>
|
| 57 |
<echo message="app.classpath = ${toString:app.classpath}"/>
|
|
| 50 | 58 |
<java classname="com.goldencode.p2j.persist.deploy.ScriptRunner" |
| 51 | 59 |
fork="true" |
| 52 | 60 |
failonerror="true" |
| ... | ... | |
| 54 | 62 |
<jvmarg value="-Xmx1g"/> |
| 55 | 63 |
<jvmarg value="${java.locale.providers.param}"/>
|
| 56 | 64 |
<jvmarg value="${java.ext.dir.param}"/>
|
| 65 |
<jvmarg value="${classpath.log.param}"/>
|
|
| 57 | 66 |
<jvmarg value="-Dfile.encoding=UTF-8"/> |
| 58 | 67 |
<jvmarg value="-Djava.util.logging.config.file=${fwd.home}/cfg/logging.properties"/>
|
| 59 | 68 |
<arg value ="${sql.url.h2}"/>
|
| ... | ... | |
| 72 | 81 |
description="Import data (.d files) into H2 database." |
| 73 | 82 |
if="${db.h2}">
|
| 74 | 83 |
<record name="import_db_h2_${db.name}_${LOG_STAMP}.log" action="start"/>
|
| 84 |
<echo message="import.classpath = ${toString:import.classpath}"/>
|
|
| 75 | 85 |
<java classname="com.goldencode.p2j.pattern.PatternEngine" |
| 76 | 86 |
fork="true" |
| 77 | 87 |
failonerror="true" |
| ... | ... | |
| 79 | 89 |
<jvmarg value="-Xmx1g"/> |
| 80 | 90 |
<jvmarg value="${java.locale.providers.param}"/>
|
| 81 | 91 |
<jvmarg value="${java.ext.dir.param}"/>
|
| 92 |
<jvmarg value="${classpath.log.param}"/>
|
|
| 82 | 93 |
<jvmarg value="-Dfile.encoding=UTF-8"/> |
| 83 | 94 |
<jvmarg value="-Djava.system.class.loader=com.goldencode.asm.AsmClassLoader"/> |
| 84 | 95 |
<arg value ="-d"/> |
| new/data/select_standard.ps1 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 1 |
# |
|
| 2 |
# The Windows counterpart of select_standard.sh, kept in sync with it: Windows cannot execute the bash |
|
| 3 |
# script, and the policy rules below decide which standard.df the build uses, so the two MUST agree. |
|
| 4 |
# |
|
| 5 |
param ( |
|
| 6 |
[Parameter(Position = 0, Mandatory = $true)] [string]$DataRel, |
|
| 7 |
[Parameter(Position = 1, Mandatory = $true)] [string]$JarPath |
|
| 8 |
) |
|
| 9 | ||
| 10 |
Set-StrictMode -Version Latest |
|
| 11 |
$ErrorActionPreference = 'Stop' |
|
| 12 | ||
| 13 |
# Get version line. Only stdout is captured, exactly as the "$(java -jar "$jar_path")" of |
|
| 14 |
# select_standard.sh does; whatever java puts on stderr is left to flow into the build log. |
|
| 15 |
# |
|
| 16 |
# The preference is relaxed for the call: Windows PowerShell turns the stderr of a native command |
|
| 17 |
# into an error record, which the $ErrorActionPreference = 'Stop' above would then make terminating, |
|
| 18 |
# and a JVM which merely reports "Picked up JAVA_TOOL_OPTIONS" would fail the build. PowerShell 7 |
|
| 19 |
# does not do this. |
|
| 20 |
$previousPreference = $ErrorActionPreference |
|
| 21 |
$ErrorActionPreference = 'Continue' |
|
| 22 |
try {
|
|
| 23 |
$output = (& java -jar $JarPath | Out-String).Trim() |
|
| 24 |
$javaExit = $LASTEXITCODE |
|
| 25 |
} |
|
| 26 |
finally {
|
|
| 27 |
$ErrorActionPreference = $previousPreference |
|
| 28 |
} |
|
| 29 | ||
| 30 |
# the counterpart of the "set -e" of select_standard.sh, which aborts on a failing java |
|
| 31 |
if ($javaExit -ne 0) |
|
| 32 |
{
|
|
| 33 |
[Console]::Error.WriteLine("ERROR: java -jar $JarPath failed with exit code $javaExit")
|
|
| 34 |
exit 1 |
|
| 35 |
} |
|
| 36 | ||
| 37 |
# Expect format: FWD v4.0.0_p2j_<branch>_<revision> |
|
| 38 |
if ($output -notmatch '_p2j_([^_]+)_([0-9]+)') |
|
| 39 |
{
|
|
| 40 |
[Console]::Error.WriteLine("ERROR: Unable to parse p2j output: $output")
|
|
| 41 |
exit 1 |
|
| 42 |
} |
|
| 43 | ||
| 44 |
$branch = $Matches[1] |
|
| 45 |
$revision = [int]$Matches[2] |
|
| 46 | ||
| 47 |
# Default to using post9950 update. Add policies for using older standard.df |
|
| 48 |
$usePre = $false |
|
| 49 | ||
| 50 |
# ---- Policy Rules ---- |
|
| 51 |
if ($branch -eq "trunk" -and $revision -lt 16415) |
|
| 52 |
{
|
|
| 53 |
$usePre = $true |
|
| 54 |
} |
|
| 55 | ||
| 56 |
# Policy example. Any of these should exist only until the branch is rebased to trunk_16415 |
|
| 57 | ||
| 58 |
#if ($branch -eq "9986c") |
|
| 59 |
#{
|
|
| 60 |
# $usePre = $true |
|
| 61 |
#} |
|
| 62 |
# ---------------------- |
|
| 63 | ||
| 64 |
if ($usePre) |
|
| 65 |
{
|
|
| 66 |
Write-Output "pre9950" |
|
| 67 |
exit 0 |
|
| 68 |
} |
|
| 69 | ||
| 70 |
# Fallback handling uses the in-place standard.df (post9950). Tell ant 'skip' |
|
| 71 |
if (!(Test-Path -LiteralPath (Join-Path $DataRel 'standard_pre9950.df') -PathType Leaf) -and |
|
| 72 |
(Test-Path -LiteralPath (Join-Path $DataRel 'standard.df') -PathType Leaf)) |
|
| 73 |
{
|
|
| 74 |
Write-Output "skip" |
|
| 75 |
exit 0 |
|
| 76 |
} |
|
| 77 | ||
| 78 |
Write-Output "post9950" |
|
| new/data/select_standard.sh 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 21 | 21 | |
| 22 | 22 |
# ---- Policy Rules ---- |
| 23 | 23 |
if [[ "$branch" == "trunk" && "$revision" -lt 16415 ]]; then |
| 24 |
use_post=false
|
|
| 24 |
use_pre=true
|
|
| 25 | 25 |
fi |
| 26 | 26 | |
| 27 | 27 |
# Policy example. Any of these should exist only until the branch is rebased to trunk_16415 |
| new/deploy/client/client.cmd 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 1 | 1 |
:: Standard FWD client startup script - Wrapper to client.ps1 |
| 2 | 2 |
@echo off |
| 3 | 3 |
setlocal |
| 4 |
pwsh -NoProfile -ExecutionPolicy Bypass -File "%~dp0client.ps1" %* |
|
| 5 |
endlocal |
|
| 4 | ||
| 5 |
:: PowerShell Core when it is installed, otherwise the Windows PowerShell which is preinstalled with |
|
| 6 |
:: Windows. %%~$PATH:I expands to the full path of the file when it is found on the PATH, and to an |
|
| 7 |
:: empty string when it is not. |
|
| 8 |
set "psexe=" |
|
| 9 |
for %%I in (pwsh.exe) do if not "%%~$PATH:I" == "" set "psexe=%%~$PATH:I" |
|
| 10 |
if not defined psexe set "psexe=powershell.exe" |
|
| 11 | ||
| 12 |
"%psexe%" -NoProfile -ExecutionPolicy Bypass -File "%~dp0client.ps1" %* |
|
| 13 |
exit /b %ERRORLEVEL% |
|
| new/deploy/client/client.ps1 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 148 | 148 |
} |
| 149 | 149 | |
| 150 | 150 |
if ($debug) {
|
| 151 |
$daddress = Test-Path "/.dockerenv" ? "0.0.0.0:"+$dport : $dport |
|
| 151 |
# an if expression, the ?: ternary operator needs PowerShell 7 |
|
| 152 |
$daddress = if (Test-Path "/.dockerenv") { "0.0.0.0:" + $dport } else { $dport }
|
|
| 152 | 153 |
$dtxt = "-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address="+$daddress+",server=y,suspend="+$suspend |
| 153 | 154 |
} else {
|
| 154 | 155 |
$dtxt = "" |
| new/deploy/deploy_helpers.ps1 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 7 | 7 |
[string]$JavaExecutable = "java" # default to 'java' unless overridden |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 |
$output = & $JavaExecutable -version 2>&1 | |
|
| 10 |
# java writes its version banner to stderr, and Windows PowerShell turns the stderr of a native |
|
| 11 |
# command into an error record, which the $ErrorActionPreference = 'Stop' of the callers then makes |
|
| 12 |
# terminating ("NativeCommandError"). PowerShell 7 does not do this. Relax the preference for the
|
|
| 13 |
# call only, and stringify what comes back: with the streams merged the lines can arrive as error |
|
| 14 |
# records rather than as strings. |
|
| 15 |
$previousPreference = $ErrorActionPreference |
|
| 16 |
$ErrorActionPreference = 'Continue' |
|
| 17 |
try {
|
|
| 18 |
$versionLines = & $JavaExecutable -version 2>&1 | ForEach-Object { "$_" }
|
|
| 19 |
} |
|
| 20 |
finally {
|
|
| 21 |
$ErrorActionPreference = $previousPreference |
|
| 22 |
} |
|
| 23 |
|
|
| 24 |
$output = $versionLines | |
|
| 11 | 25 |
Where-Object { $_ -match 'version' } |
|
| 12 | 26 |
ForEach-Object {
|
| 13 | 27 |
if ($_ -match '"([\d._]+)"') {
|
| 14 | 28 |
$version = $matches[1] |
| 15 | 29 |
if ($version -like '1.*') {
|
| 16 | 30 |
$parts = $version -split '\.' |
| 17 |
return [int]("${parts[0]}${parts[1]}")
|
|
| 31 |
# "${parts[0]}" does not index, it names a variable called 'parts[0]'
|
|
| 32 |
return [int]("$($parts[0])$($parts[1])")
|
|
| 18 | 33 |
} else {
|
| 19 | 34 |
return [int]($version -split '[._]')[0] * 10 |
| 20 | 35 |
} |
| new/deploy/server/deploy_appcds.ps1 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 122 | 122 |
continue |
| 123 | 123 |
} |
| 124 | 124 | |
| 125 |
Write-Host "JVM classpath for $clientType: $clientCp"
|
|
| 126 |
Write-Host "JVM args for $clientType: $clientArgsStr"
|
|
| 125 |
Write-Host "JVM classpath for ${clientType}: $clientCp"
|
|
| 126 |
Write-Host "JVM args for ${clientType}: $clientArgsStr"
|
|
| 127 | 127 | |
| 128 | 128 |
# The archive is dumped below with our own -Xshare:dump and a fresh |
| 129 | 129 |
# -XX:SharedArchiveFile pointing at the .jsa we're generating. Strip the |
| new/deploy/server/prepare_dir.ps1 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 1 |
# prepare_dir.ps1 |
|
| 2 | ||
| 3 |
# Parse parameters |
|
| 4 |
param ( |
|
| 5 |
[switch]$o, |
|
| 6 |
[string]$f |
|
| 7 |
) |
|
| 8 | ||
| 9 |
Set-PSDebug -Trace 0 |
|
| 10 |
Set-StrictMode -Version Latest |
|
| 11 |
$ErrorActionPreference = 'Stop' |
|
| 12 | ||
| 13 |
# Ensure the script is running with administrative privileges |
|
| 14 |
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) |
|
| 15 |
{
|
|
| 16 |
Write-Host "This script requires administrative privileges. Restarting with elevation..." |
|
| 17 |
Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`"" -Verb RunAs |
|
| 18 |
exit |
|
| 19 |
} |
|
| 20 | ||
| 21 |
# Helper Functions |
|
| 22 |
function Show-Usage {
|
|
| 23 |
Write-Host "Usage: prepare_dir.ps1 [-o] [-f <json_cfg_file>]" |
|
| 24 |
} |
|
| 25 | ||
| 26 |
function Get-Val($Key, $Default, $File) {
|
|
| 27 |
if (Test-Path $File) {
|
|
| 28 |
$json = Get-Content $File | ConvertFrom-Json |
|
| 29 |
$val = $json | Select-Object -ExpandProperty $Key -ErrorAction SilentlyContinue |
|
| 30 |
return $(if ($null -eq $val) { $Default } else { $val })
|
|
| 31 |
} |
|
| 32 |
$Default |
|
| 33 |
} |
|
| 34 | ||
| 35 |
function Split-String($InputString) { return $InputString -split ',' }
|
|
| 36 | ||
| 37 |
# Defaults |
|
| 38 |
$infile = "prepare_dir.json" |
|
| 39 |
$keyboard = "US" |
|
| 40 |
$pljava = "FALSE" |
|
| 41 |
$def_p2j_entry = "start.p" |
|
| 42 |
$def_propath = ".;common;" |
|
| 43 |
$def_search_path = ".;common;" |
|
| 44 |
$defdbname = "hotel" |
|
| 45 | ||
| 46 |
if ($args -contains "-?" -or $args -contains "/?") |
|
| 47 |
{
|
|
| 48 |
Show-Usage |
|
| 49 |
exit 1 |
|
| 50 |
} |
|
| 51 | ||
| 52 |
if ($f) { $infile = $f }
|
|
| 53 |
if (!(Test-Path $infile)) { Write-Error "Input file not found: $infile"; Show-Usage; exit 1 }
|
|
| 54 | ||
| 55 |
# Read JSON values |
|
| 56 |
$cfg = @{
|
|
| 57 |
spawner_path = Get-Val "spawner_path" "/opt/spawner/spawn" $infile |
|
| 58 |
server_xml = Get-Val "server_xml_file" "server.xml" $infile |
|
| 59 |
directory_xml = Get-Val "directory_xml_file" "directory.xml" $infile |
|
| 60 |
client_start = Get-Val "client_start_dir" "./deploy/client" $infile |
|
| 61 |
dateFormat = Get-Val "dateFormat" "mdy" $infile |
|
| 62 |
numberGroupSep = Get-Val "numberGroupSep" "," $infile |
|
| 63 |
numberDecimalSep = Get-Val "numberDecimalSep" "." $infile |
|
| 64 |
p2j_entry = Get-Val "p2j_entry" $def_p2j_entry $infile |
|
| 65 |
pkgroot = Get-Val "pkgroot" "com.goldencode.hotel" $infile |
|
| 66 |
propath = Get-Val "propath" $def_propath $infile |
|
| 67 |
search_path = Get-Val "search_path" $def_search_path $infile |
|
| 68 |
path_separator = Get-Val "path_separator" ([IO.Path]::PathSeparator) $infile |
|
| 69 |
file_separator = Get-Val "file_separator" ([IO.Path]::DirectorySeparatorChar) $infile |
|
| 70 |
case_sensitive = Get-Val "case_sensitive" "TRUE" $infile |
|
| 71 |
os_user = Get-Val "os_user" $env:USERNAME $infile |
|
| 72 |
kbd_layout = Get-Val "kbd_layout" $keyboard $infile |
|
| 73 |
server_log = Get-Val "server_log" "../logs" $infile |
|
| 74 |
client_log = Get-Val "client_log" "../logs" $infile |
|
| 75 |
embedded_host = Get-Val "embedded_host" "localhost" $infile |
|
| 76 |
admin_port = Get-Val "admin_port" "7443" $infile |
|
| 77 |
dbnames = Get-Val "dbnames" $defdbname $infile |
|
| 78 |
client_lib_path = Get-Val "client_lib_path" "..\lib" $infile |
|
| 79 |
} |
|
| 80 | ||
| 81 |
$db_array = @(Split-String $cfg.dbnames) |
|
| 82 |
$defdatabase = $db_array[0] |
|
| 83 | ||
| 84 |
# Determine if we can now create the directory file |
|
| 85 |
if (Test-Path -LiteralPath $cfg.directory_xml -PathType Leaf) {
|
|
| 86 |
$dirfile = (Get-Item -LiteralPath $cfg.directory_xml).FullName |
|
| 87 |
} |
|
| 88 |
else {
|
|
| 89 |
$parent = if ([string]::IsNullOrWhiteSpace((Split-Path $cfg.directory_xml -Parent))) {
|
|
| 90 |
$PWD.Path # Use current directory if no parent in path |
|
| 91 |
} else {
|
|
| 92 |
(Get-Item (Split-Path $cfg.directory_xml -Parent)).FullName |
|
| 93 |
} |
|
| 94 |
$dirfile = Join-Path $parent (Split-Path $cfg.directory_xml -Leaf) |
|
| 95 |
} |
|
| 96 |
if ((Test-Path $dirfile) -and -not $o.IsPresent) {
|
|
| 97 |
Write-Error "Output file exists: $dirfile, and '-o' not given." |
|
| 98 |
Show-Usage |
|
| 99 |
exit 1 |
|
| 100 |
} |
|
| 101 | ||
| 102 |
# Templates processing |
|
| 103 |
(Get-Content "server.xml.template") -replace '{directory_xml_file}', $cfg.directory_xml | Set-Content $cfg.server_xml
|
|
| 104 | ||
| 105 |
$directoryTemplate = Get-Content "directory.xml.template" |
|
| 106 |
foreach ($k in $cfg.Keys) {
|
|
| 107 |
$directoryTemplate = $directoryTemplate -replace "\{$k\}", $cfg[$k]
|
|
| 108 |
} |
|
| 109 |
$directoryTemplate = $directoryTemplate -replace '{dbname}', $defdatabase
|
|
| 110 |
$directoryTemplate | Set-Content "directory_tmp.xml" |
|
| 111 | ||
| 112 |
# DB info and Java merge |
|
| 113 |
$dbdialect = @{
|
|
| 114 |
h2 = "com.goldencode.p2j.persist.dialect.P2JH2Dialect" |
|
| 115 |
postgres = "com.goldencode.p2j.persist.dialect.P2JPostgreSQLDialect" |
|
| 116 |
} |
|
| 117 |
$dbdriver = @{
|
|
| 118 |
h2 = "org.h2.Driver" |
|
| 119 |
postgres = "org.postgresql.Driver" |
|
| 120 |
} |
|
| 121 | ||
| 122 |
$fwd_lib = $env:FWD_LIB |
|
| 123 |
if (-not $fwd_lib) { $fwd_lib = "../../p2j" }
|
|
| 124 |
$p2j_jar = if (Test-Path "$fwd_lib/build/lib/p2j.jar") {
|
|
| 125 |
"$fwd_lib/build/lib/p2j.jar" |
|
| 126 |
} elseif (Test-Path "$fwd_lib/lib/p2j.jar") {
|
|
| 127 |
"$fwd_lib/lib/p2j.jar" |
|
| 128 |
} else {
|
|
| 129 |
"../../p2j/lib/p2j.jar" |
|
| 130 |
} |
|
| 131 | ||
| 132 |
foreach ($db in $db_array) {
|
|
| 133 |
$dbtype = Get-Val "$db.dbtype" "h2" $infile |
|
| 134 |
if ($dbtype -ne "none") {
|
|
| 135 |
$jdbc_url = if ($dbtype -eq "h2") {
|
|
| 136 |
$pljava = "TRUE" |
|
| 137 |
"h2:$(Get-Val "$db.dbpath" "../db" $infile)/$db;DB_CLOSE_DELAY=-1;MV_STORE=FALSE;RTRIM=TRUE" |
|
| 138 |
} else {
|
|
| 139 |
"postgresql://$(Get-Val "$db.dbhost" "localhost" $infile):$(Get-Val "$db.dbport" "5432" $infile)/$db" |
|
| 140 |
} |
|
| 141 | ||
| 142 |
$dbfile = "directory_db.xml.$db" |
|
| 143 |
(Get-Content "directory_db.xml.template") ` |
|
| 144 |
-replace '{dbhost}', (Get-Val "$db.dbhost" "localhost" $infile) `
|
|
| 145 |
-replace '{dbport}', (Get-Val "$db.dbport" "5432" $infile) `
|
|
| 146 |
-replace '{dbname}', $db `
|
|
| 147 |
-replace '{dbuser}', (Get-Val "$db.dbuser" "fwd_user" $infile) `
|
|
| 148 |
-replace '{dbuserpass}', (Get-Val "$db.dbuserpass" "user" $infile) `
|
|
| 149 |
-replace '{dbadmin}', (Get-Val "$db.dbadmin" "fwd_admin" $infile) `
|
|
| 150 |
-replace '{dbadminpass}', (Get-Val "$db.dbadminpass" "admin" $infile) `
|
|
| 151 |
-replace '{dbdialect}', $dbdialect[$dbtype] `
|
|
| 152 |
-replace '{dbdriver}', $dbdriver[$dbtype] `
|
|
| 153 |
-replace '{jdbc_url}', $jdbc_url `
|
|
| 154 |
-replace '{pljava}', $pljava `
|
|
| 155 |
-replace '{collation}', (Get-Val "$db.collation" "en_US@iso88591_fwd_basic" $infile) |
|
|
| 156 |
Set-Content $dbfile |
|
| 157 | ||
| 158 |
# Java DirectoryCopy |
|
| 159 |
java -Xmx256m -classpath $p2j_jar com.goldencode.p2j.directory.DirectoryCopy copy $dbfile /server/standard/database/ directory_tmp.xml /server/standard/database/ |
|
| 160 |
Remove-Item $dbfile |
|
| 161 |
} else {
|
|
| 162 |
Copy-Item "directory_nodb.xml.template" "directory_nodb.xml" |
|
| 163 |
} |
|
| 164 |
} |
|
| 165 | ||
| 166 |
Move-Item -Force "directory_tmp.xml" $dirfile |
|
| 167 | ||
| 168 |
exit 0 |
|
| 1 |
# |
|
| 2 |
# prepare_dir.ps1 - the Windows counterpart of prepare_dir.sh. |
|
| 3 |
# |
|
| 4 |
# Renders server.xml and directory.xml on the deployment machine from prepare_dir.json, which |
|
| 5 |
# json_template.ps1 -d (or json_template.sh -d) produces at build time. |
|
| 6 |
# |
|
| 7 |
# Run this from the directory holding the templates, deploy/server, exactly as prepare_dir.sh is. |
|
| 8 |
# |
|
| 9 |
param ( |
|
| 10 |
[switch]$o, |
|
| 11 |
[string]$f |
|
| 12 |
) |
|
| 13 |
|
|
| 14 |
Set-PSDebug -Trace 0 |
|
| 15 |
Set-StrictMode -Version Latest |
|
| 16 |
$ErrorActionPreference = 'Stop' |
|
| 17 |
|
|
| 18 |
function Show-Usage |
|
| 19 |
{
|
|
| 20 |
Write-Host "Usage: prepare_dir.ps1 [-o] [-f <json_cfg_file>]" |
|
| 21 |
Write-Host "Where:" |
|
| 22 |
Write-Host " o = Overwrite the specified directory.xml, if it already exists." |
|
| 23 |
Write-Host " f = Use <json_cfg_file> instead of prepare_dir.json as input." |
|
| 24 |
} |
|
| 25 |
|
|
| 26 |
$utf8NoBom = New-Object System.Text.UTF8Encoding($false) |
|
| 27 |
|
|
| 28 |
# Property lookup which tolerates a missing key under Set-StrictMode; $cfg.$Key would throw. |
|
| 29 |
function Get-Node |
|
| 30 |
{
|
|
| 31 |
param ( |
|
| 32 |
$Object, |
|
| 33 |
[string]$Key |
|
| 34 |
) |
|
| 35 |
|
|
| 36 |
if ($null -eq $Object) { return $null }
|
|
| 37 |
|
|
| 38 |
$prop = $Object.PSObject.Properties[$Key] |
|
| 39 |
if ($null -eq $prop) { return $null }
|
|
| 40 |
|
|
| 41 |
return $prop.Value |
|
| 42 |
} |
|
| 43 |
|
|
| 44 |
function Get-Val |
|
| 45 |
{
|
|
| 46 |
param ( |
|
| 47 |
[string]$Key, |
|
| 48 |
[string]$Default = "" |
|
| 49 |
) |
|
| 50 |
|
|
| 51 |
$val = Get-Node $script:cfg $Key |
|
| 52 |
if ($null -eq $val -or "$val" -eq "") { return $Default }
|
|
| 53 |
|
|
| 54 |
return "$val" |
|
| 55 |
} |
|
| 56 |
|
|
| 57 |
# The per-database values live in a sub-object named after the database, so the lookup is two |
|
| 58 |
# levels. This used to pass "<db>.<key>" as a single property name to Select-Object, which never |
|
| 59 |
# resolves against nested json and silently handed back every default: with |
|
| 60 |
# prepare_dir_h2_docker.json that turned dbpath into "../db" instead of "/opt/hotel/db", and did the |
|
| 61 |
# same to the collation, the users and their passwords. |
|
| 62 |
function Get-SubVal |
|
| 63 |
{
|
|
| 64 |
param ( |
|
| 65 |
[string]$SubName, |
|
| 66 |
[string]$Key, |
|
| 67 |
[string]$Default = "" |
|
| 68 |
) |
|
| 69 |
|
|
| 70 |
$node = Get-Node $script:cfg $SubName |
|
| 71 |
$val = Get-Node $node $Key |
|
| 72 |
if ($null -eq $val -or "$val" -eq "") { return $Default }
|
|
| 73 |
|
|
| 74 |
return "$val" |
|
| 75 |
} |
|
| 76 |
|
|
| 77 |
# Replaces every {key} of a template with its value and writes the result. A literal String.Replace
|
|
| 78 |
# and not the -replace operator: -replace is a regular expression on both sides, so a value holding |
|
| 79 |
# a $ or a \ would be mangled - a database password is the obvious way to hit that. |
|
| 80 |
function Expand-Template |
|
| 81 |
{
|
|
| 82 |
param ( |
|
| 83 |
[string]$Template, |
|
| 84 |
[hashtable]$Values, |
|
| 85 |
[string]$Destination |
|
| 86 |
) |
|
| 87 |
|
|
| 88 |
if (!(Test-Path -LiteralPath $Template -PathType Leaf)) |
|
| 89 |
{
|
|
| 90 |
throw "Could not create $Destination, the template $Template was not found." |
|
| 91 |
} |
|
| 92 |
|
|
| 93 |
$content = [System.IO.File]::ReadAllText((Resolve-Path -LiteralPath $Template).Path) |
|
| 94 |
|
|
| 95 |
foreach ($key in $Values.Keys) |
|
| 96 |
{
|
|
| 97 |
$content = $content.Replace("{$key}", [string]$Values[$key])
|
|
| 98 |
} |
|
| 99 |
|
|
| 100 |
[System.IO.File]::WriteAllText($Destination, $content, $utf8NoBom) |
|
| 101 |
} |
|
| 102 |
|
|
| 103 |
if ($args -contains "-?" -or $args -contains "/?" -or $args -contains "-h") |
|
| 104 |
{
|
|
| 105 |
Show-Usage |
|
| 106 |
exit 1 |
|
| 107 |
} |
|
| 108 |
|
|
| 109 |
$infile = if ($f) { $f } else { "prepare_dir.json" }
|
|
| 110 |
if (!(Test-Path -LiteralPath $infile -PathType Leaf)) |
|
| 111 |
{
|
|
| 112 |
Write-Error "Input file not found: $infile" |
|
| 113 |
Show-Usage |
|
| 114 |
exit 1 |
|
| 115 |
} |
|
| 116 |
|
|
| 117 |
$here = (Get-Location).Path |
|
| 118 |
|
|
| 119 |
# System.IO and every native command resolve a relative path against the PROCESS working |
|
| 120 |
# directory, which PowerShell's own location does not track; keep the two in step. |
|
| 121 |
[Environment]::CurrentDirectory = $here |
|
| 122 |
$cfg = [System.IO.File]::ReadAllText((Resolve-Path -LiteralPath $infile).Path) | ConvertFrom-Json |
|
| 123 |
|
|
| 124 |
# Nothing below carries an application specific default any more: pkgroot used to fall back to |
|
| 125 |
# "com.goldencode.hotel" and dbnames to "hotel", so a deployment whose json was missing either one |
|
| 126 |
# was configured for the sample application instead of failing. |
|
| 127 |
$pkgroot = Get-Val "pkgroot" |
|
| 128 |
$dbnames = Get-Val "dbnames" |
|
| 129 |
if ([string]::IsNullOrEmpty($pkgroot)) |
|
| 130 |
{
|
|
| 131 |
Write-Error "No 'pkgroot' in $infile." |
|
| 132 |
exit 1 |
|
| 133 |
} |
|
| 134 |
if ([string]::IsNullOrEmpty($dbnames)) |
|
| 135 |
{
|
|
| 136 |
Write-Error "No 'dbnames' in $infile." |
|
| 137 |
exit 1 |
|
| 138 |
} |
|
| 139 |
|
|
| 140 |
# dbnames is a comma separated string in prepare_template.json but a real json array in the |
|
| 141 |
# prepare_dir_*_docker.json files; accept either. Splitting an array on ',' joined its elements |
|
| 142 |
# with a space and yielded a single bogus name. |
|
| 143 |
$dbnamesNode = Get-Node $cfg "dbnames" |
|
| 144 |
if ($dbnamesNode -is [System.Array]) |
|
| 145 |
{
|
|
| 146 |
$db_array = @($dbnamesNode | ForEach-Object { "$_".Trim() } | Where-Object { $_ -ne "" })
|
|
| 147 |
} |
|
| 148 |
else |
|
| 149 |
{
|
|
| 150 |
$db_array = @($dbnames -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" })
|
|
| 151 |
} |
|
| 152 |
$defdatabase = $db_array[0] |
|
| 153 |
|
|
| 154 |
$directory_xml = Get-Val "directory_xml_file" "directory.xml" |
|
| 155 |
$server_xml = Get-Val "server_xml_file" "server.xml" |
|
| 156 |
|
|
| 157 |
# The spawner default follows this host, it used to be the Linux "/opt/spawner/spawn". |
|
| 158 |
$spawner_path = Get-Val "spawner_path" (Join-Path $env:ProgramData 'FWD\spawner\spawn.exe') |
|
| 159 |
$client_start_dir = Get-Val "client_start_dir" (Join-Path (Split-Path $here -Parent) 'client') |
|
| 160 |
|
|
| 161 |
$client_lib_path = Get-SubVal "appcds" "client_lib_path" "..\lib" |
|
| 162 |
$webclient_appcds_archive = Get-SubVal "appcds" "webclient_appcds_archive" "" |
|
| 163 |
$webclient_appcds_jvmargs = (Get-SubVal "appcds" "webclient_appcds_jvmargs" "").Replace( |
|
| 164 |
"{archive}", $webclient_appcds_archive)
|
|
| 165 |
$webclient_memory = Get-Val "webclient_memory" "128m" |
|
| 166 |
|
|
| 167 |
# The libPath node is emitted only when an AppCDS block is configured, as json_template does. |
|
| 168 |
if ($null -ne (Get-Node $cfg "appcds")) |
|
| 169 |
{
|
|
| 170 |
$libpath_rendered = @" |
|
| 171 |
<node class="string" name="libPath"> |
|
| 172 |
<node-attribute name="value" value="$client_lib_path"/> |
|
| 173 |
</node> |
|
| 174 |
"@ |
|
| 175 |
} |
|
| 176 |
else |
|
| 177 |
{
|
|
| 178 |
$libpath_rendered = "" |
|
| 179 |
} |
|
| 180 |
|
|
| 181 |
# Where the directory.xml ends up; a bare file name has no parent, which Join-Path rejects. |
|
| 182 |
$dirParent = Split-Path -Path $directory_xml -Parent |
|
| 183 |
if ([string]::IsNullOrWhiteSpace($dirParent)) { $dirParent = "." }
|
|
| 184 |
if (!(Test-Path -LiteralPath $dirParent -PathType Container)) |
|
| 185 |
{
|
|
| 186 |
Write-Error "The directory holding $directory_xml does not exist: $dirParent" |
|
| 187 |
exit 1 |
|
| 188 |
} |
|
| 189 |
$dirfile = Join-Path (Resolve-Path -LiteralPath $dirParent).Path (Split-Path -Path $directory_xml -Leaf) |
|
| 190 |
|
|
| 191 |
if ((Test-Path -LiteralPath $dirfile) -and -not $o.IsPresent) |
|
| 192 |
{
|
|
| 193 |
Write-Error "Output file exists: $dirfile, and '-o' not given." |
|
| 194 |
Show-Usage |
|
| 195 |
exit 1 |
|
| 196 |
} |
|
| 197 |
|
|
| 198 |
# prepare_dir.sh reaches for sudo here, and only here, when the destination is not writable. There |
|
| 199 |
# is no in-place equivalent on Windows, and self-elevating the whole script would restart it in |
|
| 200 |
# system32 where none of the relative template paths below resolve, so the condition is reported |
|
| 201 |
# instead and the operator re-runs from an elevated prompt. |
|
| 202 |
$probe = Join-Path (Split-Path $dirfile -Parent) ".prepare_dir.probe" |
|
| 203 |
try |
|
| 204 |
{
|
|
| 205 |
[System.IO.File]::WriteAllText($probe, "") |
|
| 206 |
Remove-Item -LiteralPath $probe -Force |
|
| 207 |
} |
|
| 208 |
catch |
|
| 209 |
{
|
|
| 210 |
Write-Error ("Cannot write to $(Split-Path $dirfile -Parent). Re-run this script from an " +
|
|
| 211 |
"elevated prompt, or grant yourself write access to that directory.") |
|
| 212 |
exit 1 |
|
| 213 |
} |
|
| 214 |
|
|
| 215 |
# --------------------------------------------------------------------------------------------------- |
|
| 216 |
# server.xml and directory.xml |
|
| 217 |
# --------------------------------------------------------------------------------------------------- |
|
| 218 |
Expand-Template 'server.xml.template' @{ directory_xml_file = $directory_xml } $server_xml
|
|
| 219 |
|
|
| 220 |
# Every marker of directory.xml.template is listed. client_start_dir, libPath, |
|
| 221 |
# webclient_appcds_jvmargs and webclient_memory used to be absent, so they survived into the |
|
| 222 |
# generated directory.xml verbatim. admin_console_pw is deliberately left alone, json_template does |
|
| 223 |
# not fill it either. |
|
| 224 |
Expand-Template 'directory.xml.template' @{
|
|
| 225 |
spawner_path = $spawner_path |
|
| 226 |
client_start_dir = $client_start_dir |
|
| 227 |
libPath = $libpath_rendered |
|
| 228 |
dateFormat = (Get-Val "dateFormat" "mdy") |
|
| 229 |
numberGroupSep = (Get-Val "numberGroupSep" ",") |
|
| 230 |
numberDecimalSep = (Get-Val "numberDecimalSep" ".") |
|
| 231 |
p2j_entry = (Get-Val "p2j_entry" "start.p") |
|
| 232 |
pkgroot = $pkgroot |
|
| 233 |
propath = (Get-Val "propath" ".") |
|
| 234 |
search_path = (Get-Val "search_path" ".") |
|
| 235 |
path_separator = (Get-Val "path_separator" ";") |
|
| 236 |
file_separator = (Get-Val "file_separator" "\") |
|
| 237 |
case_sensitive = (Get-Val "case_sensitive" "FALSE") |
|
| 238 |
os_user = (Get-Val "os_user" $env:USERNAME) |
|
| 239 |
kbd_layout = (Get-Val "kbd_layout" "US") |
|
| 240 |
dbname = $defdatabase |
|
| 241 |
server_log = (Get-Val "server_log" "../logs") |
|
| 242 |
client_log = (Get-Val "client_log" "../logs") |
|
| 243 |
embedded_host = (Get-Val "embedded_host" "localhost") |
|
| 244 |
admin_port = (Get-Val "admin_port" "7443") |
|
| 245 |
webclient_appcds_jvmargs = $webclient_appcds_jvmargs |
|
| 246 |
webclient_memory = $webclient_memory |
|
| 247 |
} 'directory_tmp.xml' |
|
| 248 |
|
|
| 249 |
# --------------------------------------------------------------------------------------------------- |
|
| 250 |
# Merge each database into the directory |
|
| 251 |
# --------------------------------------------------------------------------------------------------- |
|
| 252 |
$dbdialect = @{
|
|
| 253 |
h2 = "com.goldencode.p2j.persist.dialect.P2JH2Dialect" |
|
| 254 |
postgres = "com.goldencode.p2j.persist.dialect.P2JPostgreSQLDialect" |
|
| 255 |
} |
|
| 256 |
$dbdriver = @{
|
|
| 257 |
h2 = "org.h2.Driver" |
|
| 258 |
postgres = "org.postgresql.Driver" |
|
| 259 |
} |
|
| 260 |
|
|
| 261 |
$fwd_lib = if ($env:FWD_LIB) { $env:FWD_LIB } else { "../../p2j" }
|
|
| 262 |
$p2j_jar = if (Test-Path -LiteralPath "$fwd_lib/build/lib/p2j.jar") { "$fwd_lib/build/lib/p2j.jar" }
|
|
| 263 |
elseif (Test-Path -LiteralPath "$fwd_lib/lib/p2j.jar") { "$fwd_lib/lib/p2j.jar" }
|
|
| 264 |
else { "../../p2j/lib/p2j.jar" }
|
|
| 265 |
|
|
| 266 |
foreach ($db in $db_array) |
|
| 267 |
{
|
|
| 268 |
$dbtype = Get-SubVal $db "dbtype" "h2" |
|
| 269 |
|
|
| 270 |
if ($dbtype -eq "none") |
|
| 271 |
{
|
|
| 272 |
Copy-Item -LiteralPath 'directory_nodb.xml.template' -Destination 'directory_nodb.xml' -Force |
|
| 273 |
continue |
|
| 274 |
} |
|
| 275 |
|
|
| 276 |
if (-not $dbdialect.ContainsKey($dbtype)) |
|
| 277 |
{
|
|
| 278 |
throw "Unsupported database type '$dbtype' for '$db'." |
|
| 279 |
} |
|
| 280 |
|
|
| 281 |
$dbhost = Get-SubVal $db "dbhost" "localhost" |
|
| 282 |
$dbport = Get-SubVal $db "dbport" "5432" |
|
| 283 |
$dbpath = Get-SubVal $db "dbpath" "../db" |
|
| 284 |
$pljava = if ($dbtype -eq "h2") { "TRUE" } else { "FALSE" }
|
|
| 285 |
|
|
| 286 |
$jdbc_url = if ($dbtype -eq "h2") |
|
| 287 |
{
|
|
| 288 |
"h2:$dbpath/$db;DB_CLOSE_DELAY=-1;MV_STORE=FALSE;RTRIM=TRUE" |
|
| 289 |
} |
|
| 290 |
else |
|
| 291 |
{
|
|
| 292 |
"postgresql://${dbhost}:${dbport}/$db"
|
|
| 293 |
} |
|
| 294 |
|
|
| 295 |
$dbfile = "directory_db.xml.$db" |
|
| 296 |
Expand-Template 'directory_db.xml.template' @{
|
|
| 297 |
dbhost = $dbhost |
|
| 298 |
dbport = $dbport |
|
| 299 |
dbname = $db |
|
| 300 |
dbuser = (Get-SubVal $db "dbuser" "fwd_user") |
|
| 301 |
dbuserpass = (Get-SubVal $db "dbuserpass" "user") |
|
| 302 |
dbadmin = (Get-SubVal $db "dbadmin" "fwd_admin") |
|
| 303 |
dbadminpass = (Get-SubVal $db "dbadminpass" "admin") |
|
| 304 |
dbdialect = $dbdialect[$dbtype] |
|
| 305 |
dbdriver = $dbdriver[$dbtype] |
|
| 306 |
max_c3p0_pool = (Get-SubVal $db "max_c3p0_pool" "20") |
|
| 307 |
dbpath = $dbpath |
|
| 308 |
jdbc_url = $jdbc_url |
|
| 309 |
pljava = $pljava |
|
| 310 |
collation = (Get-SubVal $db "collation" "en_US@iso88591_fwd_basic") |
|
| 311 |
} $dbfile |
|
| 312 |
|
|
| 313 |
& java -Xmx256m -classpath $p2j_jar com.goldencode.p2j.directory.DirectoryCopy ` |
|
| 314 |
copy $dbfile /server/standard/database/ directory_tmp.xml /server/standard/database/ |
|
| 315 |
if ($LASTEXITCODE -ne 0) |
|
| 316 |
{
|
|
| 317 |
throw "DirectoryCopy failed for $db with exit code $LASTEXITCODE." |
|
| 318 |
} |
|
| 319 |
|
|
| 320 |
Remove-Item -LiteralPath $dbfile -Force |
|
| 321 |
} |
|
| 322 |
|
|
| 323 |
Move-Item -LiteralPath 'directory_tmp.xml' -Destination $dirfile -Force |
|
| 324 |
Write-Host "Wrote $dirfile" |
|
| 325 |
|
|
| 326 |
exit 0 |
|
| new/deploy/server/server.cmd 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 1 | 1 |
:: Standard FWD server startup script - Wrapper to server.ps1 |
| 2 | 2 |
@echo off |
| 3 | 3 |
setlocal |
| 4 |
pwsh -NoProfile -ExecutionPolicy Bypass -File "%~dp0server.ps1" %* |
|
| 5 |
endlocal |
|
| 4 |
|
|
| 5 |
:: PowerShell Core when it is installed, otherwise the Windows PowerShell which is preinstalled with |
|
| 6 |
:: Windows. %%~$PATH:I expands to the full path of the file when it is found on the PATH, and to an |
|
| 7 |
:: empty string when it is not. |
|
| 8 |
set "psexe=" |
|
| 9 |
for %%I in (pwsh.exe) do if not "%%~$PATH:I" == "" set "psexe=%%~$PATH:I" |
|
| 10 |
if not defined psexe set "psexe=powershell.exe" |
|
| 11 |
|
|
| 12 |
"%psexe%" -NoProfile -ExecutionPolicy Bypass -File "%~dp0server.ps1" %* |
|
| 13 |
exit /b %ERRORLEVEL% |
|
| new/deploy/server/server.ps1 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 126 | 126 |
return |
| 127 | 127 |
} |
| 128 | 128 |
|
| 129 |
# Resolve the directory.xml path relative to the config's directory. |
|
| 129 |
# Resolve the directory.xml path relative to the config's directory. Split-Path returns an empty |
|
| 130 |
# string when the config was found as a bare name in the current directory, which is what happens |
|
| 131 |
# when the server is started from within its own directory; Join-Path rejects that. |
|
| 130 | 132 |
$dirXmlPath = $dirXmlName |
| 131 | 133 |
if (-not [System.IO.Path]::IsPathRooted($dirXmlPath)) {
|
| 132 |
$dirXmlPath = Join-Path (Split-Path $cfgPath -Parent) $dirXmlName |
|
| 134 |
$cfgDir = Split-Path $cfgPath -Parent |
|
| 135 |
if ([string]::IsNullOrWhiteSpace($cfgDir)) {
|
|
| 136 |
$cfgDir = $PWD.Path # Use current directory if no parent in path |
|
| 137 |
} |
|
| 138 |
$dirXmlPath = Join-Path $cfgDir $dirXmlName |
|
| 133 | 139 |
} |
| 134 | 140 |
|
| 135 | 141 |
# Use the same p2j.jar the server resolved (via Get-Classpath) instead of |
| ... | ... | |
| 321 | 327 |
'^--gc$' { $psOptions.EnableGC = $true }
|
| 322 | 328 |
'^--jmx_port=' { $psOptions.JmxPort = [int]($arg -split '=')[1] }
|
| 323 | 329 |
'^--clear_logs' {
|
| 324 |
$logDirs = $arg -match '=' ? ($arg -split '=')[1] : $default_log_dirs |
|
| 330 |
# an if expression, the ?: ternary operator needs PowerShell 7 |
|
| 331 |
$logDirs = if ($arg -match '=') { ($arg -split '=')[1] } else { $default_log_dirs }
|
|
| 325 | 332 |
Clear-Logs $logDirs |
| 326 | 333 |
} |
| 327 | 334 |
default {
|
| new/deploy/server/start_server.cmd 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 4 | 4 |
:: Determine script directory |
| 5 | 5 |
set scriptdir=%~dp0 |
| 6 | 6 |
|
| 7 |
:: PowerShell Core when it is installed, otherwise the Windows PowerShell which is preinstalled |
|
| 8 |
set "psexe=" |
|
| 9 |
for %%I in (pwsh.exe) do if not "%%~$PATH:I" == "" set "psexe=%%~$PATH:I" |
|
| 10 |
if not defined psexe set "psexe=powershell.exe" |
|
| 11 |
|
|
| 7 | 12 |
:: Pass all arguments to PowerShell script |
| 8 |
pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "%scriptdir%start_server.ps1" %* |
|
| 13 |
"%psexe%" -NoProfile -ExecutionPolicy Bypass -File "%scriptdir%start_server.ps1" %* |
|
| 14 |
exit /b %ERRORLEVEL% |
|
| new/deploy/server/stop_server.cmd 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 4 | 4 |
:: Determine script directory |
| 5 | 5 |
set scriptdir=%~dp0 |
| 6 | 6 |
|
| 7 |
:: PowerShell Core when it is installed, otherwise the Windows PowerShell which is preinstalled |
|
| 8 |
set "psexe=" |
|
| 9 |
for %%I in (pwsh.exe) do if not "%%~$PATH:I" == "" set "psexe=%%~$PATH:I" |
|
| 10 |
if not defined psexe set "psexe=powershell.exe" |
|
| 11 |
|
|
| 7 | 12 |
:: Pass all arguments to PowerShell script |
| 8 |
pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "%scriptdir%stop_server.ps1" %* |
|
| 13 |
"%psexe%" -NoProfile -ExecutionPolicy Bypass -File "%scriptdir%stop_server.ps1" %* |
|
| 14 |
exit /b %ERRORLEVEL% |
|
| new/hotel.input.windows 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 1 | 1 |
hotel |
| 2 |
|
|
| 3 |
|
|
| 2 |
hotel_gui |
|
| 3 |
*.[fhi] |
|
| 4 |
*.[pPwW] |
|
| 4 | 5 |
com.goldencode.hotel |
| 5 |
.;common\; |
|
| 6 |
.:common: |
|
| 7 |
.;common; |
|
| 6 | 8 |
ADM2.2 |
| 7 | 9 |
hotel |
| 10 |
hotel |
|
| 8 | 11 |
h2 |
| 12 |
localhost |
|
| 13 |
../db |
|
| 9 | 14 |
fwd_admin |
| 10 | 15 |
admin |
| 11 | 16 |
fwd_user |
| 12 | 17 |
user |
| 13 |
|
|
| 14 |
|
|
| 15 |
|
|
| 16 |
com.goldencode.hotel.Start |
|
| 18 |
en_US@iso88591_fwd_basic |
|
| 19 |
20 |
|
| 20 |
no |
|
| 21 |
mdy |
|
| 22 |
, |
|
| 23 |
. |
|
| 24 |
start.p |
|
| 25 |
localhost |
|
| 26 |
7443 |
|
| 27 |
directory.xml |
|
| 28 |
yes |
|
| new/install_spawner.cmd 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 4 | 4 |
:: Determine script directory |
| 5 | 5 |
set scriptdir=%~dp0 |
| 6 | 6 |
|
| 7 |
:: Pass all arguments to PowerShell script |
|
| 8 |
pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "%scriptdir%install_spawner.ps1" %* |
|
| 7 |
:: Pass all arguments to PowerShell script, run_powershell.cmd picks the PowerShell which is installed |
|
| 8 |
call "%scriptdir%run_powershell.cmd" "%scriptdir%install_spawner.ps1" %* |
|
| 9 |
exit /b %ERRORLEVEL% |
|
| new/install_spawner.ps1 2026-08-07 14:04:48 +0000 | ||
|---|---|---|
| 14 | 14 |
# Enable strict mode for error handling |
| 15 | 15 |
Set-StrictMode -Version Latest |
| 16 | 16 |
|
| 17 |
# Ensure the script is running with administrative privileges |
|
| 18 |
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) |
|
| 19 |
{
|
|
| 20 |
Write-Host "This script requires administrative privileges. Restarting with elevation..." |
|
| 21 |
Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`"" -Verb RunAs |
|
| 22 |
exit |
|
| 23 |
} |
|
| 24 |
|
|
| 25 | 17 |
# Important helper to be included for compatibility with bash sourcing of appname |
| 26 | 18 |
function Source-AppName |
| 27 | 19 |
{
|
| ... | ... | |
| 45 | 37 |
|
| 46 | 38 |
function Show-Usage {
|
| 47 | 39 |
$usage = @( |
| 48 |
"Usage: $script_name [-a] [-d] [-s<path to place spawner>] [-p<path to FWD>] [-f<path to slf4j-impl.jar>] [-n<path to native spawner>] [-c<path to srv-certs>] [-t<path to postbuild.sh tool>]", |
|
| 49 |
" [-n <native spawner>] [-c <srv-certs.store path>] [-t <postbuild.sh tool path>]", |
|
| 40 |
"Usage: $script_name [-a] [-d] [-s <path to place spawner>] [-p <path to FWD>] [-f <path to slf4j-impl.jar>] [-n <path to native spawner>] [-c <path to srv-certs>] [-t <path to postbuild.ps1 tool>]", |
|
| 50 | 41 |
"a = Copy only $appname libraries (prevents co-mingling of application and FWD libraries).", |
| 51 | 42 |
"d = Dry run. Just show commands.", |
| 52 | 43 |
"s = Destination directory to place spawner.exe (def=$fspawn)", |
| 53 | 44 |
"p = Location of FWD libraries p2j.jar and fwd-slf4j.jar (if no -f specified). `"FWD_LIB`" will be used as a fallback if default is not valid. (def=$p2j_lib)", |
| 54 | 45 |
"f = Location of file to be placed in slf4j-impl.jar destination (def=fwd-slf4j.jar in -p location or FWD_LIB)", |
| 55 |
"n = Location of built native spawner (def=$spawn_prog), unless -p specified, which will change the default location)",
|
|
| 46 |
"n = Location of built native spawner (def=$spawn_prog, unless -p specified, which will change the default location)", |
|
| 56 | 47 |
"c = Location of srv-certs.store file (def=$srv_certs)", |
| 57 |
"t = Location of postbuild.sh tool (def=$postbuild), unless -p specified, which will change the default location)"
|
|
| 48 |
"t = Location of postbuild.ps1 tool (def=$postbuild, unless -p specified, which will change the default location)"
|
|
| 58 | 49 |
) |
| 59 | 50 |
$usage | ForEach-Object { Write-Host $_ }
|
| 60 | 51 |
} |
| 61 | 52 |
|
| 53 |
# Quotes a value for the PowerShell command line assembled for the privileged step below. A single |
|
| 54 |
# quote is its own escape, so doubling it is all that is needed. |
|
| 55 |
function ConvertTo-PSLiteral |
|
| 56 |
{
|
|
| 57 |
param ( |
|
| 58 |
[string]$Value |
|
| 59 |
) |
|
| 60 |
|
|
| 61 |
return "'" + ($Value -replace "'", "''") + "'" |
|
| 62 |
} |
|
| 63 |
|
|
| 64 |
<# |
|
| 65 |
The counterpart of the "$mysudo" of install_spawner.sh. |
|
| 66 |
|
|
| 67 |
Windows has no sudo, a single command cannot be elevated in place, so the commands which need the |
|
| 68 |
rights are grouped into one child process and that process is started elevated. Everything else |
|
| 69 |
in this script stays unelevated, exactly as on Linux: elevating the whole script would also run |
|
| 70 |
the jar copies below as an administrator and leave a deployment the developer cannot overwrite on |
|
| 71 |
the next build. |
|
| 72 |
|
|
| 73 |
The child is a separate process even when no elevation is needed, because an "exit" of a script |
|
| 74 |
called in the current session would end this one as well and skip the library copying below. |
|
| 75 |
|
|
| 76 |
An elevated process cannot share this console: UAC always gives it a window of its own, and |
|
| 77 |
-Verb RunAs cannot be combined with -RedirectStandardOutput. Its output is therefore written to a |
|
| 78 |
file and replayed here, otherwise the window closes as soon as the work is done and nothing can be |
|
| 79 |
read. The command is handed over with -EncodedCommand, which takes base64 and so needs no |
|
| 80 |
quoting of its own. |
|
| 81 |
#> |
|
| 82 |
function Invoke-Privileged |
|
| 83 |
{
|
|
| 84 |
param ( |
|
| 85 |
[string]$Command, |
|
| 86 |
[switch]$Elevate |
|
| 87 |
) |
|
| 88 |
|
|
| 89 |
# the interpreter running this script, not a hardcoded "pwsh": PowerShell 7 is not necessarily |
|
| 90 |
# installed, install_spawner.cmd launches the Windows PowerShell 5.1 instead |
|
| 91 |
$psHost = (Get-Process -Id $PID).Path |
|
| 92 |
|
|
| 93 |
if (-not $Elevate) |
|
| 94 |
{
|
|
| 95 |
& $psHost -NoProfile -ExecutionPolicy Bypass -Command "& { $Command }; exit `$LASTEXITCODE"
|
|
| 96 |
return $LASTEXITCODE |
|
| 97 |
} |
|
| 98 |
|
|
| 99 |
Write-Host "Elevation is required for $fspawn, confirm the prompt to continue..." |
|
| 100 |
|
|
| 101 |
$log = Join-Path ([System.IO.Path]::GetTempPath()) "install_spawner_$PID.log" |
|
| 102 |
|
|
| 103 |
# the braces matter, a redirection binds to the last statement only and the command is a list |
|
| 104 |
$wrapped = "& { $Command } *> $(ConvertTo-PSLiteral $log); exit `$LASTEXITCODE"
|
|
| 105 |
$encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($wrapped)) |
|
| 106 |
|
|
| 107 |
try |
|
| 108 |
{
|
|
| 109 |
$proc = Start-Process -FilePath $psHost ` |
|
| 110 |
-ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass',
|
|
| 111 |
'-EncodedCommand', $encoded) ` |
|
| 112 |
-Verb RunAs -WorkingDirectory $cwd -Wait -PassThru |
|
| 113 |
} |
|
| 114 |
catch |
|
| 115 |
{
|
|
| 116 |
# declining the UAC prompt lands here, as does a machine with no interactive desktop |
|
| 117 |
Write-Host "ERROR: the elevated step could not be started: $($_.Exception.Message)" |
|
| 118 |
return 1 |
|
| 119 |
} |
|
| 120 |
|
|
| 121 |
if (Test-Path -LiteralPath $log) |
|
| 122 |
{
|
|
| 123 |
Get-Content -LiteralPath $log |
|
| 124 |
Remove-Item -LiteralPath $log -Force -ErrorAction SilentlyContinue |
|
| 125 |
} |
|
| 126 |
|
|
| 127 |
return $proc.ExitCode |
|
| 128 |
} |
|
| 129 |
|
|
| 62 | 130 |
# Defaults |
| 63 | 131 |
$script_name = $MyInvocation.MyCommand.Name |
| 64 | 132 |
$wholePath = $MyInvocation.MyCommand.Path |
| ... | ... | |
| 74 | 142 |
exit 1 |
| 75 | 143 |
} |
| 76 | 144 |
|
| 77 |
# Default paths |
|
| 78 |
$pwd = Get-Location |
|
| 79 |
$fspawn = "/opt/spawner" |
|
| 80 |
$p2j_lib = "$pwd/p2j/build/lib" |
|
| 81 |
$deploy_home = "$pwd/deploy" |
|
| 145 |
# Default paths. Note that $pwd is not used to hold the current directory, it is the name of an |
|
| 146 |
# automatic PowerShell variable. |
|
| 147 |
$cwd = (Get-Location).Path |
|
| 148 |
# The Windows counterparts of the /opt/spawner and /opt/fwd-deploy/spawner of install_spawner.sh. |
|
| 149 |
$fspawn = Join-Path $env:ProgramData 'FWD\spawner' |
|
| 150 |
$fwd_deploy = Join-Path $env:ProgramData 'FWD\fwd-deploy\spawner' |
|
| 151 |
$p2j_lib = "$cwd/p2j/build/lib" |
|
| 152 |
$deploy_home = "$cwd/deploy" |
|
| 82 | 153 |
$srv_certs = "$deploy_home/server/srv-certs.store" |
| 83 |
$build_home = "$pwd/build"
|
|
| 84 |
$p2j_root = "$pwd/p2j"
|
|
| 154 |
$build_home = "$cwd/build"
|
|
| 155 |
$p2j_root = "$cwd/p2j"
|
|
| 85 | 156 |
$postbuild = "$p2j_root/src/native/postbuild.ps1" |
| 86 | 157 |
$spawn_prog = "$p2j_root/build/native/spawn.exe" |
| 87 | 158 |
$p2j_passed = $false |
| ... | ... | |
| 114 | 185 |
} |
| 115 | 186 |
|
| 116 | 187 |
# Set defaults when no options passed and spawn/postbuild.ps1 are not found (or bail) |
| 117 |
if (-not $p2j_passed -and -not $spawn_passed -and !(Test-Path $spawn_prog) -and (Test-Path "/opt/fwd-deploy/spawner/spawn")) {
|
|
| 118 |
$spawn_prog = "/opt/fwd-deploy/spawner/spawn.exe"
|
|
| 188 |
if (-not $p2j_passed -and -not $spawn_passed -and !(Test-Path $spawn_prog) -and (Test-Path "$fwd_deploy/spawn.exe")) {
|
|
| 189 |
$spawn_prog = "$fwd_deploy/spawn.exe"
|
|
| 119 | 190 |
} |
| 120 | 191 |
if (!(Test-Path $spawn_prog)) {
|
| 121 | 192 |
Write-Error "Error: $spawn_prog not found. Exiting." |
| 122 | 193 |
exit 1 |
| 123 | 194 |
} |
| 124 |
if (-not $p2j_passed -and -not $postbuild_passed -and !(Test-Path $postbuild) -and (Test-Path "/opt/fwd-deploy/spawner/postbuild.sh")) {
|
|
| 125 |
$postbuild = "/opt/fwd-deploy/spawner/postbuild.ps1"
|
|
| 195 |
if (-not $p2j_passed -and -not $postbuild_passed -and !(Test-Path $postbuild) -and (Test-Path "$fwd_deploy/postbuild.ps1")) {
|
|
| 196 |
$postbuild = "$fwd_deploy/postbuild.ps1"
|
|
| 126 | 197 |
} |
| 127 | 198 |
if (!(Test-Path $postbuild)) {
|
| 128 | 199 |
Write-Error "Error: $postbuild not found. Exiting." |
| ... | ... | |
| 140 | 211 |
$spawn_prog = "$p2j_root/build/native/spawn.exe" |
| 141 | 212 |
} |
| 142 | 213 |
if (-not $postbuild_passed) {
|
| 143 |
$postbuild = "$p2j_root/src/native/postbuild.sh"
|
|
| 214 |
$postbuild = "$p2j_root/src/native/postbuild.ps1"
|
|
| 144 | 215 |
} |
| 145 | 216 |
} |
| 146 | 217 |
} |
| ... | ... | |
| 150 | 221 |
$slf4j_impl = "$p2j_lib/fwd-slf4j.jar" |
| 151 | 222 |
} |
| 152 | 223 |
|
| 153 |
# Run postbuild |
|
| 154 |
$cmdString = "& pwsh -File $postbuild -SpawnDir $fspawn -SpawnProg $spawn_prog -CertFile $srv_certs -FwdLib $p2j_jar" |
|
| 155 |
if ($d) {
|
|
| 156 |
Write-Host $cmdString |
|
| 224 |
# Elevation is needed only when the destination is outside the user's own profile and this session is |
|
| 225 |
# not elevated already, the same test as the |
|
| 226 |
# [[ "$fspawn"* != "$HOME"* ]] && [[ $(whoami) != "root" ]] |
|
| 227 |
# of install_spawner.sh. Installing under -s $env:USERPROFILE\... raises no prompt at all. |
|
| 228 |
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent() |
|
| 229 |
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) |
|
| 230 |
$underHome = $fspawn.StartsWith($env:USERPROFILE, [System.StringComparison]::OrdinalIgnoreCase) |
|
| 231 |
$needElevation = -not $isAdmin -and -not $underHome |
|
| 232 |
|
|
| 233 |
# The privileged step: the commands install_spawner.sh runs under sudo, grouped so that at most one |
|
| 234 |
# UAC prompt is raised. The order differs from install_spawner.sh in one respect, the directory ACL |
|
| 235 |
# is applied before postbuild instead of after it: postbuild.ps1 hardens the folder itself and |
|
| 236 |
# honours its own -StrictAcl, so it has to have the last word. Against an older postbuild.ps1 which |
|
| 237 |
# leaves the folder alone, the grant below is still what gives the ordinary users their access. |
|
| 238 |
$commands = @() |
|
| 239 |
|
|
| 240 |
# Create the destination for the spawner, if not already there. postbuild bails out on a missing one, |
|
| 241 |
# creating it is the job of this script, as in install_spawner.sh. |
|
| 242 |
if (!(Test-Path $fspawn)) {
|
|
| 243 |
$commands += "New-Item -Path $(ConvertTo-PSLiteral $fspawn) -ItemType Directory -Force | Out-Null" |
|
| 244 |
} |
|
| 245 |
|
|
| 246 |
# The equivalent of the "chmod gou+rx $fspawn" of install_spawner.sh, S-1-5-32-545 is the well known |
|
| 247 |
# SID of the Users group (the group names are localized, the SIDs are not). |
|
| 248 |
$commands += "& icacls $(ConvertTo-PSLiteral $fspawn) /grant '*S-1-5-32-545:(RX)' | Out-Null" |
|
| 249 |
|
|
| 250 |
# Position the spawner files |
|
| 251 |
$commands += ("& $(ConvertTo-PSLiteral $postbuild)" +
|
|
| 252 |
" -SpawnDir $(ConvertTo-PSLiteral $fspawn)" + |
|
| 253 |
" -SpawnProg $(ConvertTo-PSLiteral $spawn_prog)" + |
|
| 254 |
" -CertFile $(ConvertTo-PSLiteral $srv_certs)" + |
|
| 255 |
" -FwdLib $(ConvertTo-PSLiteral $p2j_jar)" + |
|
| 256 |
" -Slf4jImpl $(ConvertTo-PSLiteral $slf4j_impl)") |
|
| 257 |
|
|
| 258 |
$privileged = $commands -join '; ' |
|
| 259 |
|
|
| 260 |
if ($d) {
|
|
| 261 |
Write-Host $privileged |
|
| 157 | 262 |
} else {
|
| 158 |
& pwsh -File $postbuild -SpawnDir $fspawn -SpawnProg $spawn_prog -CertFile $srv_certs -FwdLib $p2j_jar |
|
| 263 |
$rc = Invoke-Privileged -Command $privileged -Elevate:$needElevation |
|
| 264 |
if ($rc -ne 0) {
|
|
| 265 |
Write-Host "WARNING! The spawner installation failed with exit code $rc." |
|
| 266 |
} |
|
| 159 | 267 |
} |
| 160 | 268 |
|
| 161 | 269 |
# Determine the configured JDK |
| 162 | 270 |
#jver is 18 for java 1.8, 15 for java 1.5, 110 for java 11, 170 for java 17 etc. |
| 163 |
$jver = & java -version 2>&1 | Select-String 'version' | ForEach-Object {
|
|
| 271 |
# java writes its version banner to stderr, which Windows PowerShell reports as an error record of the |
|
| 272 |
# native command; keep the preference relaxed for the call and stringify what the merged streams give. |
|
| 273 |
$previousPreference = $ErrorActionPreference |
|
| 274 |
$ErrorActionPreference = 'Continue' |
|
| 275 |
try {
|
|
| 276 |
$javaVersionLines = & java -version 2>&1 | ForEach-Object { "$_" }
|
|
| 277 |
} |
|
| 278 |
finally {
|
|
| 279 |
$ErrorActionPreference = $previousPreference |
|
| 280 |
} |
|
| 281 |
$jver = $javaVersionLines | Select-String 'version' | ForEach-Object {
|
|
| 164 | 282 |
if ($_ -match '"(\d+\.\d+|\d+)"') {
|
| 165 | 283 |
$v = $matches[1] |
| 166 | 284 |
$parts = $v -split '\.' |
| 167 |
if ($parts.Length -eq 1) { return "$parts[0]0" }
|
|
| 285 |
if ($parts.Length -eq 1) { return "$($parts[0])0" }
|
|
| 168 | 286 |
return "$($parts[0])$($parts[1])" |
| 169 | 287 |
} |
| 170 | 288 |
} |
| ... | ... | |
| 172 | 290 |
|
| 173 | 291 |
# Copy the application jar and the collation jar specifically to the deployment location |
| 174 | 292 |
if (-not (Test-Path $spidir)) {
|
| 175 |
if ($d) { Write-Host "New-Item -Path $spidir -ItemType Directory" } else { New-Item -Path $spidir -ItemType Directory | Out-Null }
|
|
| 293 |
if ($d) { Write-Host "New-Item -Path $spidir -ItemType Directory -Force" } else { New-Item -Path $spidir -ItemType Directory -Force | Out-Null }
|
|
| 176 | 294 |
} |
| 177 | 295 |
$appJar = "$build_home/lib/$appname.jar" |
| 178 | 296 |
$fwdSpiJar = "$p2j_lib/fwdspi.jar" |
| 179 | 297 |
if ($d) {
|
| 180 | 298 |
Write-Host "Copy-Item $appJar $deploy_home/lib -Force" |
| 181 |
Write-Host "$fwdSpiJar $spidir -Force" |
|
| 299 |
Write-Host "Copy-Item $fwdSpiJar $spidir -Force"
|
|
| 182 | 300 |
} else {
|
| 183 | 301 |
Copy-Item $appJar "$deploy_home/lib" -Force |
| 184 | 302 |
Copy-Item $fwdSpiJar $spidir -Force |
| 185 | 303 |
} |
| 186 | 304 |
# Copy the rest of the library files (except aspectjtools.jar and fwdspi.jar) to the deployment location, unless -a is included. |
| 187 | 305 |
if (-not $a) {
|
| 188 |
Get-ChildItem $p2j_lib -Include *.jar,*.zip -Recurse | |
|
| 306 |
Get-ChildItem $p2j_lib -Include *.jar,*.zip -Recurse -File |
|
|
| 189 | 307 |
Where-Object { $_.Name -notmatch 'aspectjtools\.jar|fwdspi\.jar' } |
|
| 190 | 308 |
ForEach-Object {
|
| 191 | 309 |
if ($d) {
|
| 192 |
Write-Host "Copy-Item $_.FullName $deploy_home/lib -Force"
|
|
| 310 |
Write-Host "Copy-Item $($_.FullName) $deploy_home/lib -Force"
|
|
| 193 | 311 |
} else {
|
| 194 | 312 |
Copy-Item $_.FullName "$deploy_home/lib" -Force |
| 195 | 313 |
} |
| new/json_template.cmd 2026-08-07 11:54:43 +0000 | ||
|---|---|---|
| 1 |
@echo off |
|
| 2 |
:: |
|
| 3 |
:: Wrapper for json_template.ps1, the counterpart of json_template.sh. |
|
| 4 |
:: |
|
| 5 |
:: Run this from the project root, the script resolves its templates relative to the current |
|
| 6 |
:: directory exactly as the shell version does. |
|
| 7 |
:: |
|
| 8 |
set scriptdir=%~dp0 |
|
| 9 |
|
|
| 10 |
call "%scriptdir%run_powershell.cmd" "%scriptdir%json_template.ps1" %* |
|
| 11 |
exit /b %ERRORLEVEL% |
|
| new/json_template.ps1 2026-08-07 12:11:51 +0000 | ||
|---|---|---|
| 1 |
# |
|
| 2 |
# The Windows counterpart of json_template.sh, kept in sync with it: takes input from |
|
| 3 |
# prepare_template.json and performs configuration of build.properties, zfile_set.txt, p2j.cfg.xml, |
|
| 4 |
# deploy/server/server.xml and the directory.xml file (which can be located anywhere, as it is |
|
| 5 |
# specified in the json file). |
|
| 6 |
# |
|
| 7 |
# Substitution is done with a literal String.Replace and not with the -replace operator: -replace is |
|
| 8 |
# a regular expression on both sides, so a value holding a $ or a \ would be mangled - a database |
|
| 9 |
# password is the obvious way to hit that. |
|
| 10 |
# |
|
| 11 |
param ( |
|
| 12 |
[switch]$a, |
|
| 13 |
[switch]$d, |
|
| 14 |
[switch]$o, |
|
| 15 |
[switch]$n, |
|
| 16 |
[string]$f |
|
| 17 |
) |
|
| 18 |
|
|
| 19 |
Set-PSDebug -Trace 0 |
|
| 20 |
Set-StrictMode -Version Latest |
|
| 21 |
$ErrorActionPreference = 'Stop' |
|
| 22 |
|
|
| 23 |
function Show-Usage |
|
| 24 |
{
|
|
| 25 |
Write-Host "Usage: json_template.ps1 [-a] [-d] [-o] [-f <json_file>]" |
|
| 26 |
Write-Host "Takes input from prepare_template.json and performs configuration of build.properties," |
|
| 27 |
Write-Host "p2j.cfg.xml, deploy/server/server.xml, and the directory.xml file." |
|
| 28 |
Write-Host "Where:" |
|
| 29 |
Write-Host " a = Only performing Analytics" |
|
| 30 |
Write-Host " d = Generate deploy/server/prepare_dir.json output file to be used by prepare_dir.ps1" |
|
| 31 |
Write-Host " o = Overwrite the specified directory.xml, if it already exists. Otherwise, leave it alone" |
|
| 32 |
Write-Host " f = Use <json_file> instead of prepare_template.json as input." |
|
| 33 |
} |
|
| 34 |
|
|
| 35 |
$utf8NoBom = New-Object System.Text.UTF8Encoding($false) |
|
| 36 |
|
|
| 37 |
# Property lookup which tolerates a missing key under Set-StrictMode; $cfg.$Key would throw. |
|
| 38 |
function Get-Node |
|
| 39 |
{
|
|
| 40 |
param ( |
|
| 41 |
$Object, |
|
| 42 |
[string]$Key |
|
| 43 |
) |
|
| 44 |
|
|
| 45 |
if ($null -eq $Object) { return $null }
|
|
| 46 |
|
|
| 47 |
$prop = $Object.PSObject.Properties[$Key] |
|
| 48 |
if ($null -eq $prop) { return $null }
|
|
| 49 |
|
|
| 50 |
return $prop.Value |
|
| 51 |
} |
|
| 52 |
|
|
| 53 |
function Get-Val |
|
| 54 |
{
|
|
| 55 |
param ( |
|
| 56 |
[string]$Key, |
|
| 57 |
[string]$Default = "" |
|
| 58 |
) |
|
| 59 |
|
|
| 60 |
$val = Get-Node $script:cfg $Key |
|
| 61 |
if ($null -eq $val -or "$val" -eq "") { return $Default }
|
|
| 62 |
|
|
| 63 |
return "$val" |
|
| 64 |
} |
|
| 65 |
|
|
| 66 |
# The per-database values live in a sub-object named after the database, so the lookup is two |
|
| 67 |
# levels. Note prepare_dir.ps1 used to pass "<db>.<key>" as a single property name, which never |
|
| 68 |
# resolved and silently handed back every default. |
|
| 69 |
function Get-SubVal |
|
| 70 |
{
|
|
| 71 |
param ( |
|
| 72 |
[string]$SubName, |
|
| 73 |
[string]$Key, |
|
| 74 |
[string]$Default = "" |
|
| 75 |
) |
|
| 76 |
|
|
| 77 |
$node = Get-Node $script:cfg $SubName |
|
| 78 |
$val = Get-Node $node $Key |
|
| 79 |
if ($null -eq $val -or "$val" -eq "") { return $Default }
|
|
| 80 |
|
|
| 81 |
return "$val" |
|
| 82 |
} |
|
| 83 |
|
|
| 84 |
# Replaces every {key} of a template with its value and writes the result.
|
|
| 85 |
function Expand-Template |
|
| 86 |
{
|
|
| 87 |
param ( |
|
| 88 |
[string]$Template, |
|
| 89 |
[hashtable]$Values, |
|
| 90 |
[string]$Destination |
|
| 91 |
) |
|
| 92 |
|
|
| 93 |
if (!(Test-Path -LiteralPath $Template -PathType Leaf)) |
|
| 94 |
{
|
|
| 95 |
throw "Could not create $Destination, the template $Template was not found." |
|
| 96 |
} |
|
| 97 |
|
|
| 98 |
$content = [System.IO.File]::ReadAllText($Template) |
|
| 99 |
|
|
| 100 |
foreach ($key in $Values.Keys) |
|
| 101 |
{
|
|
| 102 |
$content = $content.Replace("{$key}", [string]$Values[$key])
|
|
| 103 |
} |
|
| 104 |
|
|
| 105 |
[System.IO.File]::WriteAllText($Destination, $content, $utf8NoBom) |
|
| 106 |
} |
|
| 107 |
|
|
| 108 |
# Splits a PROPATH answer. Both spellings are accepted so the same answer file works either way: |
|
| 109 |
# a ';' separated list is split on ';' (which also keeps a "C:\..." drive letter intact), anything |
|
| 110 |
# else is split on ':'. |
|
| 111 |
function Split-PropathValue |
|
| 112 |
{
|
|
| 113 |
param ( |
|
| 114 |
[string]$Value |
|
| 115 |
) |
|
| 116 |
|
|
| 117 |
$sep = if ($Value.Contains(';')) { ';' } else { ':' }
|
|
| 118 |
|
|
| 119 |
return @($Value -split [regex]::Escape($sep) | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" })
|
|
| 120 |
} |
|
| 121 |
|
|
| 122 |
if ($args -contains "-?" -or $args -contains "/?" -or $args -contains "-h") |
|
| 123 |
{
|
|
| 124 |
Show-Usage |
|
| 125 |
exit 1 |
|
| 126 |
} |
|
| 127 |
|
|
| 128 |
$analytics = $a.IsPresent |
|
| 129 |
$overwrite = $o.IsPresent |
|
| 130 |
$json_file = if ($f) { $f } else { "prepare_template.json" }
|
|
| 131 |
$prepare_dir = if ($d) { "deploy/server/prepare_dir.json" } else { "" }
|
|
| 132 |
|
|
| 133 |
if (!(Test-Path -LiteralPath $json_file -PathType Leaf)) |
|
| 134 |
{
|
|
| 135 |
Write-Error "Input file not found: $json_file" |
|
| 136 |
Show-Usage |
|
| 137 |
exit 1 |
|
| 138 |
} |
|
| 139 |
|
|
| 140 |
$root = (Get-Location).Path |
|
| 141 |
|
|
| 142 |
# System.IO and every native command resolve a relative path against the PROCESS working directory, |
|
| 143 |
# which PowerShell's own location does not track: Push-Location moves the latter and leaves the |
|
| 144 |
# former where the script started. The two are kept in step here and around the Push-Location |
|
| 145 |
# further down, otherwise the templates under deploy/server are looked for in the project root and |
|
| 146 |
# the files written there land in the root as well. |
|
| 147 |
[Environment]::CurrentDirectory = $root |
|
| 148 |
|
|
| 149 |
$cfg = [System.IO.File]::ReadAllText($json_file) | ConvertFrom-Json |
|
| 150 |
|
|
| 151 |
# --------------------------------------------------------------------------------------------------- |
|
| 152 |
# Values taken straight from the json |
|
| 153 |
# --------------------------------------------------------------------------------------------------- |
|
| 154 |
$appname = Get-Val "appname" |
|
| 155 |
$projname = Get-Val "projname" $appname |
|
| 156 |
$include_spec = Get-Val "include_spec" "*.[fhi]" |
|
| 157 |
$program_spec = Get-Val "program_spec" "*.[pPwW]" |
|
| 158 |
$pkgroot = if ($analytics) { "com.goldencode.$appname" } else { Get-Val "pkgroot" "com.goldencode.$appname" }
|
|
| 159 |
$propath_bld = Get-Val "propath_bld" "." |
|
| 160 |
$propath = Get-Val "propath" "." |
|
| 161 |
$admversion = Get-Val "admversion" "ADM2.2" |
|
| 162 |
$dbnames = Get-Val "dbnames" |
|
| 163 |
$embedded_host = Get-Val "embedded_host" "localhost" |
|
| 164 |
$admin_port = Get-Val "admin_port" "7443" |
|
| 165 |
|
|
| 166 |
if ($analytics) |
|
| 167 |
{
|
|
| 168 |
$win_proj = "no" |
|
| 169 |
$dateFormat = "mdy" |
|
| 170 |
$numberGroupSep = "," |
|
| 171 |
$numberDecimalSep = "." |
|