ldx*_*ldx 6 java xml ant parsing build
我有一个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) {}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,有些任务MacroDef可能嵌套了其他任务.该TaskContainer接口只指定了addTask(task),我看不出有什么方法来检索嵌套任务.
如何检索所有javac任务?没有使用ant库的解决方案是可以的,但是XML解析似乎很麻烦,因为ant使用属性,引用,构建文件可以导入其他文件等.
好的,为了澄清你的问题,我将重申这个问题.
如何收集build.xml文件中所有<javac>任务的所有类路径,即使其中一些可能嵌套在<macrodef>定义中?
简单的答案是每个案例的一般答案是不可能的.其原因与计算机科学理论密切相关,涵盖了可计算性问题以及图灵机的局限性.在您的情况下,我们知道输入可以是无限的(因为ANT语言可以引用时间戳),并且输出可以是输入的反映,因此我们知道收集每一个可能需要无限的时间类路径.
也就是说,你很容易推断出一些类路径,甚至可能在合理的(即非无限的)时间内推断出所有的类路径.关键是ANT预先做了很多配置,但最终必须在运行中进行一些配置.目标中的<javac>类路径是预先配置的; 因为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());
}
}
Run Code Online (Sandbox Code Playgroud)
但嵌套在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());
}
}
Run Code Online (Sandbox Code Playgroud)
由于实际调用的javac任务在macrodef pre-runtime中不存在,因此在执行之前的所有情况下都不可能真正"知道"它的类路径.是的,你可以做一些花哨的代码来模拟运行,跟踪瞬态ANT属性,但你永远不能"证明"这样的代码与运行相同,除非你正在处理属性的子集(即那些保证的属性)要始终有之间的相同值的所有运行).
我希望我在回答你的问题时没有错过标记,如果我这样做,希望这对你的问题的解决方案有用.但请放心,没有解决方案为每个可能的 build.xml文件打印出类路径,其中javac任务嵌入在macrodef调用中.
---原帖如下 - 要真正捕获macrodef的内容,你需要捕获引用macrodef的任务,然后捕获macrodef,然后查看macrodef中的元素(请记住,它们也可能是宏).