【问题标题】:How to run ant from an Eclipse plugin, send output to an Eclipse console, and capture the build result (success/failure)?如何从 Eclipse 插件运行 ant,将输出发送到 Eclipse 控制台,并捕获构建结果(成功/失败)?
【发布时间】:2016-05-24 23:15:22
【问题描述】:

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

我找到了三种从 eclipse 运行 Ant 脚本的方法:

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

有没有办法让控制台输出捕获结果?

【问题讨论】:

    标签: eclipse ant console


    【解决方案1】:

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

    原答案 我意识到这是一篇旧帖子,但我能够在我的一个插件中完全按照您的意愿行事。如果它在这一点上对您没有帮助,也许它会帮助其他人。我最初是在 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) {
        }
    });
    

    【讨论】:

    • 在我发布这个问题后不久,我打算使用它的项目被取消了。由于这是对您真正有用的最完整的回复,因此我将其标记为答案。
    • 投票将我的注意力吸引回了这个旧答案。在 4.2 (Juno) 中仍然运行良好。
    • posted an answer 关于此解决方案的输出丢失问题。我认为输出可能发生在workingCopy.launch(...) 之后但在.addListener(new IStreamListener() { ... }) 之前。该输出永远不会到达听众。在您的答案中添加一个注释可能是个好主意,其他人也可能会花很长时间对为什么不调用他们的流侦听器感到困惑。
    • 感谢@Lii 的加入
    【解决方案2】:

    我想向happytime harry's answer 添加一件事。

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

    例如看这个bug。我认为happytime harry的解决方案可能有这个问题。我自己在 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 在此之前运行,则此解决方案可能不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-19
      • 1970-01-01
      • 2013-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多