在Eclipse插件中,我想运行一个Ant构建脚本。我还想通过在Eclipse控制台中显示Ant输出来向用户显示它。最后,我还想等待Ant构建完成,并捕获结果:构建成功还是失败?
我找到了三种从eclipse运行Ant脚本的方法:
org.eclipse.ant.core.AntRunner
,致电某些设置者并致电run()
或run(IProgressMonitor)
。结果是正常终止(表示成功),或者包含IStatus
{表示失败的BuildException
的CoreException,或者其他错误。但是,我没有在任何地方看到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)
,然后在该集合属性"org.eclipse.ui.externaltools.ATTR_LOCATION"
上调用构建文件名(并将属性DebugPlugin.ATTR_CAPTURE_OUTPUT
更改为true),最后调用{ {1}}。 Ant输出显示在Eclipse控制台中,但我不知道如何在代码中捕获构建结果(成功/失败)。或者甚至如何等待终止发布。有没有办法让两个控制台输出和捕获结果?
答案 0 :(得分:4)
编辑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) {
}
});
答案 1 :(得分:1)
我想向happytime harry's answer添加一件事。
有时,第一次写入流发生在添加流侦听器之前。然后,永远不会为侦听器调用streamAppended
,因此输出会丢失。
例如,见bug。我认为快乐时候哈里的解决方案可能有这个问题。我自己在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
在此之前运行,则此解决方案可能无效。