Run Scala REPL via Java ProcessBuilder - java

For research reasons I want to be able to call the Scala REPL in my Java code. To do so I use Java's ProcessBuilder and call the command scala. Although the code nicely returns the welcome message of the scala REPL, the statements that I sent to it do not return any output or errors.
Note that my use of processbuilder is correct, I tested it on other commands and it works. It is specifically Scala that is not giving me any output or errors.
Why isn't Scala giving me any output? Is there a way to make it work?
Here is the short compilable version of my code:
public class CommandEvaluator {
public static void main(String args[]) throws IOException
{
ProcessBuilder pb = new ProcessBuilder("scala.bat");
Process proc = pb.start();
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERR");
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUT");
// kick them off
errorGobbler.start();
outputGobbler.start();
OutputStream outStream = proc.getOutputStream();
PrintWriter pWriter = new PrintWriter(outStream);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true) { // REPL
System.out.print("> ");
String stat = br.readLine();
pWriter.println(stat);
pWriter.flush();
}
}
private static class StreamGobbler extends Thread
{
private String type;
private BufferedReader br;
StreamGobbler(InputStream is, String type)
{
this.type = type;
InputStreamReader isr = new InputStreamReader(is);
br = new BufferedReader(isr);
}
#Override
public void run()
{
try
{
String line = null;
while ((line = br.readLine()) != null)
System.out.println(type + ">" + line);
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
}

Related

Execute Java Program From Java Code using Process

I am trying to execute a java code by using Process class.
Here is my code.
Class file which is trying to execute is.
class Demo{
public static void main(String[] args) {
System.out.println("Hello World");
}
}
class Pro {
public static void main(String[] args) {
try {
ProcessBuilder builder = new ProcessBuilder("java Demo");
builder.redirectErrorStream(true);
Process process = builder.start();
InputStream is = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Both classes are in different file and in the same folder.
O/P
java.io.IOException: Cannot run program "java Demo": CreateProcess error=2, The system cannot find the file specified
at java.base/java.lang.ProcessBuilder.start(Unknown Source)
at java.base/java.lang.ProcessBuilder.start(Unknown Source)
at GFG.main(GFG.java:13)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.base/java.lang.ProcessImpl.create(Native Method)
at java.base/java.lang.ProcessImpl.<init>(Unknown Source)
at java.base/java.lang.ProcessImpl.start(Unknown Source)
... 3 more
Try like this:
private static final String LOCATION = "D:\\test.java";
public static void main(String args[]) throws InterruptedException,IOException{
ProcessBuilder processBuilder = new ProcessBuilder(command);
List<String> command = new ArrayList<String>();
command.add("javac"); //or command.add("javac -jar")
command.add(LOCATION);
ProcessBuilder builder = new ProcessBuilder(command);
Map<String, String> environ = builder.environment();
final Process process = builder.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("Program terminated!");
}
}
Hope this helps,
Addendum (how to wait for process):
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
calling:
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String domainName = "https://wwww.google.com";
//in mac oxs
String command = "ping -c 3 " + domainName;
//in windows
//String command = "ping -n 3 " + domainName;
String output = obj.executeCommand(command);
System.out.println(output);
}
This is an example to ping some page, 3 times and wait for response.

Getting output in command prompt instead of WordPad

I am new to creating batch files. I followed a tutorial and wrote a program to redirect the output of an echo programs's simple Java version into the file test.txt. I am supposed to get output as:
E:\classes\com\javaworld\jpitfalls\article2>java GoodWinRedirect test.txt (Tutorials's example)
OUTPUT>'Hello World'
ExitValue: 0
Instead, when i type
C:\Users\attsuap1\Desktop\JavaCallingBatchFile2\src>GoodwinRedirect.java test.txt in my command prompt, a WordPad page opens, showing the codes that is in the java class.
If i type
C:\Users\attsuap1\Desktop\JavaCallingBatchFile2\src>java GoodWinRedirect test.txt,
I get the error:
Error: Could not find or load main class GoodWinRedirect
These are the codes:
GoodWinRedirect.java
import java.util.*;
import java.io.*;
class StreamGobbler extends Thread {
InputStream is;
String type;
OutputStream os;
StreamGobbler(InputStream is, String type) {
this(is, type, null);
}
StreamGobbler(InputStream is, String type, OutputStream redirect) {
this.is = is;
this.type = type;
this.os = redirect;
}
public void run() {
try {
PrintWriter pw = null;
if (os != null)
pw = new PrintWriter(os);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (pw != null)
pw.println(line);
System.out.println(type + ">" + line);
}
if (pw != null)
pw.flush();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
public class GoodWinRedirect {
public static void main(String args[]) {
if (args.length < 1) {
System.out.println("USAGE java GoodWinRedirect <outputfile>");
System.exit(1);
}
try {
FileOutputStream fos = new FileOutputStream(args[0]);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("java jecho 'Hello World'");
// any error message?
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");
// any output?
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT", fos);
// kick them off
errorGobbler.start();
outputGobbler.start();
// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
fos.flush();
fos.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
How do i get the output as OUTPUT>'Hello World' ExitValue: 0 in the command prompt? Someone please help me. Thank you so much in advance.

Writing to InputStream of a Java Process

I have a code that starts a java process (i.e.: executing a compiled java code) via
ProcessBuilder builder = new ProcessBuilder("java", "Sample", "arg1", "arg2");
builder.redirectErrorStream(true);
Process process = builder.start();
Through this, I can basically process the output and errors
OutputStream stdin = process.getOutputStream(); // <- Eh?
InputStream stdout = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
// reader.readLine() blah blah
Now, how can I send input to the stdin? That is, if the code executed by the process has a line that waits for an input as in:
Scanner scan = new Scanner(System.in);
String val = scan.nextLine();
System.out.println(val);
I tried this:
writer.write("I'm from the stdin!.");
writer.flush();
Though nothing happened. The console still waited for an input.
Any thoughts?
EDIT: The question was answered, as accepted below. I'm editing to show the faulty code (which I failed to include btw. Lol).
Before the writer.write() part, I had a
String line;
line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
The Process OutputStream (our point of view) is the STDIN from the process point of view
OutputStream stdin = process.getOutputStream(); // write to this
So what you have should be correct.
My driver (apply your own best practices with try-with-resources statements)
public class ProcessWriter {
public static void main(String[] args) throws Exception {
ProcessBuilder builder = new ProcessBuilder("java", "Test");
builder.directory(new File("C:\\Users\\sotirios.delimanolis\\Downloads"));
Process process = builder.start();
OutputStream stdin = process.getOutputStream(); // <- Eh?
InputStream stdout = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
writer.write("Sup buddy");
writer.flush();
writer.close();
Scanner scanner = new Scanner(stdout);
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
}
My application
public class Test {
public static void main(String[] args) throws Exception {
Scanner console = new Scanner(System.in);
System.out.println("heello World");
while(console.hasNextLine()) {
System.out.println(console.nextLine());
}
}
}
Running the driver prints
heello World
Sup buddy
For some reason I need the close(). The flush() alone won't do it.
Edit It also works if instead of the close() you provide a \n.
So with
writer.write("Sup buddy");
writer.write("\n");
writer.write("this is more\n");
writer.flush();
the driver prints
heello World
Sup buddy
this is more
This is an example which maybe can helps someone
import java.io.IOException;
import java.io.File;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
String[] commands = {"C:/windows/system32/cmd.exe"};
ProcessBuilder builder = new ProcessBuilder(commands);
builder.directory(new File("C:/windows/system32"));
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
InputStream stderr = process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));
BufferedReader error = new BufferedReader(new InputStreamReader(stderr));
new Thread(() -> {
String read;
try {
while ((read = reader.readLine()) != null) {
System.out.println(read);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
String read;
try {
while ((read = error.readLine()) != null) {
System.out.println(read);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
while (true) {
try {
Scanner scanner = new Scanner(System.in);
writer.write(scanner.nextLine());
writer.newLine();
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}

how to run a java executable jar in another java program

I know this question has been asked before but those answers didn't provide me an answer.
I want to execute a exec jar file in my java program and get the output from executing jar into a string. Here below are the codes I have used so far without success.
cmdlink = "java -jar iwtest-mac.jar"+" "+cmd;
System.out.println(cmdlink);
Process process = Runtime.getRuntime().exec(cmdlink);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((reader.readLine()) != null) {
st = reader.readLine();
}
process.waitFor();
and another code I have tried is as follows:
String cmdlink = "iwtest-mac.jar "+cmd;
ProcessBuilder pb = new ProcessBuilder("java", "-jar", cmdlink); //cmd here is a string that contains inline arguments for jar.
pb.redirectErrorStream(true);
pb.directory(new File("C:\\Users\\Dharma"));
System.out.println("Directory: " + pb.directory().getAbsolutePath());
Process p = pb.start();
InputStream is = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
for (String line = br.readLine(); line != null; line = br.readLine()) {
System.out.println( line );
p.waitFor();
Both of the above are not working for me. Any suggestions are appreciated.
This works For Me..
public class JarRunner {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "C:\\JCcc.jar");
pb.directory(new File("C:\\"));
try {
Process p = pb.start();
LogStreamReader lsr = new LogStreamReader(p.getInputStream());
Thread thread = new Thread(lsr, "LogStreamReader");
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class LogStreamReader implements Runnable {
private BufferedReader reader;
public LogStreamReader(InputStream is) {
this.reader = new BufferedReader(new InputStreamReader(is));
}
public void run() {
try {
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is what the Docs says-
ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
You can pass any number of arguments in constructor.
Read more about process builder here.

Java program hangs when trying to invoke powershell script

I'm building a GUI with NetBeans, and one of the buttons in the GUI requires the use of a powershell script. I'm trying to get the script's output and put it into a JTextArea within the GUI. Here is what I have so far. I did a bit of debugging, and it seems to hang inside the while loop, but I'm confused as to why it's doing so.
private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("cmd powershell C:/hello1.ps1");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null) {
outputTextArea.setText(line);
}
reader.close();
proc.getOutputStream().close();
} catch (IOException ex) {
Logger.getLogger(BatchFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
And here is a simple powershell script I'm trying to get it to work with.
#Filename: hello1.ps1
Write-Host "Hello World!"
#End of Script
I did some researched, and I noticed that it was hanging for other people to, but only because they forgot to close the processes output stream.
I was having the same issue. I moved the proc.getOutputStream().close() before the while loop and everything worked
private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {
String allOutput = "";
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("cmd /c powershell C:/hello1.ps1");
BufferedReader errorReader = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
BufferedReader outReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while ((line = errorReader.readLine()) != null) {
allOutput += "\n" + line;
}
while ((line = outReader.readLine()) != null) {
allOutput += "\n" + line;
}
int retVal = proc.waitFor();
} catch (IOException ex) {
Logger.getLogger(BatchFrame.class.getName()).log(Level.SEVERE, null, ex);
}
outputTextArea.setText(allOutput);
}
Form the command line properly with CMD.EXE /c
Check the ErrorStream
Use Process.waitFor() read the java-docs for the Process class.
No need to close the OutputStream since you never use it and the program shouldn't expect user input (java switching the names of input and output is annoying)
NOTE the code above isn't tested, so there may be syntax errors etc etc.
Here is my tested code, note the choice to "hack" or close STDIN when done.
package test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Test
{
private static boolean hack=false;
public static void main(String[] args) throws IOException
{
Runtime rt = Runtime.getRuntime();
String cmd[];
if (hack)
cmd=new String[]{"cmd","/c","C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe","-File","c:\\cygwin\\home\\jpyeron\\test.ps1", "<NUL"};
else
cmd=new String[]{"C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe","-File","c:\\cygwin\\home\\jpyeron\\test.ps1"};
final Process p = rt.exec(cmd);
Thread stdout = new Thread()
{
public void run()
{
InputStream out = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(out));
String line = null;
try
{
while ((line = in.readLine()) != null)
{
System.out.println(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
};
};
stdout.start();
Thread stderr = new Thread()
{
public void run()
{
InputStream err = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(err));
String line = null;
try
{
while ((line = in.readLine()) != null)
{
System.out.println(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
};
};
stderr.start();
if (hack)
;
else
p.getOutputStream().close();
}
}
This helped me: Do not read the InputStream if there are no errors.
e.g.
private void takeAction () throws IOException, InterruptedException
{
String action = getAction (); // A powershell-Command
Process p = Runtime.getRuntime ().exec ( action );
InputStream is = p.getErrorStream ();
if ( 0 < is.available () )
{
BufferedReader br = new BufferedReader (
new InputStreamReader ( is ) );
String err = br.readLine ();
while ( null != err )
{
System.out.println ( "takeAction() " + err );
err = br.readLine ();
}
p.getOutputStream ().close ();
}
}

Categories