ActionProgress
+ ActionProvider
implementations should call the
+ new progress listener if possible.
+
+ A new callback was added permitting the invoker of a project + action to be notified when the action completes. +
+SourceGroup.contains
no longer throws IllegalArgumentException
An implementation may be added by a caller to the {@code context} + * of {@link ActionProvider#invokeAction}. + * If the action provider supports this interface, and is actually attempting to + * run an action at this time, it should call {@link #start} + * before returning from {@code invokeAction}, and at some subsequent + * point (possibly still within {@code invokeAction} but generally later from + * a separate task thread) call {@link #finished} once on the result. + *
SPI example using Ant: + *
+ * {@code @}Override public void invokeAction(String command, Lookup context) { + * FileObject buildXml = ...; + * String[] antTargets = ...decide on targets using command...; + * if (antTargets == null) { // wrong conditions, not even pretending to run this action + * showWarningDialog(); + * return; + * } + * final ActionProgress listener = ActionProgress.start(context); + * try { + * ActionUtils.runTarget(buildXml, antTargets, null).addTaskListener(new TaskListener() { + * {@code @}Override public void taskFinished(Task task) { + * listener.finished(((ExecutorTask) task).result() == 0); + * } + * }); + * } catch (IOException x) { + * LOG.log(Level.FINE, "could not start program", x); + * listener.finished(false); + * } + * } + *+ * @since 1.43 + */ +public abstract class ActionProgress { + + /** + * Locates a progress listener in an action context. + * {@link #started} is called on the listener immediately. + * If none was defined by the caller, a dummy implementation is provided + * so that the {@link ActionProvider} need not do a null check. + * @param context a context as supplied to {@link ActionProvider#invokeAction} + * @return a progress listener (or dummy stub) + */ + public static @NonNull ActionProgress start(@NonNull Lookup context) { + ActionProgress ap = context.lookup(ActionProgress.class); + if (ap != null) { + ap.started(); + return ap; + } else { + return new ActionProgress() { + @Override public void started() {} + @Override public void finished(boolean success) {} + }; + } + } + + /** Constructor for subclasses. */ + protected ActionProgress() {} + + /** + * Called when the action is started. + * Serves no purpose other than confirming to the caller that this action + * provider does in fact support this interface and that it should wait + * for action completion. If this method is not called, the caller will + * not know when the action is truly finished. + * Called automatically by {@link #start}, so action providers need not pay attention. + */ + protected abstract void started(); + + /** + * Called when the action has completed. + *
The meaning of the {@code success} parameter depends on the action and may vary + * from implementation to implementation, but a caller may expect that an action + * such as {@link ActionProvider#COMMAND_BUILD} will fail if the project could not be built; + * and an action such as {@link ActionProvider#COMMAND_RUN} will fail if the program could not + * even be started (but perhaps also if it ran and terminated with an erroneous + * exit code). Some callers may ignore this parameter, + * but callers which intend to run multiple actions in succession (on the same or + * different projects) may abort the chain in case one fails. + * @param success true if the action ran normally, false if it somehow failed + */ + public abstract void finished(boolean success); + +} --- a/projectapi/src/org/netbeans/spi/project/ActionProvider.java +++ a/projectapi/src/org/netbeans/spi/project/ActionProvider.java @@ -175,6 +175,7 @@ * @param context any action context, e.g. for a node selection * (as in {@link ContextAwareAction}) * @throws IllegalArgumentException if the requested command is not supported + * @see ActionProgress */ void invokeAction(String command, Lookup context) throws IllegalArgumentException;