以编程方式在存储在任意子文件夹中的包中编译Java类

时间:2010-02-03 13:15:10

标签: java java-compiler-api

我希望用Java编译一个应用程序,它由一定数量的包中的各种java类组成。在命令行中,我可以切换到包含根软件包的文件夹并输入:

javac rootpackage/subpackage/*.java

javac rootpackage/*/*.java

编译我的rootpackage的所有主要子包中的所有java类。

但是我希望能够在Java应用程序中执行此操作。 (我们的想法是,我们向学生提供包含单元测试的应用程序。单元测试需要针对他们的代码运行,然后应用程序创建一个包含源文件的JAR文件,这些文件已经过测试结果的“水印”。这工作正常,但我们希望确保测试的类文件是从提交的源文件创建的,因此想要以编程方式编译java源代码。)

问题在于每个学生将他们的根包存储在任意位置,我似乎无法将文件的位置传递给JavaCompiler(javax.tools)。

是否可能,如果是这样,有人可以提供一些关于如何正确编译任意放置的根包的提示。

干杯

理查德

更多信息:

学生有文件夹结构:

/home/student/work/java/myproject/

包含根包。他们启动应用程序(可能存储在此文件夹中 - 因此没有任何问题 - 但可能存储在其他地方),要求他们提供包含根包的文件夹。进入后,学生单击创建JAR按钮,编译其包中的文件,对新编译的文件运行测试,然后创建JAR。

在思考这个问题的同时,解决方案可能是告诉学生将“创建JAR”应用程序安装在包含其根包的文件夹中。

2 个答案:

答案 0 :(得分:0)

你可以看一下开头行的每个.java文件的顶部:

package com.blah.blah.assignment;

即。查找包名称的开头,然后在搜索路径中查找第一个目录(在此示例中),然后将此路径提供给JavaCompiler对象,或者我误解了您的问题?

刚刚查看了javax.tools包,为什么不为javaFilemanager创建一个复合包装器,它包装一个ForwardingjavaFileManager,它将把getFileForInput或getJavaFileForInput等方法的所有请求转发到学生源目录中的相应起始目录。 (根据您对第一个.java文件进行解析的初步位置来确定其源路径的根目录)

答案 1 :(得分:0)

JavaCompiler.getTask()的最后一个参数是一个Iterable<?扩展JavaFileObject>包含要传递给编译器的编译单元。 JavaFileObject提供的一个实现是SimpleFileJavaObject(http://java.sun.com/javase/6/docs/api/javax/tools/SimpleJavaFileObject.html)。它由java.net.URI对象构造,可以从File对象轻松创建。把它们放在一起,做这样的事情:

List<JavaFileObject> javaFiles = new ArrayList<JavaFileObject>();
File javaFile = new File(rootPackageDirFromUser, fileNameInRootDir);
URI javaURI = javaFile.toURI();
javaFiles.add(new SimpleJavaFileObject(javaURI, JavaFileObject.Kind.SOURCE));
JavaCompiler.CompilationTask task =
    ToolProvider.getSystemJavaCompiler().getTask(..., javaFiles);

其中rootPackageDirFromUser由用户提供,用户告诉他们存储文件的位置,fileNameInRootDir是该目录中java源文件的名称。如果您事先不知道文件名,则需要遍历rootPackageDirFromUser来构建列表。

我没有测试过这个,但这应该给你一般的想法。