Java runtime exec not handling string array well - java

I have a tomcat servlet which calls a jar function with parameters. The first parameter sometimes contains space. So I tried to use a String array, but it doesn't work at all.
What am I doing wrong?
requestParm = "java -classpath c:\\j\\test.jar test.connect " + fileName + " new";
requestParmarray =new String[]{"java -classpath c:\\j\\test.jar test.connect ",fileName , " new"};
requestParmarrayNew =new String[]{"java -classpath c:\\j\\test.jar test.connect "+fileName+" new"};
// This line works.but can not handle space well
Process ls_proc = Runtime.getRuntime().exec(requestPar);
// Does not call the function at all
Process ls_proc = Runtime.getRuntime().exec(requestParmarray );
// Does not call the function at all
Process ls_proc = Runtime.getRuntime().exec(requestParmarrayNew );
// Does not call the function at all
Process ls_proc = new ProcessBuilder("java -classpath c:\\j\\test.jar test.connect ",fileName, "new" ).start();

You're creating the array incorrectly: Each individual argument must be in its own entry:
String[] requestParmArray = new String[] {
"java",
"-classpath",
"c:\\j\\test.jar",
"test.connect",
fileName,
"new"
};
Process ls_proc = Runtime.getRuntime().exec(requestParmArray);
Also note that I removed the space you had after test.connect; the spaces you put on the command line are just to separate arguments, but in the above, they're separated by being separate entries in the array.

You should make the array in exec() have each parameter as a separate array entry like:
String[] requestPar = new String[]{"java", "-classpath", "c:\\j\\test.jar", "test.connect ", fileName, "new"};
And use it:
Process ls_proc = Runtime.getRuntime().exec(requestPar);

Related

Process does not exit when launched from Java

I am launching WebTorrent-CLI from within my Java application as a separate process. I am using zt-exec for managing the process. When WebTorrent is launched with the following command, it is supposed to exit after the file at given index (value of --select) has been downloaded.
"D:\downloadmanager\node\webtorrent.cmd" download "magnet:?xt=urn:btih:08ada5a7a6183aae1e09d831df6748d566095a10&dn=Sintel" --select 0 --out "D://nf/"
As expected, webtorrent-cli does exit after downloading 0th file when the command above is used to launch it from command line. But when I try the same from within my Java app, it completely ignores the --select option and continues downloading other files in the torrent.
Basically, when launched as a process from Java, webtorrent ignores all the options set (--select, --out or whatever). I should mention that there is nothing wrong with the library because recently I've tried replacing it with commons-exec and that solved nothing. Also, to make sure that the right command is passed while starting the process, I'm printing the command right before calling executor.start(). The command above is copied from the output retrieved from printing the command before the process starts.
This is how the process is started:
#Override
public synchronized void start() throws IOException {
if (mWasDownloadStarted || mWasDownloadFinished) return;
mExec.getCommand().listIterator().forEachRemaining(s -> {
System.out.print(s + " ");
});
mExec.start();
setProcessId();
mWasDownloadStarted = true;
mWasDownloadStopped = false;
}
This is how the command is prepared:
private String buildCommand() {
List <String> command = new ArrayList<>();
command.add("\"" + mManager.mWTLocation + "\"");
command.add("download");
command.add("\"" + mManager.mMagnetUrl + "\"");
if (mManager.mFileIndex >= 0) {
command.add("--select " + mManager.mFileIndex);
}
if (mManager.mSaveTo != null) {
command.add("--out \"" + mManager.mSaveTo + "\"");
}
mManager.mExec.command(command);
String cmdStr = "";
for (String s : command) {
cmdStr = cmdStr.concat(s + " ");
}
return cmdStr.trim();
}
What might be wrong?
Okay, so I was able to fix this issue.
The / character following the path specified as value of --out was causing the problem. In order to fix this, I added a line in node_modules/webtorrent-cli/bin/cmd.js to print the arguments passed to webtorrent:
console.log(process.argv)
With the /, output of this line was something like the following:
[ 'D:\\downloadmanager\\node\\node.exe',
'D:\\downloadmanager\\node\\node_modules\\webtorrent-cli\\bin\\cmd.js',
'download',
'magnet:?xt=urn:btih:08ada5a7a6183aae1e09d831df6748d566095a10&dn=Sintel',
'--select',
'0',
'--out',
'D:\\nf"' ]
Note the " that is included in the path after D:\\nf. When / is removed from the path, the quote disappears and webtorrent behaves as expected.
I doubt that this is a bug in webtorrent. I think zt-exec (or maybe I) was doing something stupid.
Somewhat unrelated, but I think I should also mention that I had to enclose every value for each option with quotes, even the index, to get rid of other nasty errors (e.g.: Error 87, the parameter is incorrect)

reading java property value with spaces into one variable

Hello my problem is as follows:
i have a property fiel with a startconfig for external program to run from java:
# Standardauswahl falls keine PlayerType übergeben wurden
Default = 1
# Liste der gültigen PlayerTypes
PlayerTypes = Human,MCTS,TMM,Random,Value
StartConfig = \"C:\\Program Files\\Java\\jdk1.7.0_13\\bin\\javaw.exe\" -Dlog4j.configuration=file:///C:/Users/djdeejay/git/myGit/com.djdeejay.cowTrade.client.standaloneplayer.application/bin/log4j.xml -Dfile.encoding=Cp1252 -classpath [..... some parameter deleted.....] 0.0-RC1.jar;C:\\Users\\djdeejay\\git\\myGit\\de.thWildau.cowTrade.server\\lib\\slf4j-api-1.5.2.jar;C:\\Users\\djdeejay\\git\\myGit\\de.thWildau.cowTrade.server\\lib\\slf4j-log4j12-1.5.2.jar;C:\\Users\\djdeejay\\git\\myGit\\de.thWildau.cowTrade.server\\lib\\log4j-1.2.16.jar com.djdeejay.cowTrade.client.standaloneplayer.application.RandomPlayerApplication %1 %2 %3
when i load the properties as follows
cmd = this.serverSettings.getPlayerTypeSetting("StartConfig");
#Override
public String getPlayerTypeSetting(String key) {
return this.startPlayerTypeSettingsProp.getProperty(key);
}
java cutting startconfig after the first space:
Cannot run program """C:\Program" when its in doublequotes or Cannot run program ""C:\Program":
i have tried several variants with "", with escaping and so on nothing gives my needed result
how do i config getproperty to read until EOL?
cheers
As discussed in the comments, the getProperty call is alright. But the usage as a single string in Runtime.getRuntime().exec(cmd) uses the default whitespace Tokenizer to split the string into command and argument.
To do this yourself, first split the string manually and then pass it to Runtime#exec:
String startCmdLine = this.serverSettings.getPlayerTypeSetting("StartConfig");
int cmdEndPos = startCmdLine.indexOf("javaw.exe") + "javaw.exe".length();
String cmd = startCmdLine.substring(0, cmdEndPos);
String args = startCmdLine.substring(cmdEndPos);
Runtime.getRuntime().exec(new String[]{ cmd, args });
Though I really advise you to take advantage of the JAVA_HOME environment variable if you just want to start a known java binary. That way you can reduce that to a set of parameters in the property file.
Try replacing your spaces with: "\u0020"
Use this:
StringEscapeUtils.escapeXml(String input);
See doc here

how to use property=value in CLI commons Library

I am trying to use the OptionBuilder.withArgName( "property=value" )
If my Option is called status and my command line was:
--status p=11 s=22
It only succeeds to identify the first argument which is 11 and it fails to identify the second argument...
Option status = OptionBuilder.withLongOpt("status")
.withArgName( "property=value" )
.hasArgs(2)
.withValueSeparator()
.withDescription("Get the status")
.create('s');
options.addOption(status);
Thanks for help in advance
You can access to passed properties using simple modification of passed command line options
--status p=11 --status s=22
or with your short syntax
-s p=11 -s s=22
In this case you can access to your properties simply with code
if (cmd.hasOption("status")) {
Properties props = cmd.getOptionProperties("status");
System.out.println(props.getProperty("p"));
System.out.println(props.getProperty("t"));
}
If you need to use your syntax strictly, you can manually parse your property=value pairs.
In this case you should remove .withValueSeparator() call, and then use
String [] propvalues = cmd.getOptionValues("status");
for (String propvalue : propvalues) {
String [] values = propvalue.split("=");
System.out.println(values[0] + " : " + values[1]);
}

Passing arguments to a lua function with luaj

I'm trying to call a lua function in a Java program using LuaJ. It works fine when I'm not passing any arguments to the closure:
String script = "print 'Hello World!'";
InputStream input = new ByteArrayInputStream(script.getBytes());
Prototype prototype = LuaC.compile(input, "script");
LuaValue globals = JsePlatform.standardGlobals();
LuaClosure closure = new LuaClosure(prototype, globals);
closure.call();
But now I'm trying a lua script with a top-level function that takes an argument and I just can't figure out how to pass in the argument from Java. Here's what I got so far:
String script = "function something(argument)\n"+
"test_string = 'Hello World!'\n"+
"print(test_string)\n"+
"print(argument)\n"+
"end";
InputStream input = new ByteArrayInputStream(script.getBytes());
Prototype prototype = LuaC.compile(input, "script");
LuaValue globals = JsePlatform.standardGlobals();
LuaClosure closure = new LuaClosure(prototype, globals);
closure.invokemethod("something", CoerceJavaToLua.coerce("Foo"));
This results in an Exception on the invokemethod line:
org.luaj.vm2.LuaError: attempt to index ? (a function value)
Thanks for your help!
In lua, the top-level scope is an anonymous function with variable arguments. These are accessed using ... In your example, you don't need the function named something, the chunk itself can be used as an unnamed function.
For example, this code in luaj-3.0-beta1
String script = "argument = ...\n"+
"test_string = 'Hello World!'\n"+
"print(test_string)\n"+
"print(argument)\n";
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.loadString(script, "myscript");
chunk.call( LuaValue.valueOf("some-arg-value") );
Produced this result for me:
Hello World!
some-arg-value
You can pass in any number of arguments this way.
Since you receive
org.luaj.vm2.LuaError: attempt to index ? (a function value)
as your error; this means that your function is not being created at all.
Try it without \n and give spaces in the variable script. Like this:
String script = "function something(argument) " +
" test_string = 'Hello World!'; " +
" print( test_string ); " +
" print( argument ); " +
" end";

Scala - Fails to execute a process through terminal in a particular scenario

I'm using graphviz to generate graphs based on the messages passed in a scala program.
To invoke the graphviz application from inside the scala program, I'm using the exec() method (similar to Java). It successfully executed the command and created the graph when I used the below code snippet:
var cmd: String = "dot -Tpng Graph.dot -o Graph.png"
var run: Runtime = Runtime.getRuntime() ;
var pr: Process = run.exec(cmd) ;
However It fails to execute after changing the path of the input and output files (I just included a directory inside which the input file and output file resides as shown below)
def main(args: Array[String]): Unit = {
var DirectoryName: String = "Logs"
var GraphFileName: String = DirectoryName + File.separator + "Graph.dot"
val GraphFileObj: File = new File(GraphFileName)
// var cmd: String = "dot -Tpng Graph.dot -o Graph.png"
var cmd: String = "dot -Tpng \"" + GraphFileObj.getAbsolutePath + "\" -o \"" + DirectoryName + File.separator + "Graph.png\"" ;
println(cmd)
var run: Runtime = Runtime.getRuntime() ;
var pr: Process = run.exec(cmd) ;
}
The same command when executed through terminal gives proper output. Can you please help me to find what I'm missing?
exec is not a shell...e.g. quoting won't work as you expect, and thus your path (which may contain spaces, etc) will not be processed as you expect. The command will be broken apart using StringTokenizer, and your literal quotes will be...well..literal.
Use the form of exec that takes an array instead, so you can tokenize the command correctly.
val args = Array[String]("dot", "-Tpng", GraphFileObj.getAbsolutePath, ...);
run.exec(args)

Categories