0

First of all I have searched the forum and the web for 5 hours, but couldn't find out what my problem is so I'm hoping this isn't a duplicate.

I am using the Java ProcessBuilder to compile and run a Java Project. When I type

javac /Users/Katzenmeister/Desktop/Final/src/edu/kit/informatik/citationmanager/*.java

to my Terminal on MacOSX I can compile the whole folder without any errors.

In my Program I have the following

public class CompilerController {

private static File directory;
private static String mainClass;
private static boolean compiled = false;

public static void setDirectory(File directory) {
    CompilerController.directory = directory;
}

public static void setMainClass(String mainClass) {
    CompilerController.mainClass = mainClass;
}

private static void compile() {
    ProcessBuilder pb = new ProcessBuilder("javac",directory.getAbsolutePath()+"/*.java");
    pb.inheritIO();
    try {
        pb.start();
        compiled = true;
    } catch (IOException ex) {
        System.out.println(ex);
    }
}

private static String[] getSourcePath() {

    String[] strArr = directory.toString().split("src");

    strArr[0] += "src";
    strArr[1] += mainClass;

    return strArr;
}

private static void run() {

    ProcessBuilder pb = new ProcessBuilder("java",getSourcePath()[0],getSourcePath()[1]);
    try {
        pb.start();
    } catch(IOException ex) {
        System.out.println(ex);
    }

}

public static void compileRun() {
    compile();
    if (compiled) {
        run();
    }
}
}

In my JavaFX Controller class I get the directory by using a DirectoryChooser and passing the absolute path to the CompilerController using setDirectory().

When I run my program I get the following error:

javac: file not found: /Users/Katzenmeister/Desktop/Final/src/edu/kit/informatik/citationmanager/*.java
Usage: javac <options> <source files>
use -help for a list of possible options

Which is as far as I can tell the same thing I got working on my Terminal. I have only been coding for 6 Months now so I lack knowledge, but I'm assuming this is due to the JVM Runtime Directory probably. Any help is very welcome. Here are some of the forum links that I have already checked for reference:

ProcessBuilder can't find file?!

Run a .java file using ProcessBuilder

How to run a Java program using ProcessBuilder inside the other Java program. (with -cp and -Xbootclasspath commands)

Compile and Run Java Program from another Java Program

ProcessBuilder can't find file?!

P.S: This is my first question on the forum. I tried my best to fit the etiquette, if I have done anything wrong please tell me so I can edit my question.

EDIT: I got the code to work as follows for anyone who might have a similar problem

private static void compile() {

    ArrayList<String> files = new ArrayList<>();
    files.add("javac");
    files.add("-sourcepath");
    files.add("./*");

    try {
        for (File file : directory.listFiles()) {
            if (!file.isHidden()) {
                files.add(file.getName());
            }
        }
    } catch(NullPointerException ex) {}

    pb.directory(new File(directory.getAbsolutePath()));
    pb.command(files);
    pb.inheritIO();

    try {
        synchronized (processLock) {
            Process pr = pb.start();
            int i = pr.waitFor();
        }
        compiled = true;
    } catch (IOException ex) {
        System.out.println(ex);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
Community
  • 1
  • 1

1 Answers1

0

* is processed differently in the shell vs in ProcessBuilder: it is expanded before being passed to javac in the shell, but it is passed literally in the ProcessBuilder command.

You can see this if you add echo before the command in the shell:

echo javac /Users/whatever/*.java

will print out something like:

javac /Users/whatever/Foo.java /Users/whatever/Bar.java

When you are invoking ProcessBuilder like that, you are doing the equivalent of single-quoting the path in the shell, like this:

javac '/Users/whatever/*.java'

which suppresses glob expansion, so javac receives /Users/whatever/*.java, as you can see if you add echo to the front:

echo javac '/Users/whatever/*.java'

prints

javac /Users/whatever/*.java

You need to expand the glob yourself, e.g. use new File("/your/directory").listFiles(), and pass all the files to the ProcessBuilder explicitly.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • Thanks a lot I will be trying it right now and posting the results – Katzenmeister Apr 02 '17 at 12:36
  • I tried your suggestion and now the java files are being seen by the compiler. But now the problem is that the dependencies of these classes to each other are not being found since I am compiling each class on itself. For example the class Foo has an ArrayList and since Foo and Bar are compiled independently the compilation of Foo fails. How can I overcome this issue? – Katzenmeister Apr 02 '17 at 12:46
  • If you expect the commands to execute in the same way, they have to execute in the same environment, e.g. same environment variables, same current directory etc. – Andy Turner Apr 02 '17 at 12:51
  • The classes are all in the same folder i.e. directory and I tried declaring a global ProcessBuilder and using the command() function in a for loop to compile all classes, but this still doesn't do it. My compile function looks like this: – Katzenmeister Apr 02 '17 at 12:57
  • private static void compile() { try { for (File file : directory.listFiles()) { if (!file.isHidden()) { pb.command("javac",directory.getAbsolutePath()+"/"+file.getName()); pb.inheritIO(); try { pb.start(); compiled = true; } catch (IOException ex) { System.out.println(ex); } } } } catch(NullPointerException ex) { } } – Katzenmeister Apr 02 '17 at 12:58
  • Please re-read my previous comment: "they have to execute in the same environment, e.g. same environment variables, same current directory etc" I cannot see any evidence of you ensuring either of those. – Andy Turner Apr 02 '17 at 12:59