escaping sed characters java not working - java

I'll start with saying that I found a lot of topics simular to mine, but none were able to provide me with the correct answer.
I'm trying to insert a string into an xml file using following shell script :
#!/bin/bash
cd /var/lib/tomcat7/webapps/Config || exit
sudo sed -i '/<\/home>/i <entry>'"$#"'</entry>' data.xml
when executing the script like this ./script.sh "test entry", my xml-file will look like this :
<home>
<entry>test entry</entry>
</home>
which is what I want. But when I try to call this script trough java, I'm not able to successfully escape the quotes.
My java code is this :
String entry = "test entry";
String command = "/home/user/addentry.sh " + "\"" + entry + "\"";
Process p = null;
Runtime run = Runtime.getRuntime();
try {
p = run.exec(command);
}
.....
When the code is executed my xml file looks like this :
<home>
<entry>"test
</home>
As you can see, the quote is also passed as part of my input.
When changing the java code to :
String command = "/home/user/addentry.sh " + entry;
it works fine for strings without a space (so only 1 parameter for the script)
Thanks in advance

Try this:
package org.script.test;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Invalid arguments");
return;
}
String entry="\"" +args[0]+ "\"";
System.out.println("adding: " + entry);
Process pr = null;
try {
pr =
Runtime.getRuntime().exec(new String[] { "/bin/sh", "-c", "cd /home/oracle/testscript ; . ./test.sh " + entry });
} catch (IOException e) {
e.printStackTrace();
}
}
}
Called by:
assume package org.script.test
java -Xms128M -Xmx128M -classpath testScript.jar org.script.test.Main "test entry"
It works even if you don't pass the arguments:
package org.mihai.script;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
String entry = "test entry 2";
System.out.println("adding: " + entry);
Process pr = null;
try {
pr =
Runtime.getRuntime().exec(new String[] { "/bin/sh", "-c", "cd /home/oracle/testscript ; . ./test.sh " + "\"" + entry +"\"" });
} catch (IOException e) {
e.printStackTrace();
}
}
}
Call:
java -Xms128M -Xmx128M -classpath testScript.jar org.mihai.script.Main
Output data.xml:
<home>
<entry>test entry</entry>
<entry>test entry 2</entry>
</home>

Related

Runtime.getRuntime().exec(command) doesn't work

I have a problem with executing command in Runtime.getRuntime().exec(command) on my linux DEV machine.
I'm trying to convert html content to mobi format using calibre but it doesn't work.
Even if I added log.warn to display what this process returns it shows nothing.
It works on my local machine where I do have Windows 10 and I read on the Internet that I should point out that command should be launched on linux so I added String[] cmd = {"bash", "-c", command}; but it still doesn't work.
My command looks like this:
/usr/src/calibre/ebook-convert /tmp/filesDirectory_mobi3970575619159760977/d7ed6792-b3cb-4761-bb6a-b9facf9e7a6c9250643820137116550.html /tmp/filesDirectory_mobi3970575619159760977/d7ed6792-b3cb-4761-bb6a-b9facf9e7a6c11909891397415910433.mobi
And here's my code:
#Override
public Document convert(Document document, DocumentFormat documentFormat) {
Document htmlDocument = htmlDocumentConverter.convert(document, documentFormat);
try {
log.info("Converting document from {} to {}", getSourceFormat().toString(), getTargetFormat().toString());
CalibreConfigData calibreData = calibreConfig.getConfigurationData(CalibreConversion.HTML_TO_MOBI);
Files.write(calibreData.getSourceFilePath(), htmlDocument.getContent());
String command = calibreData.getCalibreCommand();
String[] cmd = {"bash", "-c", command};
var r = Runtime.getRuntime().exec(cmd);
r.waitFor();
log.warn("Process: " + new String(r.getInputStream().readAllBytes(), StandardCharsets.UTF_8));
byte[] convertedFileAsBytes = Files.readAllBytes(calibreData.getConvertedFilePath());
// Files.deleteIfExists(calibreData.getSourceFilePath());
// Files.deleteIfExists(calibreData.getConvertedFilePath());
// Files.deleteIfExists(calibreData.getFilesDirectoryPath());
return new Document(convertedFileAsBytes);
} catch (InterruptedException | IOException e) {
log.error("Conversion failed due to problem: " + e);
throw new ConversionException("Conversion failed due to problem: " + e);
}
}
I checked created tempFiles and found out that file .html has content inside but file .mobi is empty even after executing above's command.
A main method of a Calibre conversion invoker could be as simple as the below:
public static void main(String[] args) {
try {
String[] command = { "/usr/src/calibre/ebook-convert", args[0], args[1] };
ProcessBuilder pb = new ProcessBuilder(command);
pb.inheritIO();
pb.start();
} catch (Throwable t) {
t.printStackTrace();
}
}

run git clone in Java getRuntime.exec() - use /bin/bash in linux - “no such file or directory” in error stream

I am trying to execute git clone in Java using Java's Runtime.getRuntime().exec() in Linux and the interpreter is /bin/bash. However, I get "no such file or directory" in error stream. I searched the stackoverflow and found no answer can solve my problem. Here is my program in Test.java:
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
String version = "10.1.1";
String repo_url = "https://github.com/postcss/postcss-url";
String directory = "./tmp";
String cmd = "\"/usr/bin/git clone --branch " + version + " " + repo_url + " --depth=1 " + directory + "\"";
// String cmd = "git -h";
String interpreter = "/bin/bash";
cmd = " -c "+ cmd;
System.out.println(interpreter + cmd);
Process process = Runtime.getRuntime().exec(new String[]{ interpreter, cmd });
print(process.getInputStream());
print(process.getErrorStream());
process.waitFor();
int exitStatus = process.exitValue();
System.out.println("exit status: " + exitStatus);
File[] files = new File(directory).listFiles();
System.out.println("number of files in the directory: " + files.length);
}
public static void print(InputStream input) {
new Thread(new Runnable() {
#Override
public void run() {
BufferedReader bf = new BufferedReader(new InputStreamReader(input));
String line = null;
try {
while ((line = bf.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("IOException");
}
}
}).start();
}
}
./tmp is surely an empty directory. I use javac Test.java to compile the code and then run java Test. Besides, I tried sudo java Test and got the same result. I get output like this:
/bin/bash -c "/usr/bin/git clone --branch 10.1.1 https://github.com/postcss/postcss-url --depth=1 ./tmp"
exit status: 127
/bin/bash: -c "/usr/bin/git clone --branch 10.1.1 https://github.com/postcss/postcss-url --depth=1 ./tmp": No such file or directory
Exception in thread "main" java.lang.NullPointerException
at Test.main(Test.java:18)
When I use "git -h" or "ls", it works just fine. But, this command /bin/bash -c "/usr/bin/git clone --branch 10.1.1 https://github.com/postcss/postcss-url --depth=1 ./tmp" works in shell but failed in Java. How can I solve this problem?
You have to pass -c as a separate parameter, and you shouldn't add literal double quotes to the command:
new String[]{ "bash", "-c", "git clone ..." }
This is because spaces and quotes are shell syntax, and Runtime.exec doesn't invoke one to run the command (which happens to be a shell invocation, but that's unrelated)

Error Could not find or load main class -jar

I am working on a java UNO project, OS : Ubuntu 14. I am calling exec via passing command to run via a jar file with some set of sub commands of that jar file.
String finalOutputMSG = "";
String[] cmd = {JAVA_LOCATION, " -jar ", JAR_LOCATION, " " + inputFile, " -dir ", ".isc", " -out xml"};//java location provides java location, jar location provides jar location, inputfile contains input file's location -dir provides output directory with name .isc, -out is output file with file format for output is xml
Similar command ran properly without showing any errors but in a case where I am trying to import a file and convert it into another format eg .xlsx to .xml, is giving error. In commands it worked, I have already generated outputs from an input file.
finalOutputMSG = exec(cmd);
/**
* exec() is executed and outputs are displayed
*
* #param String[] command passed to jar
* #return output message containing outputs or output message
*/
private static String exec(String[] cmd) {
String outputMSG = "";
Process proc = null;
try {
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);//any error output generated by subprocesses merged with the standard output,
//read using the Process.getInputStream()
///* Start the process */
proc = pb.start();
if (debug) {
System.out.println("Process started !");
}
outputMSG = getOutput(proc);
if (debug) {
System.out.println("outputMSG " + outputMSG);
}
} catch (IOException e) {
if (debug) {
System.out.println("Exception in exec " + e.getMessage());
JOptionPane.showMessageDialog(null, "Exception in exec ");
}
// StringBuilder append = appendToFile.append("Exception in exec ").append(e.getMessage());
} catch (Exception e) {
if (debug) {
System.out.println("Exception in exec " + e.getMessage());
JOptionPane.showMessageDialog(null, "Exception in exec ");
}
} finally {
///* Clean-up */
proc.destroy();
if (debug) {
System.out.println("Process ended !");
}
}
return outputMSG;
}
/**
* Reads output from current process
*
* #param current process
* #return output read in current process
*/
private static String getOutput(Process p) {
StringBuilder outStream = new StringBuilder();
if (debug) {
System.out.println("StringBuilder initialized in getOutput");
}
try {
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
if (debug) {
System.out.println("BufferedReader initialized in getOutput");
}
String line = null;
if (debug) {
System.out.println("in.readLine() in getOutput abt to be read");
}
while ((line = in.readLine()) != null) {
outStream.append(line);
if (debug) {
System.out.println("line in getOutput " + line);
System.out.println("outStream in getOutput " + outStream);
}
outStream.append("\n");
}
} catch (IOException e) {
if (debug1) {
System.out.println("IOException in getOutputs " + e.getMessage());
}
} catch (Exception ex) {
if (debug1) {
System.out.println("Exception in getOutputs" + ex.getMessage());
}
}
return outStream.toString();
}
Error Message depicted by Netbeans
Error: Could not find or load main class -jar
I have searched on the issue, but could not find any help that is useful, I could not understand, what is missing.
Solution:
String[] cmd = {JAVA_LOCATION, " -jar ", JAR_LOCATION, " " + inputFile, " -dir ", ".isc", " -out xml"};
I replaced the values that printed in console, and ran the command so got on terminal, it worked fine.
Solution: the command to be used must be without any spaces in the ends. Because terminal in linux interprets the commands like for "ls", but in java/ any programming language, it doesn't interprets for ls, so in case of the following parameter cmdarray
public Process exec(String[] cmdarray)
throws IOException
takes the command as it is.
String[] cmd = {JAVA_LOCATION, "-jar", JAR_LOCATION, inputFile, "-dir", ".isc", "-out", "xml"};

Java Powershell CreateProcess error=2, The system cannot find the file specified

I am executing powershell commands in java and I have written two programs, however the strange part is one works fine and the other throws the error. The code that throws the error is as shown
I have tried the following
1) Spcifying the fully specified path of powershell
2) My path variable has the following - "C:\WINDOWS\system32\WindowsPowerShell\v1.0"
I know I might be doing something trivial but its been a day and I am unable to figure out what the issue might be
import java.io.IOException;
public class FileCount {
public static void main(String[] args) {
Process flCntProcess = null;
try {
String test = "C:\\WINDOWS\\system32\\windowspowershell\\v1.0\\powershell.exe -Command \"& { Get-ChildItem C:\\test -Recurse -force | Measure-Object }\"";
System.out.println("Powershell command : " + test);
ProcessBuilder builder = new ProcessBuilder(test);
builder.redirectErrorStream(true);
flCntProcess = builder.start();
// FILE COUNT OUTPUT STREAM PROCESSING
NotifyThreadComplete outputThread = new ProcessHandler(flCntProcess.getInputStream(),"OUTPUT");
outputThread.addListener(new ThreadCompleteListener() {
#Override
public void notifyCompletion(Thread t, long startTm, boolean didErrorOut, String noOfLines) {
System.out.println("Completed Output Stream Processing");
System.out.println("Printing values");
System.out.println("No of Lines : " + noOfLines);
System.out.println("Did Error out : " + didErrorOut);
if(didErrorOut) {
System.out.println("Do not continue with processing");
} else {
System.out.println("Continue with processing");
}
}
});
System.out.println("Starting output thread ");
outputThread.start();
} catch (Exception e) {
System.err.println("Exception while counting files using Powershell Command" + e.getMessage());
} finally {
if(flCntProcess != null && flCntProcess.getOutputStream() != null) {
try {
flCntProcess.getOutputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Error code indicates the file to execute can't be found. Try splitting up the program from its arguments:
String ps = "C:\\WINDOWS\\system32\\windowspowershell\\v1.0\\powershell.exe";
String args = "-Command \"& { Get-ChildItem C:\\test -Recurse -force | Measure-Object}\"";
ProcessBuilder builder = new ProcessBuilder(ps, args);
The constructor of ProcessBuilder does not accept a single String containing a cli invocation, but an array of Strings containing in order :
the program to be executed
its arguments
See the javadoc
So it interprets your whole String test as the program name, splitting it up should work :
final String psh = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
final String args = "-Command & { Get-ChildItem C:\\temp -Recurse -force | Measure-Object }";
final ProcessBuilder builder = new ProcessBuilder(psh, args);

Running .pkg on MAC OS from java code

Am trying to run a .mpkg application from my java code :
public void runNewPkg(){
try {
String command = "sudo installer -pkg Snip.mpkg -target /Applications";
Process p = Runtime.getRuntime().exec(command);
System.out.println(p.getErrorStream());
} catch (Exception ex) {
ex.printStackTrace();
}
}
And am getting the following error and my terminal window hangs..
java.lang.UNIXProcess$DeferredCloseInputStream#2747ee05
Password:
Sumit-Ghoshs-iMac-3:downloads sumitghosh3$ Password:
Password:
-bash: **********: command not found
Sumit-Ghoshs-iMac-3:downloads sumitghosh3$
I Think i need to provide the password also to run the pkg from the command line
Could you tell me how i can do that?
You can provide the password to sudo:
echo "p#sw0rd" | sudo -S cal -y 2011
The command above runs 'cal -y 2011' with root permissions.
I would actually try editing your /etc/sudoers file to not prompt for a password. If you use the NOPASSWD tag, you should be able to do that. An example entry would be:
sumitghosh3 ALL=(ALL) NOPASSWD: ALL
If you want an interactive solution for elevating privilege, I have used openscript to elevate privilege of a wrapped shell script. It goes something like this:
import java.io.File;
import java.text.MessageFormat;
/**
* OsxExecutor.java
*/
public class OsxExecutor {
private String error = null;
private String output = null;
/**
* Privileged script template format string.
* Format Arguments:
* <ul>
* <li> 0 = command
* <li> 1 = optional with clause
* </ul>
*/
private final static String APPLESCRIPT_TEMPLATE =
"osascript -e ''try''"
+ " -e ''do shell script \"{0}\" {1}''"
+ " -e ''return \"Success\"''"
+ " -e ''on error the error_message number the error_number'' "
+ " -e ''return \"Error: \" & error_message''"
+ " -e ''end try'';";
public void executeCommand(String command, boolean withPriviledge) {
String script = MessageFormat.format(APPLESCRIPT_TEMPLATE,
command,
withPriviledge
? "with administrator privileges"
: "");
File scriptFile = null;
try {
scriptFile = createTmpScript(script);
if (scriptFile == null) {
return;
}
// run script
Process p = Runtime.getRuntime().exec(scriptFile.getAbsolutePath());
StreamReader outputReader = new StreamReader(p.getInputStream());
outputReader.start();
StreamReader errorReader = new StreamReader(p.getErrorStream());
errorReader.start();
int result = p.waitFor();
this.output = outputReader.getString();
if (result != 0) {
this.error = "Unable to run script "
+ (withPriviledge ? "with administrator privileges" : "")
+ "\n" + script + "\n"
+ "Failed with exit code: " + result
+ "\nError output: " + errorReader.getString();
return;
}
} catch (Throwable e) {
this.error = "Unable to run script:\n" + script
+ "\nScript execution "
+ (withPriviledge ? " with administrator privileges" : "")
+ " failed: " + e.getMessage();
} finally {
if (scriptFile.exists()) {
scriptFile.delete();
}
}
}
}
If withPriviledge flag is true, a password dialog will be raised. Not shown is createTmpScript() which creates an executable file in /tmp, and StreamReader which extends Thread and is used to capture both stdout and stderr streams.

Categories

Resources