I am using JavaCompiler
of javax.tools
to compile some java code and I am trying to use wildcard in my classpath
in order to include all the .jar
files but I fail.
Here is my code:
String classpath = "C:\tomcat6\webapps\myapp/WEB-INF/lib/javax.ws.rs-api-2.0-m10.jar;"
+ "C:\\tomcat6\\webapps\\myapp/WEB-INF/lib/javax.persistence-2.1.0.jar";
Iterable<String> options = Arrays.asList("-d", classesBaseDir,
"-classpath", classpath);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager,
diagnostics, options, null, file);
boolean result = task.call();
The code above works just fine. But when I am trying to change the classpath
to
String classpath = "C:\\tomcat6\\webapps\\myapp/WEB-INF/lib/*";
it fails with
compiler.err.doesnt.exist|package javax.ws.rs does not exist
...
symbol: class GET
location: class com.my.oasis.resources.TestClass
09/04/2014 14:27:09:030 | COMPILER_DIAGNOSTIC | compileResource() - compiler.err.cant.resolve.location|cannot find symbol
...
I have also tried the following alterations
String classpath = "\"C:\\tomcat6\\webapps\\myapp/WEB-INF/lib/*\"";
String classpath = "'C:\\tomcat6\\webapps\\myapp/WEB-INF/lib/*'";
but none of them worked. Any ideas?
Thanks
Note: the reason why the path includes slashes and backslashes is because the my program identifies the environment in runtime and auto completes the path.
Edit: I am using tomcat 6 and java 1.7.0_21
Using backslashes or slashes makes no difference. But you obviously assume that the path is auto-globbed (like a normal command line would). This does not happen. So you run your compiler as you would with a command line arg of
which is not what you want. You may look into the API docs for
java.io.File.listFiles(FileFilter)
or evenjava.nio.file.Files.walkFileTree(Path, FileVisitor)
to gain a better understanding.To expand a bit on that, when your shell sees C:\tomcat6\webapps\myapp/WEB-INF/lib/* it expands it into a space-separated list of whatever is in your
WEB-INF/lib
directory. This is called globbing, or since it's done automatically, auto-globbing.Now Java doesn't do that, but you can build it yourself in a few lines of code:
Since Java1.7 you can also use
Files.newDirectoryStream(Path)
instead oflist(File)
. With 1.8 you could even calljoin
instead of joining manually.Wildcards: Since Java 1.6 wildcards are supported when using java/javaw/javac, more information: Windows/Solaris and Linux
example:
This uses all .jar files (not .class!) in the lib directory as classpath. This should not be confused with the *-expansion of your shell.
-cp lib/*
gets expanded to-cp lib/a.jar lib/b.jar
which is not valid argument syntax. In order to avoid this you have to add quotation marks:-cp "lib/*"
The cause of your Problem: You are trying to call the Java compiler from source directly with its Java API. This source code does not contain the wildcard expansion. The JDK ships with a wrapper binary (javac,javadoc,javah,javap are all the same binary) which does some things and finally calls the compiler task. This wrapper also expands the wildcards in your classpath and therefore the compiler task doesn't have to do this anymore (and it doesn't). See at Compiler Readme section "build -> Notes -> The launcher". Launcher sourcecode.
Solution:
javac
through a Processbuilder. (This is not recommended since it is a complicated and error prone solution for a simple problem)example code:
This function takes all classpath entries and builds one classpath. Classpath entries with a wildcard in it will get expanded.