我希望用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”应用程序安装在包含其根包的文件夹中。
答案 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来构建列表。
我没有测试过这个,但这应该给你一般的想法。