ProcessBuilder command argument - java

(Sorry for my english I'm french) I'm creating a tiny Java IDE for my school project, but I'm facing a problem with running classes under Linux (I'm using Debian 7.3), no problem with Win 8.1
I'm using ProcessBuilder class to execute the java bin with some arguments, wich are args and projectOut
args = the class we want to run
projectOut = the absolute project path+"/out"
package com.esgi.honeycode;
import java.io.*;
import java.util.Scanner;
public class CustomRun {
public static void run(String args, final String projectOut) throws IOException {
System.out.flush();
if (args != null && projectOut != null) {
//SEPARATOR is a const for the file separator
ProcessBuilder builder = new ProcessBuilder("java", "-classpath", "\"" + System.getProperty("java.class.path") + System.getProperty("path.separator") + projectOut + PropertiesShared.SEPARATOR + "out\"", args);
System.out.println(builder.command());
builder.redirectErrorStream(true);
final Process process = builder.start();
Thread outThread = new Thread()
{
#Override
public void run() {
try {
String line;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
};
Thread inThread = new Thread() {
#Override
public void run() {
Scanner s = new Scanner(System.in);
//Need to control in before !!
while (true) {
String input = s.nextLine();
try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(process.getOutputStream()))) {
pw.write(input);
pw.flush();
}
}
}
};
outThread.start();
inThread.start();
}
}
}
Testing with a simple class :
public class MyClass{
public static void main(String[] args)
{
System.out.println("TESTESTE");
}
}
the class is stored in : /home/m3te0r/HoneyCodeProjects/untitledaaa/out
And if I try to run the class, I get this output, with the command print :
[java, -classpath, "/home/m3te0r/Bureau/HoneyCode.jar:/home/m3te0r/HoneyCodeProjects/untitledaaa/out", MyClass]
Error: Could not find or load main class MyClass
Like I said, there is no problem under Win 8.1 and it also works when I run the same command in a terminal.
EDIT FOR THE ANSWER ():
Ok, so I figured out what was wrong.
I just removed the escaped double quotes fot the classpath and it worked.
I was thinking there would be a problem with spaced dir names or files, but there is not.
ProcessBuilder builder = new ProcessBuilder("java", "-classpath", System.getProperty("java.class.path") + System.getProperty("path.separator") + projectOut + PropertiesShared.SEPARATOR + "out", args);

Related

How to open/run java program using cmd in another java program

I want compile Java program by making a Javac command in cmd using another Java program, then run it. How do I do that? Is there a class that i can use?
for example here is the cmd
C:\Users\UserName\Documents> Javac HelloWorld.java
How can i compile HelloWorld.java inside a java program, then run it.
Here is my initial source code wherein there is a directory and a Java file.
public class Test {
public static void main(String[] args) {
String directory = "C:\\Users\\UserName\\Documents";
String fileName = "HelloWorld.java";
}
}
Try this
try {
// Execute command
String command = "cmd /c start cmd.exe";
Process child = Runtime.getRuntime().exec(command);
// Get output stream to write from it
OutputStream out = child.getOutputStream();
out.write("<execute the java class by mentioning the usual command>");
out.flush();
out.close();
} catch (IOException e) {
}
You probably want to compile the other source code first. The Java compiler is actually written in Java itself. You do not need to invoke the javac.exe, instead take a look at javax.tools.ToolProvider.getSystemJavaCompiler() ToolProvider Javadoc.
Once you compiled the source code file with that, you can use the class loader to load the compiler class file and invoke the code from there, probably by means of reflection.
Overall you are asking for an advanced use case.
if you want to compile different java files using this a program , you can try this method.
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
try {
runProcess("javac YourDir/HelloWorld.java");
runProcess("java YourDir.HelloWorld");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class HelloWorld {
public static void main(String[] args) {
System.out.println("ok");
}
}

How to Stop a Running a Program Using Other Java Program

I have been implementing a program to compile and run other applications. I was wondering if there is a way to terminate a program when my application discovers that there is an issue e.g. infinite loop. I tried to using process.Destroy() but it kills the CMD not that actual program that has infinite loop...
Your help is really appreciated.
Here is a part of my code:
synchronized (pro) {
pro.wait(30000);
}
try{
pro.exitValue();
}catch (IllegalThreadStateException ex)
{
pro.destroy();
timeLimitExceededflag = true;
System.out.println("NOT FINISHED123");
System.exit(0);
}
}
Basically I am making my application to invoke the cmd using a processBuilder. This code terminates the CMD but if it runs a program that has an infinite loop that application will be still running which affects my servers performance.
I'd suggest to use the following solution:
start your program with a title specified
get PID of the process using "tasklist" command. A CSV parser required. There are tons of available I believe, like org.apache.commons.csv.CSVParser etc :)
kill the process by "taskkill" command using PID.
Here is some part of code which may be useful:
public static final String NL = System.getProperty("line.separator", "\n");
public <T extends Appendable> int command(String... cmd) throws Exception {
return command(null, cmd);
}
public <T extends Appendable> int command(T out, String... cmd) throws Exception {
try {
final ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
final Process proc = pb.start();
final BufferedReader rd = new BufferedReader(new InputStreamReader(proc.getInputStream()));
for (;;) {
final String line = rd.readLine();
if (line == null) {
break;
}
if (out != null) {
out.append(line);
out.append(NL);
}
}
return proc.waitFor();
} catch (InterruptedException e) {
throw new IOException(e);
}
}
public void startProcessWithTitle(String pathToExe, String title) throws Exception {
command("cmd.exe", "/C", "start", '"' + pathToExe + '"', '"' + title + '"', ..cmd.params..);
}
public int findProcessByTitle(String title) throws Exception {
final StringBuilder list = new StringBuilder();
if (command(list, "tasklist", "/V", "/FO", "csv") != 0) {
throw new RuntimeException("Cannot get tasklist. " + list.toString());
}
final CSVReader csv = new CSVReader(new StringReader(list.toString()), ',', true, "WindowsOS.findProcessByTitle");
csv.readHeaders(true); // headers
int pidIndex = csv.getHeaderIndex("PID");
int titleIndex = csv.getHeaderIndex("Window Title");
while (csv.nextLine()) {
final String ttl = csv.getString(titleIndex, true);
if (ttl.contains(title)) {
return csv.getInt(pidIndex);
}
}
Utils.close(csv);
return -1;
}
public boolean killProcess(int pid) throws Exception {
return command("taskkill", "/T", "/F", "/PID", Integer.toString(pid)) == 0;
}

Java run another class and control its I/O [duplicate]

I have a Main.java and Test.java classes that I want to compile and run Main.java in Test.java code. Here is my code
Process pro1 = Runtime.getRuntime().exec("javac Main.java");
pro1.waitFor();
Process pro2 = Runtime.getRuntime().exec("java Main");
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
I just print "ok" in Main.java but this code doesn't print anything. What is the problem ?
I have modified the code to include some checks:
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
try {
runProcess("javac Main.java");
runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the Main.java:
public class Main {
public static void main(String[] args) {
System.out.println("ok");
}
}
When everything is fine, it just works:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java exitValue() 0
java Main stdout: ok
java Main exitValue() 0
Now, for example, if I have some error in Main.java:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java stderr: Main.java:3: package Systems does not exist
javac Main.java stderr: Systems.out.println("ok");
javac Main.java stderr: ^
javac Main.java stderr: 1 error
javac Main.java exitValue() 1
java Main stdout: ok
java Main exitValue() 0
It still prints "ok" because the previously compiled Main.class is still there, but at least you can see what exactly is happening when your processes are running.
You also need to
pro2.waitFor();
because executing that process will take some time and you can't take the exitValue() before the process has finished.
I have added the condition in Laj class main function to check for compilation process has completed successfully or not..
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static int runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
// System.out.println(command + " exitValue() " + pro.exitValue());
return pro.exitValue();
}
public static void main(String[] args) {
try {
int k = runProcess("javac Main.java");
if (k==0)
k=runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Reading output from java.lang.Process - There is nothing to read

I'm trying to execute terminal command in linux trough Java and i cant get any input from inputStream.
This is my code
ProcessBuilder build = new ProcessBuilder("/usr/bin/xterm", "find /home");
Process pr = null;
BufferedReader buf;
try {
build.redirectErrorStream(true);
pr = build.start();
buf = new BufferedReader(new InputStreamReader( pr.getInputStream()));
String line = buf.readLine();
pr.waitFor();
while (true) {
System.out.println(line + "sadasdas");
line = buf.readLine();
}
} catch (Exception e) {
e.printStackTrace();
}
Process is executed and immediately terminal closes, and no output is catched and printed. On the other hand if i will compose an unknown command i get all the lines with tips how to use commands. Same problem i had with windows cmd. I was trying to use getRuntime.exec(cmd) method but the end is the same.
I've also tried to created separate threads for process and reader which looks like this
public class kurdee
{
public static Thread thread;
public kurdee()
{
List cmd = new LinkedList();
cmd.add(new String("/usr/bin/xterm"));
cmd.add(new String("find"));
thisProc thispr = new thisProc(cmd);
this.thread = new Thread(thispr);
thread.start();
reader rd = new reader(thispr.proc);
Thread thread1 = new Thread(rd);
thread1.start();}
public static void main(String args[])
{
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
kurdee kurd = new kurdee();
}
});
}
}
class reader implements Runnable
{
private BufferedReader buf;
private Process proc;
public reader(Process proc)
{
this.proc=proc;
this.buf = new BufferedReader(new InputStreamReader(proc.getInputStream()));
}
public void run()
{
String line="";
System.out.println("Thread is alive");
try{
//Thread.sleep(1000);
line = buf.readLine();
}catch(Exception ex){System.out.println(ex + " before first while started");}
while(kurdee.thread.isAlive())
{
System.out.println("Thread is alive");
while(line!=null)
{
try{
//System.out.println(proc.exitValue());
System.out.println(line + " asd");
line=buf.readLine();
}catch(Exception e){System.out.println(e + " Inner while loop");}
}
}
}
}
class thisProc implements Runnable
{
private ProcessBuilder build;
public static Process proc=null;
public thisProc(List<String> args)
{
this.build = new ProcessBuilder(args);
build.redirectErrorStream(true);
try{
this.proc = build.start();
}catch(Exception ex){System.out.println(ex + " proc class");}
}
public void run()
{
try{
proc.waitFor();
}catch(Exception ex){System.out.println(ex + " proc class");}
}
}
But with any combination of invoking threads etc i make there is still nothing to read.
I'm trying to use command "find /home -xdev -samefile file" to get all hard links to file so maybe there is an easier way.
xterm is not the way to execute processes in unix, it is not a shell. a shell is something like "/bin/sh". however, "find" is a normal unix executable, so you should just execute that directly, e.g. new ProcessBuilder("find", "/home"). and yes, you should always process the streams on separate threads, as recommended by this article.
First, don't try to execute the command with xterm, that's pointless; just do it directly. Secondly, be careful when you compose your array of command strings to put one word into each string; passing, for example "find /home" as a single string among many to ProcessBuilder is going to error out.

how to compile & run java program in another java program?

I have a Main.java and Test.java classes that I want to compile and run Main.java in Test.java code. Here is my code
Process pro1 = Runtime.getRuntime().exec("javac Main.java");
pro1.waitFor();
Process pro2 = Runtime.getRuntime().exec("java Main");
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
I just print "ok" in Main.java but this code doesn't print anything. What is the problem ?
I have modified the code to include some checks:
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
public static void main(String[] args) {
try {
runProcess("javac Main.java");
runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the Main.java:
public class Main {
public static void main(String[] args) {
System.out.println("ok");
}
}
When everything is fine, it just works:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java exitValue() 0
java Main stdout: ok
java Main exitValue() 0
Now, for example, if I have some error in Main.java:
alqualos#ubuntu:~/tmp$ java Laj
javac Main.java stderr: Main.java:3: package Systems does not exist
javac Main.java stderr: Systems.out.println("ok");
javac Main.java stderr: ^
javac Main.java stderr: 1 error
javac Main.java exitValue() 1
java Main stdout: ok
java Main exitValue() 0
It still prints "ok" because the previously compiled Main.class is still there, but at least you can see what exactly is happening when your processes are running.
You also need to
pro2.waitFor();
because executing that process will take some time and you can't take the exitValue() before the process has finished.
I have added the condition in Laj class main function to check for compilation process has completed successfully or not..
public class Laj {
private static void printLines(String name, InputStream ins) throws Exception {
String line = null;
BufferedReader in = new BufferedReader(
new InputStreamReader(ins));
while ((line = in.readLine()) != null) {
System.out.println(name + " " + line);
}
}
private static int runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
printLines(command + " stdout:", pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
// System.out.println(command + " exitValue() " + pro.exitValue());
return pro.exitValue();
}
public static void main(String[] args) {
try {
int k = runProcess("javac Main.java");
if (k==0)
k=runProcess("java Main");
} catch (Exception e) {
e.printStackTrace();
}
}
}

Categories