Java can't do system call - java

I am using Java to format a poem in LaTeX and then compile it. The LaTeX-ization works perfectly fine, but I somehow can't run the command. Is this a problem with my LaTeX invocation? For some reason, when I use Java to write an equivalent batch file and then run it, Java will do nothing but when I run the batch file from the shell, it works.
/**
*
* #param title the title of the poem
* #param poem a <code>List</code> with one string for each line of the
* poem.
* #throws FileNotFoundException
*/
protected static void writePDF(final String title, List<String> poem) throws FileNotFoundException {
final StringBuilder latex = new StringBuilder(0);
// I know I shouldn't concatenate like this; I'll fix it later.
// eeeewww escapes
latex.append(
"\\documentclass[letterpaper,12pt,article,oneside]{memoir}\n"
+ "\\usepackage[utf8]{inputenc}\n"
+ "\\usepackage{ebgaramond}\n"
+ "\\usepackage{hyperref}\n"
+ "\\usepackage[protrusion,expansion,kerning,tracking,spacing]{microtype}\n"
+ "\\linespread{1.3}\n"
+ "\\nonfrenchspacing\n"
+ "\\microtypecontext{spacing=nonfrench}\n"
+ "\\begin{document}\n"
+ "\\title{" + title + "}\n"
+ "\\author{}\n"
+ "\\date{\\today}\n"
+ "\\maketitle\n"
+ "\\setlength{\\parindent}{0pt}\n"
+ "\\setlength{\\parskip}{\\baselineskip}\n");
// Go Java 8!
poem
.stream()
.map((String s)
// Original poem's in HTML
-> s.replace("<p>", "\n\n").replace("<br>", "\\\\\n"))
.forEach(latex::append);
latex.append("\n\\end{document}");
final String latexstr = latex.toString().replace("...", "\\ldots");
final String filename = title + ".tex";
final File file = new File(filename);
try (final PrintWriter pw = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)))) {
pw.print(latexstr);
}
final String path = file.getAbsolutePath()
.substring(0, file.getAbsolutePath().lastIndexOf("\\")) + "\\";
System.out.println("Path: " + path);
final String LaTeXcmd = "pdflatex \""
+ path
+ title + "\"";
final File script = new File(""
+ rand.nextDouble()
+ "compile"
+ title.replace(" ", "_")
+ ".bat");
//I originally wanted just to write a batch file and run it from Java.
// try (final PrintWriter pw = new PrintWriter(new BufferedOutputStream(new FileOutputStream(script)))) {
// pw.print(""
// //"#echo off\n"
// + "cd " + path + "\n"
// + LaTeXcmd + "\n"
// // + "del \"" + path + title + ".aux\"\n"
// // + "del \"" + path + title + ".log\"\n"
// // + "del \"" + path + title + ".out\"\n"
// // + "del \"" + path + title + ".tex\"\n"
// // + "start /b \"\" cmd /c del \"%~f0\"&exit /b\n"
//
// + "msg * all\n"
// );
// }
try {
System.out.println("latexcmd " + LaTeXcmd);
final File workingdir = new File(path);
System.out.println("workingdir " + workingdir);
// >>>>>>>>>>>>>>>> IS THIS CORRECT? <<<<<<<<<<<<<<<<
Runtime.getRuntime().exec(LaTeXcmd, new String[]{}, workingdir);
// This statement works perfectly fine (Windows).
// Runtime.getRuntime().exec("msg * all");
} catch (IOException ex) {
Logger.getLogger(PoetryBackend.class.getName()).log(Level.SEVERE, null, ex);
}
}

It's not correct. Try
String command = new String[] {"cmd", "/c", LaTeXcmd };
Runtime.getRuntime().exec(command, new String[]{}, workingdir);
since otherwise you're not executing it through command interpreter, which is what you want if you want it to behave like you would run it from cmd prompt.
This applies to running .bat files as well.

Related

Process.waitFor() not "waiting" for current thread to finish

I have an excel sheet where it has a list of jar files to be executed. To kick start the testing, I will run a code to read from the said excel sheet and execute the jar files in the excel sheet. The code to run those jar files is as follow :
final Process p = Runtime.getRuntime().exec("cmd /c start cmd /k java -jar " + start.jar_filepath + " " + start.tc_name + " " + start.test_data + " " + start.test_result + " " + start.test_cycle);
This will actually run all the jar files concurrently.
I actually wanted one jar to be executed at one time, and the next jar to be executed AFTER the current jar has finish execution.
I added the following.
p.waitFor();
However, it still behaves the same, that is, it is executed simultaneously.
Am I using the waitFor() wrongly ? Advice is appreciated.
Update:
The following is the code that iterates the excel sheet
public static void main(final String[] args) throws IOException, Throwable {
final DataFormatter df = new DataFormatter();
final FileInputStream StartInput = new FileInputStream("c:\\TA\\TestConfig_MA.xlsx");
final XSSFWorkbook StartInputWB = new XSSFWorkbook(StartInput);
final XSSFSheet sheet = StartInputWB.getSheet("Config");
System.out.println("Amount of Row in test config : "+ sheet.getLastRowNum());
start.count = 1;
//while (start.count <= sheet.getLastRowNum()) {
for(start.count = 1; start.count <= sheet.getLastRowNum(); start.count++){
System.out.println("Total test case = " + sheet.getLastRowNum());
System.out.println(start.count);
final XSSFRow row = sheet.getRow(start.count);
start.testability = row.getCell(0).toString();
start.jar_filepath = row.getCell(1).toString();
start.tc_name = row.getCell(2).toString();
start.test_data = row.getCell(3).toString();
start.test_result = row.getCell(4).toString();
start.test_cycle = df.formatCellValue(row.getCell(5));
System.out.println("test cycle from start.jar = " + start.test_cycle);
System.out.println("Test Case Name : " + start.tc_name);
if (start.testability.equals("Y") || start.testability.equals("y)")) {
System.out.println("Test Case Name : " + start.tc_name);
System.out.println("Round : " + start.count);
final Process p = Runtime.getRuntime().exec("cmd /c start cmd /k java -jar " + start.jar_filepath + " " + start.tc_name + " " + start.test_data + " " + start.test_result + " " + start.test_cycle);
p.waitFor();
System.out.println("wait for = " +p.waitFor());
else {
System.out.println("Its a no");
}
// ++start.count;
}//for
System.out.println("test is done");
}
}
why you need "cmd /c start cmd /k ..."?
You run cmd which runs start which runs cmd which runs java
In particular, start opens a new window and returns immediately. Therefore p.waitFor(); will wait for start to complete, but not the new window opened by it.
You may want to narrow it to simple
...exec("java -jar " + ...)
or at least
...exec("cmd /c java -jar " + ...)

Executing python script from Netbeans and reading output, FAILS in one case but not another

I am currently heeding advice from this Stack Overflow post:
Call and receive output from Python script in Java? (which links to http://www.devdaily.com/java/edu/pj/pj010016 for getting the output)
So, that's great and all, and I used it for the following code successfully:
String directPath;
if (Files.exists(Paths.get("C:/Users/jiaqin/Documents/NetBeansProjects/NCHandler/nchandlerv2/NCPythonFiles/"))) {
directPath = "C:/Users/jiaqin/Documents/NetBeansProjects/NCHandler/nchandlerv2/NCPythonFiles/";
}
else {
directPath = "/home/lab/testNetconf/NCPythonFiles/net_back_end/";
}
Process p = Runtime.getRuntime().exec("python " + directPath + "get_platform_and_OS.py -ssh_ip " + ui.ssh_ip
+ " -username " + ui.username + " -password " + ui.password);
Scanner threeInfo = new Scanner(p.getInputStream());
String hostName = "";
String IP_Address = ui.ssh_ip;
String OS = "";
String platform = "";
int iter = 0;
while (threeInfo.hasNextLine()) {
switch(iter) {
case 0:
hostName = threeInfo.nextLine();
break;
case 1:
OS = threeInfo.nextLine();
break;
case 2:
platform = threeInfo.nextLine();
break;
default:
break;
}
iter ++;
}
threeInfo.close();
Label hostNameLabel = new Label(hostName);
Label sshLabel = new Label("SSH IP Address: " + IP_Address);
Label OSLabel = new Label(OS);
Label platformLabel = new Label(platform);
Essentially, I run a python script by determining its path first, then I read the output using a Scanner (instead of a BufferedReader like in the post). Based on that case, I have a later method that uses the exact same concept:
public static String verifyShowCommands(String[] showCommands, MainUI ui) {
try {
String errorText = "";
String retErrors = "";
System.out.println("Python exec command is:\n" + "python /home/lab/testNetconf/NCPythonFiles/net_back_end/verify_show_commands.py -ssh_ip " + ui.ssh_ip + " -username "
+ ui.username + " -password " + ui.password + " -show_commands \"" + String.join(", ", showCommands) + "\"");
Process p = Runtime.getRuntime().exec("python /home/lab/testNetconf/NCPythonFiles/net_back_end/verify_show_commands.py -ssh_ip " + ui.ssh_ip + " -username "
+ ui.username + " -password " + ui.password + " -show_commands \"" + String.join(", ", showCommands) + "\"");
BufferedReader obtainedInfo = new BufferedReader(new InputStreamReader(p.getInputStream()));
String read = null;
while ((read = obtainedInfo.readLine()) != null) {
System.out.println("New line found");
retErrors += read;
}
System.out.println("Obtained Info is:" + retErrors + " and that's it");
obtainedInfo.close();
for (int i = 0; i < showCommands.length; i ++) {
if (i < showCommands.length - 1) {
int thisSCStart = retErrors.indexOf(showCommands[i]);
int nextSCStart = retErrors.indexOf(showCommands[i+1]);
String outputSC = retErrors.substring(thisSCStart, nextSCStart);
if (outputSC.contains("'Valid': 'No'")) {
errorText += outputSC + "\n";
}
}
else {
String outputSC = retErrors.substring(retErrors.indexOf(showCommands[i]));
if (outputSC.contains("'Valid': 'No'")) {
errorText += outputSC + "\n";
}
}
}
return errorText;
}
catch (IOException e) {
return null;
}
}
As you can see, I'm once again running a python script and reading the output. The error occurs when I attempt to get the substring of retErrors - because retErrors is an empty string; that's right, for some reason, this time the output is NOT getting read. Note that the above uses BufferedReader; I was originally using Scanner, and when that failed I changed over because I thought maybe for god-knows-what reason, synchronization might affect the situation. Unfortunately, it seemed there was STILL no output to read.
As for how I know, I simply observed in the Netbeans output and searched for the line
System.out.println("Obtained Info is:" + retErrors + " and that's it");
Then, you might ask the obvious question: what if the command is invalid? Well, I printed out the entire exec command at the top as well:
System.out.println("Python exec command is:\n" + "python /home/lab/testNetconf/NCPythonFiles/net_back_end/verify_show_commands.py -ssh_ip " + ui.ssh_ip + " -username "
+ ui.username + " -password " + ui.password + " -show_commands \"" + String.join(", ", showCommands) + "\"");
So, I looked for that line in the Netbeans output, and there it was:
Info: Python exec command is:
python /home/lab/testNetconf/NCPythonFiles/net_back_end/verify_show_commands.py -ssh_ip 9.0.0.12 -username root -password lab -show_commands "show bgp scale"
And then I copy-pasted that exact command into a terminal and ran it, and I got an output (the actual type of the printed result in the output is a dictionary, hence the brackets):
Anyone have some advice? This is extraordinarily frustrating to me because I'm following the exact format of the first case with get_platform_and_os.py but then with verify_show_commands.py, it just doesn't read anything.
As a side note, if this information helps, when I run the command manually in the terminal, it takes roughly 2-3 seconds to complete. However, running it in my project takes much less than a second before it errors out.
So...
Using Quotes within getRuntime().exec
Apparently this is a thing. I just made every word in the command an array element instead, and inside the array, "show bgp scale" was entered without the quotes. After that, it worked.

Send some input to a Terminal window using Java on Mac OS

I can get a terminal window or command prompt to open on either Mac OS or Windows. I want to send a string to that terminal or cmd window using my java.
String in = " -i " + "\"" + tfIntdta.getText() + "\"";
String rst = " - r " + "\"" + tfRstplt.getText() + "\"";
String out = " -o " + "\"" + tfOutdta.getText() + "\"";
String strip = " -s" + "\"" + tfStpdta.getText() + "\"";
String guistring = "-n gui";
String wd = "\"" + System.getProperty("user.dir");
String osver = System.getProperty("os.name");
String app = "";
if (osver.contains("Mac")){
app = wd + "/relap5.x\"";
} else if (osver.contains("Windows")){
app = "\\relap5.exe";
} else if (osver.contains("linux")) {
app = "/relap5.x";
}
String run = app + in + rst + out;
So the string would look something like this.
"/Users/brianallison/Documents/Java/RELAP5 GUI/issrs/relap5.x" -i "" - r "" -o ""
I want the line above to appear on the terminal or cmd window and execute.
Put your command and parameters in an array:
String[] command = {
"/Users/brianallison/Documents/Java/RELAP5 GUI/issrs/relap5.x",
"-i", "Choose your input file",
"-r", "",
"-o", ""
};
Then execute using Runtime#exec(String[] cmdarray):
Runtime.getRuntime().exec(command);
This answer has been put together after reading your other two questions from today, here and here.

How to find last line in a mapreduce job

I am processing a .csvfile. I would like to print only my first and last lines. I have accomplished this using normal Java code but, I did not find any Inputformatwhich will read the lines and find first and last line. My Java code is as as below.
public class CSVToJSON {
public static void main(String[] args) throws ParseException, ClassNotFoundException, FileNotFoundException {
File file = new File("/../Desktop/ABCD.txt");
try {
BufferedReader csvFile = new BufferedReader(new FileReader("/../Desktop/.csv"));
BufferedWriter jsonFile = new BufferedWriter(new FileWriter(file));
InputStream inputStream = new ByteArrayInputStream(jsonNew.getBytes(StandardCharsets.UTF_8));
jsonFile.write(jsonNew);
jsonFile.newLine();
String next, fileContent = csvFile.readLine();
for (boolean first = true, last = (fileContent == null); !last; first = false, fileContent = next)
{
last = ((next = csvFile.readLine()) == null);
if (first)
{
String[] tab = fileContent.split(",");
String line = "[" + tab[2] + "," + tab[3] + "," + tab[8] + "," + tab[11] + "," + tab[15] + "," + tab[16] + "],";
InputStream inputStreamNew = new ByteArrayInputStream(line.getBytes(StandardCharsets.UTF_8));
jsonFile.write(line);
jsonFile.newLine();
}else if (last) {
String[] tab = fileContent.split(",");
String lineLast = "[" + tab[2] + "," + tab[3] + "," + tab[8] + "," + tab[11] + "," + tab[15] + "," + tab[16] + "]" + "\n" + "];
InputStream inputStreamNewLine = new ByteArrayInputStream(lineLast.getBytes(StandardCharsets.UTF_8));
jsonFile.write(lineLast);
jsonFile.newLine();
}else {
String[] tab = fileContent.split(",");
String line = "[" + tab[2] + "," + tab[3] + "," + tab[8] + "," + tab[11] + "," + tab[15] + "," + tab[16] + "],";
inputStream inputStreamNormalLine = new ByteArrayInputStream(line.getBytes(StandardCharsets.UTF_8));
jsonFile.write(line);
jsonFile.newLine();
}
}
csvFile.close();
jsonFile.close();
} catch (FileNotFoundException e) {
Logger.getLogger(CSVToJSON.class.getName()).log(Level.SEVERE, null, e);
} catch (IOException e) {
Logger.getLogger(CSVToJSON.class.getName()).log(Level.SEVERE, null, e);
}

Using wkhtmltopdf with JBoss form based authentication

I am trying to use wkhtml2pdf in JBoss with Java to create PDF files. I was successful, but it only creates a PDF file from my login-page, rather than from the jsp file.
I read that it is possible to add parameters like username or password, and this is what I did:
String command = applicationLocation + "wkhtmltopdf.exe " + "--post j_username=" + username +" --post j_password=" + password + " " + reqURL + "?" + reqQuery + " c:/PDF/" + folderName + "/" + id + "/" + folderName + ".pdf";
But that doesn't create a PDF file, not even an error output. This is how my class looks like:
public class GeneratePDF {
String logUserId = "0";
public String path = "c:/PDF";
String applicationLocation = "C:\\Program Files\\wkhtmltopdf\\";
/**
* This method creates a command which calls wkhtmltopdf from Google in order to create a PDF file.
*
* #param reqURL
* #param reqQuery
* #param folderName
* #param id
*/
public void genrateCmd(String reqURL, String username, String password, String reqQuery, String folderName, String id) {
try {
// make sure c:/eGP exists
File destFoldereGP = new File("c:/eGP");
if (destFoldereGP.exists() == false) {
destFoldereGP.mkdirs();
System.out.println("successfully created c:/eGP");
}
// make sure c:/PDF exists
File destFolderPDF = new File("c:/PDF/");
if (destFolderPDF.exists() == false) {
destFolderPDF.mkdirs();
System.out.println("successfully created c:/PDF");
}
// make sure c:/PDF/foldername exists
File destFolder = new File("c:/PDF/" + folderName);
if (destFolder.exists() == false) {
destFolder.mkdirs();
System.out.println("successfully created c:/PDF/foldername");
}
// make sure c:/PDF/foldername/id exists
File destFolder2 = new File("c:/PDF/" + folderName + "/" + id);
if (destFolder2.exists() == false) {
destFolder2.mkdirs();
System.out.println("successfully created c:/PDF/foldername/id");
}
//For Image change 'wkhtmltopdf.exe' to 'wkhtmltoimage.exe' and '.pdf' to '.jpeg'
String command = applicationLocation + "wkhtmltopdf.exe " + "--post j_username=" + username +" --post j_password=" + password + " " + reqURL + "?" + reqQuery + " c:/PDF/" + folderName + "/" + id + "/" + folderName + ".pdf";
System.out.println("Command to create PDF: " + command);
Runtime.getRuntime().exec(command);
System.out.println("Successfully created a new PDF file.");
} catch (IOException e1) {
System.out.println("Exception: " + e1);
} catch (Exception e) {
System.out.println("Exception: " + e);
}
}
}
Any idea how to create PDFs with wkhtml2pdf and form based authentication in JBoss?
Thanks a lot.

Categories

Resources