簡體   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