Skip to content

Commit

Permalink
fix windows batch argument probrem.
Browse files Browse the repository at this point in the history
the `shift` command of cmd.exe is not shift `%*`.
and use delayed-expansion. immediate expansion cause many troubles of special-characters in arguments.
  • Loading branch information
nazoking authored and muuki88 committed Nov 26, 2014
1 parent 7f5c66b commit 6a7a131
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 60 deletions.
Expand Up @@ -8,14 +8,15 @@
@setlocal enabledelayedexpansion

@echo off

if "%@@APP_ENV_NAME@@_HOME%"=="" set "@@APP_ENV_NAME@@_HOME=%~dp0\\.."
set ERROR_CODE=0

set "APP_LIB_DIR=%@@APP_ENV_NAME@@_HOME%\lib\"

rem Detect if we were double clicked, although theoretically A user could
rem manually run cmd /c
for %%x in (%cmdcmdline%) do if %%~x==/c set DOUBLECLICKED=1
for %%x in (!cmdcmdline!) do if %%~x==/c set DOUBLECLICKED=1

rem FIRST we load the config file of extra options.
set "CFG_FILE=%@@APP_ENV_NAME@@_HOME%\@@APP_ENV_NAME@@_config.txt"
Expand Down Expand Up @@ -72,86 +73,64 @@ if "%JAVAOK%"=="false" (

rem We use the value of the JAVA_OPTS environment variable if defined, rather than the config.
set _JAVA_OPTS=%JAVA_OPTS%
if "%_JAVA_OPTS%"=="" set _JAVA_OPTS=%CFG_OPTS%
if "!_JAVA_OPTS!"=="" set _JAVA_OPTS=!CFG_OPTS!

rem We keep in _JAVA_PARAMS all -J-prefixed and -D-prefixed arguments
rem "-J" is stripped, "-D" is left as is, and everything is appended to JAVA_OPTS
set _JAVA_PARAMS=
set _APP_ARGS=

:param_beforeloop
if [%1]==[] goto param_afterloop
set _TEST_PARAM=%~1
:param_loop
call set _PARAM1=%%1
set "_TEST_PARAM=%~1"

rem ignore arguments that do not start with '-'
if not "%_TEST_PARAM:~0,1%"=="-" (
shift
goto param_beforeloop
)
if ["!_PARAM1!"]==[""] goto param_afterloop

set _TEST_PARAM=%~1
if "%_TEST_PARAM:~0,2%"=="-J" (
rem strip -J prefix
set _TEST_PARAM=%_TEST_PARAM:~2%
)

if "%_TEST_PARAM:~0,2%"=="-D" (
rem test if this was double-quoted property "-Dprop=42"
for /F "delims== tokens=1-2" %%G in ("%_TEST_PARAM%") DO (
if not "%%G" == "%_TEST_PARAM%" (
rem double quoted: "-Dprop=42" -> -Dprop="42"
set _JAVA_PARAMS=%%G="%%H"
) else if [%2] neq [] (
rem it was a normal property: -Dprop=42 or -Drop="42"
set _JAVA_PARAMS=%_TEST_PARAM%=%2
shift
)
)
rem ignore arguments that do not start with '-'
if "%_TEST_PARAM:~0,1%"=="-" goto param_java_check
if ["!_APP_ARGS!"]==[""] (
set _APP_ARGS=!_PARAM1!
) else (
rem a JVM property, we just append it
set _JAVA_PARAMS=%_TEST_PARAM%
set _APP_ARGS=!_APP_ARGS! !_PARAM1!
)

:param_loop
shift
goto param_loop

if [%1]==[] goto param_afterloop
set _TEST_PARAM=%~1

rem ignore arguments that do not start with '-'
if not "%_TEST_PARAM:~0,1%"=="-" goto param_loop

set _TEST_PARAM=%~1
if "%_TEST_PARAM:~0,2%"=="-J" (
:param_java_check
if "!_TEST_PARAM:~0,2!"=="-J" (
rem strip -J prefix
set _TEST_PARAM=%_TEST_PARAM:~2%
set _JAVA_PARAMS=!_JAVA_PARAMS! !_TEST_PARAM:~2!
shift
goto param_loop
)

if "%_TEST_PARAM:~0,2%"=="-D" (
if "!_TEST_PARAM:~0,2!"=="-D" (
rem test if this was double-quoted property "-Dprop=42"
for /F "delims== tokens=1-2" %%G in ("%_TEST_PARAM%") DO (
if not "%%G" == "%_TEST_PARAM%" (
rem double quoted: "-Dprop=42" -> -Dprop="42"
set _JAVA_PARAMS=%_JAVA_PARAMS% %%G="%%H"
for /F "delims== tokens=1,*" %%G in ("!_TEST_PARAM!") DO (
if not ["%%H"] == [""] (
set _JAVA_PARAMS=!_JAVA_PARAMS! !_PARAM1!
) else if [%2] neq [] (
rem it was a normal property: -Dprop=42 or -Drop="42"
set _JAVA_PARAMS=%_JAVA_PARAMS% %_TEST_PARAM%=%2
call set _PARAM1=%%1=%%2
set _JAVA_PARAMS=!_JAVA_PARAMS! !_PARAM1!
shift
)
)
) else (
rem a JVM property, we just append it
set _JAVA_PARAMS=%_JAVA_PARAMS% %_TEST_PARAM%
set _JAVA_PARAMS=!_JAVA_PARAMS! !_PARAM1!
)
shift
goto param_loop
:param_afterloop

set _JAVA_OPTS=%_JAVA_OPTS% %_JAVA_PARAMS%
set _JAVA_OPTS=!_JAVA_OPTS! !_JAVA_PARAMS!
:run

@@APP_DEFINES@@

rem Call the application and pass all arguments unchanged.
"%_JAVACMD%" %_JAVA_OPTS% %@@APP_ENV_NAME@@_OPTS% -cp "%APP_CLASSPATH%" %APP_MAIN_CLASS% %*
"%_JAVACMD%" !_JAVA_OPTS! !@@APP_ENV_NAME@@_OPTS! -cp "%APP_CLASSPATH%" %APP_MAIN_CLASS% !_APP_ARGS!
if ERRORLEVEL 1 goto error
goto end

Expand Down
73 changes: 64 additions & 9 deletions src/sbt-test/windows/java-app-archetype/build.sbt
@@ -1,4 +1,4 @@
import NativePackagerKeys._
//import NativePackagerKeys._

packageArchetype.java_application

Expand All @@ -16,16 +16,71 @@ wixProductId := "ce07be71-510d-414a-92d4-dff47631848a"

wixProductUpgradeId := "4552fb0e-e257-4dbd-9ecb-dba9dbacf424"

// debug out
val debugOutFile = file(".") / "debug_out.txt"

batScriptExtraDefines ++= Seq("call :print_args %%* > "+ debugOutFile.getAbsolutePath

batScriptExtraDefines += "goto print_args_end"

batScriptExtraDefines += ":print_args"

batScriptExtraDefines += "echo cmdcmdline=!cmdcmdline!"

batScriptExtraDefines += "echo *=%*"

batScriptExtraDefines += 1.to(9).map(i => "echo %%"+i+"=%"+i).mkString("\n")

batScriptExtraDefines += "echo _JAVA_OPTS=!_JAVA_OPTS!"

batScriptExtraDefines += "echo _APP_ARGS=!_APP_ARGS!"

batScriptExtraDefines += "exit /B"

batScriptExtraDefines += ":print_args_end"


TaskKey[Unit]("check-script") <<= (stagingDirectory in Universal, name, streams) map { (dir, name, streams) =>
import scala.sys.process._
val fails = new StringBuilder()
val script = dir / "bin" / (name+".bat")
val cmd = Seq("cmd", "/c", script.getAbsolutePath)
val result =
Process(cmd) ! streams.log match {
case 0 => ()
case n => sys.error("Failed to run script: " + script.getAbsolutePath + " error code: " + n)
def crlf2cr(txt:String) = txt.trim.replaceAll("\\\r\\\n", "\n")
def checkOutputEnv(env:Map[String,String], expected:String, args:String*) = {
val pr = new StringBuilder()
val logger = ProcessLogger((o: String) => pr.append(o+"\n"),(e: String) => pr.append("error < " + e+"\n"))
val cmd = Seq("cmd", "/c", script.getAbsolutePath) ++ args
val result = Process(cmd, None, env.toSeq:_*) ! logger
if ( result != 0 ) {
pr.append("error code: " + result+"\n")
}
val output = crlf2cr(pr.toString)
if(output != expected.trim){
fails.append("\n---------------------------------\n")
fails.append("Failed to correctly run the main script!.\n")
fails.append("\""+cmd.mkString("\" \"")+"\"\n")
if(debugOutFile.exists){
fails.append(crlf2cr(scala.io.Source.fromFile(debugOutFile).mkString))
}
fails.append("\n--expected----------------------------\n")
fails.append(expected.trim+"\n")
fails.append("\n--found-------------------------------\n")
fails.append(crlf2cr(pr.toString)+"\n")
}
if(debugOutFile.exists){
debugOutFile.delete()
}
val output = Process(cmd).!!
val expected = "SUCCESS!"
assert(output contains expected, "Failed to correctly run the main script!. Found ["+output+"] wanted ["+expected+"]")
}
def checkOutput(expected:String, args:String*) = checkOutputEnv(Map.empty, expected, args:_*)
checkOutput("arg #0 is [OK]\nSUCCESS!", "OK")
checkOutput("arg #0 is [OK]\nproperty(test.hoge) is [huga]\nSUCCESS!", "-Dtest.hoge=\"huga\"", "OK")
checkOutputEnv(Map("show-vmargs"->"true"), "arg #0 is [OK]\nvmarg #0 is [-Xms6m]\nSUCCESS!","-J-Xms6m", "OK")
// include space
checkOutput("arg #0 is [C:\\Program Files\\Java]\nproperty(test.hoge) is [C:\\Program Files\\Java]\nSUCCESS!", "-Dtest.hoge=C:\\Program Files\\Java", "C:\\Program Files\\Java")
// include symbols
checkOutput("arg #0 is [\\[]!< >%]\nproperty(test.hoge) is [\\[]!< >%]\nproperty(test.huga) is [\\[]!<>%]\nSUCCESS!",
"\"-Dtest.hoge=\\[]!< >%\"", "\\[]!< >%", "-Dtest.huga=\"\\[]!<>%\"")
// include space and double-quote is failed...
// can't success include double-quote. arguments pass from Process(Seq("-Da=xx\"yy", "aa\"bb")) is parsed (%1="-Da", %2="xx\"yy aa\"bb") by cmd.exe ...
//checkOutput("arg #0 is [xx\"yy]\nproperty(test.hoge) is [aa\"bb]\nvmarg #0 is [-Dtest.hoge=aa\"bb]\nSUCCESS!", "-Dtest.hoge=aa\"bb", "xx\"yy")
assert(fails.toString == "", fails.toString)
}
@@ -1,5 +1,16 @@
package test

import scala.collection.JavaConversions._

object Test extends App {
println("SUCCESS!")
override def main(args: Array[String]): Unit = {
for((x,i) <- args.zipWithIndex) println("arg #" + i + " is [" + x + "]")
for((k,v) <- System.getProperties if k.startsWith("test.")) println("property(" + k + ") is [" + v + "]")
if(System.getenv("show-vmargs") == "true"){
for((x,i) <- java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments().zipWithIndex){
println("vmarg #" + i + " is [" + x + "]")
}
}
println("SUCCESS!")
}
}

0 comments on commit 6a7a131

Please sign in to comment.