在Apache Ant中查找调用(或父)目标

时间:2015-01-29 15:51:55

标签: java ant

我们使用Ant来控制我们的产品创建工作流程,目标数量非常广泛。我们使用了许多build.xml文件,这些目标调用其他目标(许多目标并行运行)。

我们有一个扩展Ant BuildListener的java类,以便我们可以监听BuildEvents并将每个目标的开始和停止时间写入Oracle数据库。但是,现在我需要能够找出每个目标的父目标 - 这些信息也需要记录下来。如果我有这个:

<target name="targetA">
    <parallel>
        <antcall target="targetB"/>
        <antcall target="targetC"/>
    </parallel>
    <antcall target="targetD"/>

有时我们的目标会在同一个build.xml中向目标发出几个antcall,有时我们会在指定目标的子目录中对其他build.xmls进行ant调用。

在任何方面,我想知道一种方法,我可以弄清楚targetA是targetB的父亲。我以为我可以从我的监听器中的BuildEvent属性中确定这些信息。但这似乎不可用。因此,当我收到一个BuildEvent告诉我targetB启动时,看起来BuildEvent并不了解TargetA。

有没有其他人尝试过这样的事情并取得成功?我一直试图使用监听器,但不会反对可以确定目标层次结构的后期处理。

1 个答案:

答案 0 :(得分:1)

我对此并不完全确定,但我想你可以这样(它假设当目标并行运行时,它们运行在与ant使用的主线程不同的线程中,而其他目标运行在与构建侦听器之一的线程中运行:

import java.util.Stack;

import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.Target;


public abstract class MyBuildListener implements BuildListener {

    private Thread mainThread = Thread.currentThread();

    private Stack<Target> callingTargets = new Stack<Target>();

    private ThreadLocal<Stack<Target>> callingTargetsPerThread = new ThreadLocal<Stack<Target>>();

    @Override
    public void targetStarted(BuildEvent event) {
        if(Thread.currentThread()==mainThread) {
            printCallingStack(callingTargets);
            callingTargets.push(event.getTarget());
        } else {
            Stack<Target> callingTargetsForThread = callingTargetsPerThread.get();
            if(callingTargetsForThread==null) {
                callingTargetsPerThread.set(callingTargetsForThread = new Stack<Target>());
            }
            printCallingStack(callingTargetsForThread);
            printCallingStack(callingTargets);
            callingTargetsForThread.add(event.getTarget());
        }
    }

    @Override
    public void targetFinished(BuildEvent event) {
        if(Thread.currentThread()==mainThread) {
            callingTargets.pop();
        } else {
            Stack<Target> callingTargetsForThread = callingTargetsPerThread.get();
            callingTargetsForThread.pop();
            if (callingTargetsForThread.isEmpty()) {
                callingTargetsPerThread.remove();
            }
        }
    }

    private void printCallingStack(Stack<Target> stack) {
        for(int i=stack.size();i>=0;i--) {
            System.out.println(stack.get(i).getName());
        }
    }

}