我有一个build.xml,用于导入其他ant xml文件。我想从中获取所有javac任务,以便我可以看到为这些任务设置了什么类路径(javac用于多个目标)。我想出了以下代码(简化了一下):
public static void main(String[] args) throws Exception {
Project project = new Project();
project.init();
String build = "build.xml";
File buildFile = new File(build);
ProjectHelper.configureProject(project, buildFile);
Hashtable<String,Object>ht = project.getTargets();
for (String key : ht.keySet()) {
try {
Target target = (Target)ht.get(key);
Task[] tasks = target.getTasks();
for (Task task : tasks) {
if (task instanceof UnknownElement) {
((UnknownElement)task).maybeConfigure();
task = ((UnknownElement)task).getTask();
if (task == null) {
return;
}
}
if (task instanceof Javac) {
// here we go
}
}
} catch(Exception ignore) {}
}
}
但是,像MacroDef
这样的任务可能嵌套了其他任务。 TaskContainer
接口仅指定addTask(task)
,我认为无法检索嵌套任务。
如何检索所有javac任务?没有使用ant库的解决方案是可以的,但是XML解析似乎很麻烦,因为ant使用属性,引用,构建文件可以导入其他文件等。
答案 0 :(得分:5)
好的,为了澄清你的问题,我将重申这个问题。
如何收集所有&lt; javac&gt;的所有类路径? build.xml文件中的任务,即使其中一些可能嵌套在&lt; macrodef&gt;中定义
简单的答案是每个案例的一般答案是不可能的。其原因与计算机科学理论密切相关,涵盖了可计算性问题以及图灵机的局限性。在您的情况下,我们知道输入可以是无限的(因为ANT语言可以引用时间戳),并且输出可以是输入的反映,因此我们知道它将需要无限收集每个可能的类路径的时间。
尽管如此,你很容易推断某些类路径,甚至可能在合理(即非无限)的时间内推断出所有类路径。关键是ANT预先做了很多配置,但最终必须在运行中进行一些配置。 A&lt; javac&gt;目标中的classpath是预先配置的;因为ANT决定让所有变量都不可变。这意味着对于“典型”javac标记,您只需要一些看起来像这样的代码:
if (task instanceof Javac) {
Javac javac = (Javac)task;
Path path = javac.getClasspath();
if (path == null) {
System.out.println("javac: Path is null");
} else {
System.out.println("javac: Path is " + path.toString());
}
}
但嵌套在macrodef javac标签中需要模拟运行。实际配置不会直接保存在任务中,它将保存在类的RuntimeConfigurable
包装内。然后将在项目执行时创建Task
个节点,这意味着它们的配置将在运行中进行计算。
我将列出一些关于如何导航到macrodef Wrapper“child”元素的代码:
if (task instanceof MacroDef) {
MacroDef macroDef = (MacroDef)task;
// a Sequence element, but not really, as `unkSeq.getRealThing()` will return null
UnknownElement unkSeq = macroDef.getNestedTask();
// Make sure we are dealing with the wrapper, or we won't get very far
RuntimeConfigurable wrapper = unkSeq.getWrapper();
// Wrappers can be configured too.
wrapper.maybeConfigure(project, true);
Enumeration enumeration = wrapper.getChildren();
while (enumeration.hasMoreElements()) {
// children of the wrapper
RuntimeConfigurable child = (RuntimeConfigurable) enumeration.nextElement();
UnknownElement unkchild = (UnknownElement)child.getProxy();
// you can use this to print the name
System.out.println("child(wrapper): " + unkchild.getTaskName());
// this will be null, as the macro hasn't "executed"
System.out.println("child(real): " + unkchild.getRealThing());
}
}
由于实际调用的javac
任务在macrodef pre-runtime中不存在,因此在执行之前的所有情况下都不可能真正“知道”它的类路径。是的,你可以做一些花哨的代码来模拟运行,跟踪瞬态ANT属性,但你永远不能“证明”这样的代码与运行相同,除非你正在处理属性的子集(即那些保证的属性) 总是在所有运行之间具有相同的值。
我希望我在回答你的问题时没有错过标记,如果我这样做,希望这方面的内容对你解决问题有用。但请放心,有 no 解决方案可以打印每个可能的 build.xml文件的类路径,其中javac任务嵌入在macrodef调用中。
---原帖如下--- 要真正捕获macrodef的内容,您需要捕获引用macrodef的任务,然后捕获macrodef,然后查看macrodef中的元素(请记住它们也可能是宏)。