繁体   English   中英

如何从Eclipse插件运行ant,将输出发送到Eclipse控制台,并捕获构建结果(成功/失败)?

[英]How to run ant from an Eclipse plugin, send output to an Eclipse console, and capture the build result (success/failure)?

在Eclipse插件中,我想运行一个Ant构建脚本。 我还想通过在Eclipse控制台中显示Ant输出来向用户显示它。 最后,我还想等待Ant构建完成,并捕获结果:构建成功还是失败?

我发现了三种从eclipse运行Ant脚本的方法:

  • 实例化一个org.eclipse.ant.core.AntRunner ,调用一些setter并调用run()run(IProgressMonitor) 其结果要么是正常终止(表示成功),或与一个CoreException IStatus含有BuildException (表示失败),否则别的东西出了问题。 但是,我没有看到任何地方的Ant输出。
  • 实例化org.eclipse.ant.core.AntRunner并调用run(Object) ,传递包含命令行参数的String[] 结果是正常终止(指示成功)或InvocationTargetException (指示失败),否则出现其他错误。 看来,Ant输出被发送到Eclipse的stdout; 它在Eclipse本身中不可见。
  • 调用DebugPlugin.getDefault().getLaunchManager() ,然后在该调用上调用getLaunchConfigurationType(IAntLaunchConfigurationConstants.ID_ANT_BUILDER_LAUNCH_CONFIGURATION_TYPE) ,然后在该set属性"org.eclipse.ui.externaltools.ATTR_LOCATION"上调用构建文件名(和属性DebugPlugin.ATTR_CAPTURE_OUTPUT到是的)最后调用launch() Ant输出显示在Eclipse控制台中,但我不知道如何在代码中捕获构建结果(成功/失败)。 或者甚至如何等待终止发射。

有没有办法同时拥有控制台输出,并捕获结果呢?

编辑 05/16/2016 @Lii提醒我, ILaunchConfigurationWorkingCopy#launch调用和附加IStreamListener之间的任何输出都将丢失。 他在这里为这个答案做出了贡献。

原始答案我意识到这是一个旧帖子,但我能够在我的一个插件中完全按照你想要的那样做。 如果它在这一点上没有帮助你,也许它会帮助别人。 我最初在3.2中做过这个,但它已针对3.6 API更改进行了更新...

// show the console
final IWorkbenchPage activePage = PlatformUI.getWorkbench()
        .getActiveWorkbenchWindow()
        .getActivePage();
activePage.showView(IConsoleConstants.ID_CONSOLE_VIEW);

// let launch manager handle ant script so output is directed to Console view
final ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType type = manager.getLaunchConfigurationType(IAntLaunchConstants.ID_ANT_LAUNCH_CONFIGURATION_TYPE);
final ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null, [*** GIVE YOUR LAUNCHER A NAME ***]);
workingCopy.setAttribute(ILaunchManager.ATTR_PRIVATE, true);
workingCopy.setAttribute(IExternalToolConstants.ATTR_LOCATION, [*** PATH TO ANT SCRIPT HERE ***]);
final ILaunch launch = workingCopy.launch(ILaunchManager.RUN_MODE, null);
// make sure the build doesnt fail
final boolean[] buildSucceeded = new boolean[] { true };
((AntProcess) launch.getProcesses()[0]).getStreamsProxy()
        .getErrorStreamMonitor()
        .addListener(new IStreamListener() {
            @Override
            public void streamAppended(String text, IStreamMonitor monitor) {
                if (text.indexOf("BUILD FAILED") > -1) {
                    buildSucceeded[0] = false;
                }
            }
        });
// wait for the launch (ant build) to complete
manager.addLaunchListener(new ILaunchesListener2() {
    public void launchesTerminated(ILaunch[] launches) {
        boolean patchSuccess = false;
        try {
            if (!buildSucceeded[0]) {
                throw new Exception("Build FAILED!");
            }
            for (int i = 0; i < launches.length; i++) {
                if (launches[i].equals(launch)
                        && buildSucceeded[0]
                        && !((IProgressMonitor) launches[i].getProcesses()[0]).isCanceled()) {
                    [*** DO YOUR THING... ***]
                    break;
                }
            }
        } catch (Exception e) {
            [*** DO YOUR THING... ***]
        } finally {
            // get rid of this listener
            manager.removeLaunchListener(this);
            [*** DO YOUR THING... ***]
        }
    }

    public void launchesAdded(ILaunch[] launches) {
    }

    public void launchesChanged(ILaunch[] launches) {
    }

    public void launchesRemoved(ILaunch[] launches) {
    }
});

我想在happytime harry的回答中添加一件事。

有时,第一次写入流发生在添加流侦听器之前。 然后,从不为这些写入调用streamAppended on listener,因此输出会丢失。

例如,请参阅此错误 我认为快乐时候哈里的解决方案可能有这个问题。 我自己在ILaunchListener.launchChanged注册了我的流监听ILaunchListener.launchChanged ,这发生了4/5次。

如果想要确保从流中获取所有输出,则可以使用IStreamMonitor.getContents方法获取在添加侦听器之前发生的输出。

以下是对处理此问题的实用程序方法的尝试。 它基于ProcessConsole的代码。

/**
 * Adds listener to monitor, and calls listener with any content monitor already has.
 * NOTE: This methods synchronises on monitor while listener is called. Listener may
 * not wait on any thread that waits for monitors monitor, what would result in dead-lock.
 */
public static void addAndNotifyStreamListener(IStreamMonitor monitor, IStreamListener listener) {
    // Synchronise on monitor to prevent writes to stream while we are adding listener.
    // It's weird to synchronise on monitor because that's a shared object, but that's 
    // what ProcessConsole does.  
    synchronized (monitor) {
        String contents = monitor.getContents();
        if (!contents.isEmpty()) {
            // Call to unknown code while synchronising on monitor. This is dead-lock prone!
            // Listener must not wait for other threads that are waiting in line to 
            // synchronise on monitor.
            listener.streamAppended(contents, monitor);
        }
        monitor.addListener(listener);
    }
}

PS: ProcessConsole.java有一些奇怪的东西。 为什么从ProcessConsole.StreamListener构造函数切换内容缓冲?! 如果ProcessConsole.StreamListener在此之前运行,则此解决方案可能无效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM