Avatar of numtech
numtech

asked on 

Java 6 exec, escaping special characters within ProcessBuilder.command(String[])

Hello,

I use the commandline from my main java app to execute another 'mailer.jar' app.
One of the argument is the mail content that can contains any character including \n, \r, ", '...

I thought using
ProcessBuilder.command(String[])

Open in new window

instead of  
ProcessBuilder.command(String)

Open in new window

would prevent the ProcessBuilder.exec from having troubles with splitting the command line, but it does not work.

If my command is a String[] array containing:
String[] cmd=new String[]{"java",
"-jar",
"mailer.jar"
"smtp.test.org",
"test@test.org",
"test@test.org",
"my subject ...",
"my content with carriage returns and other strange characters"};

Open in new window


I will obtain as the String[] args of the main method of my mailer.jar
String[] args=new String[]{
"smtp.test.org",
"test@test.org",
"test@test.org",
"my subject ...",
"my content with",
"carriage returns and",
"other strange characters",
...};

Open in new window


What should I do?
I would prefer not to use Apache Commons Exec because we have developped our own low level lib to handle multi threading and asynchronous exec...

Thanks for your help!

Regards,

Renaud
JavaShell Scripting

Avatar of undefined
Last Comment
numtech
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

For the final array element, does a simple string work?
Avatar of numtech
numtech

ASKER

Hello,

Yes it works perfectly with simple String content in the cmd.
But if one of the String in the cmd contains any " or ' character, it would be splitted in the final array.

I did this, and it solved the problem under windows, but I think it is really not a good idea to go into this because I will have to test it on every plaform/version (and I am targetting Win, MacOS and Linux).
private String[] escapeCMD(String[] commandLine) {
        String[] escapedCmd = Arrays.copyOf(commandLine, commandLine.length);
        for (int i = 0; i < escapedCmd.length; i++) {
            escapedCmd[i] = escapedCmd[i].replace("\"", "\\\"").replace("'", "\\'");
        }
        return escapedCmd;
    }

Open in new window

Avatar of numtech
numtech

ASKER

What a weird work around when I am not supposed to know the underlying OS specifics!
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Would it not be easier just to do something like the following?
Mailer.main(args);

Open in new window

Avatar of numtech
numtech

ASKER

Not an option, mailer.jar cannot be loaded inside the main JVM. We have designed this to obtain a low coupling between different components that will evolve in a independant way.
Our designt is:
boot.jar
update.jar
runtime.jar
mailer.jar
The command line prototype and exit code of each main method is defined as the low level interface between application components.
We tryed the classloader approch in the past but we gave up after a while because of an memory leak issue in the unloading process (and we do not want to re-invent OSGI...)
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

I'm afraid to say that it looks like what you did in http:#35769647 IS going to have to be tested for each of your target platforms then
Avatar of Mick Barry
Mick Barry
Flag of Australia image

> "my content with",
> "carriage returns and",
> "other strange characters",

they are separate arguments. Are you expecting them to be treated as one?
And how are you receiving the special characters?
Avatar of numtech
numtech

ASKER

To illustrate I can show you the real example
This is what is sent as the commandline arguments:

java

-jar

mailer.jar

zimbra.xxxx.fr

ryyyyy@xxxx.fr

ryyyyy@xxxx.fr

NUMAILER[BOOT] RollbackSuccesfull -- satId=40436aff506a72aae8552438d493238b22d67581, path=C:/Program Files/Xxxx/Backup4, companyId=2

The install add to be rolled back.;Rollback reason was: XxxxException : The process terminated in error after 12ms, IExecutionResult[exitCode=1, stdOut="", stdErr=""] >>>> STACK TRACE :[fr.xxxx.boot.RuntimeBooter.bootRuntime(RuntimeBooter.java:125), fr.xxxx.boot.RuntimeBooter.run(RuntimeBooter.java:51), java.lang.Thread.run(Unknown Source)]

 ..\log, 25]

Open in new window


This is what I receive as the main args:
Arg[0] : zimbra.xxxx.fr

Arg[1] : ryyyyy@xxxx.fr

Arg[2] : ryyyyy@xxxx.fr

Arg[3] : NUMAILER[BOOT] RollbackSuccesfull -- satId=40436aff506a72aae8552438d493238b22d67581, path=C:/Program Files/Xxxx/Backup4, companyId=2

Arg[4] : The install add to be rolled back.;Rollback reason was: XxxxException : The process terminated in error after 17ms, IExecutionResult[exitCode=1, stdOut=",

Arg[5] : stdErr=Invalid or corrupt jarfile runtime-4.1.1.jar ;]

Arg[6] : >>>>

Arg[7] : STACK

Arg[8] : TRACE

Arg[9] : :[fr.xxxx.boot.RuntimeBooter.bootRuntime(RuntimeBooter.java:125),

Arg[10] : fr.xxxx.boot.RuntimeBooter.run(RuntimeBooter.java:51),

Arg[11] : java.lang.Thread.run(Unknown

Arg[12] : Source)] ..\log 25

Open in new window

Avatar of Mick Barry
Mick Barry
Flag of Australia image

Have you tested it on the other platforms?
Runtime.exec() used to be terrible at handling the command line, one would have hoped they had fixed it up for ProcessBuilder
ASKER CERTIFIED SOLUTION
Avatar of numtech
numtech

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Issue is that you don't know what shell (if any) is involved.
Avatar of numtech
numtech

ASKER

If found myself the solution by exploring apache commons exec sources.
Java
Java

Java is a platform-independent, object-oriented programming language and run-time environment, designed to have as few implementation dependencies as possible such that developers can write one set of code across all platforms using libraries. Most devices will not run Java natively, and require a run-time component to be installed in order to execute a Java program.

102K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo