X

Geertjan's Blog

  • February 5, 2011

Invoke an Action from the NetBeans Command Line

Geertjan Wielenga
Product Manager
Ingo Fischer, on the NetBeans Platform development mailing list (here), would like to invoke an action from the command line. I guess, something like this:
/home/geertjan/netbeans-dev-201101300000/bin/netbeans --runAction "GreetAction"

And, for this example, here's the "GreetAction":

@ActionID(category = "MyActions",
id = "org.trigger.action.GreetAction")
@ActionRegistration(displayName = "#CTL_GreetAction")
@ActionReferences({
@ActionReference(path = "Menu/File", position = 0)
})
@Messages("CTL_GreetAction=Greet")
public final class GreetAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "hello world");
}
}

So, note that the "GreetAction" will be registered in the actions category "MyActions". That means that in the central registry there'll be a folder "Actions/MyActions", which is where the "GreetAction" will be registered.

Now, let's invoke that Action from the command line.

@ServiceProvider(service = OptionProcessor.class)
public class TriggerActionCommandLine extends OptionProcessor {
//Here we specify "runAction" as the new key in the command,
//but it could be any other string you like, of course:
private static Option action = Option.requiredArgument(Option.NO_SHORT_NAME, "runAction");
@Override
public Set<org.netbeans.spi.sendopts.Option> getOptions() {
return Collections.singleton(action);
}
@Override
protected void process(Env env, Map<Option, String[]> values) throws CommandException {
String[] args = (String[]) values.get(action);
if (args.length > 0) {
//Set the value to be the first argument from the command line,
//i.e., this is "GreetAction", for example:
final String actionName = args[0];
//Wait until the UI is constructed,
//otherwise you will fail to retrieve your action:
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override
public void run() {
//Then find & perform the action:
Action a = findAction(actionName);
//TODO: a null check
a.actionPerformed(null);
}
});
}
}
public Action findAction(String actionName) {
FileObject myActionsFolder = FileUtil.getConfigFile("Actions/MyActions");
FileObject[] myActionsFolderKids = myActionsFolder.getChildren();
for (FileObject fileObject : myActionsFolderKids) {
//Probably want to make this more robust,
//but the point is that here we find a particular Action:
if (fileObject.getName().contains(actionName)) {
try {
DataObject dob = DataObject.find(fileObject);
InstanceCookie ic = dob.getLookup().lookup(InstanceCookie.class);
if (ic != null) {
Object instance = ic.instanceCreate();
if (instance instanceof Action) {
Action a = (Action) instance;
return a;
}
}
} catch (Exception e) {
ErrorManager.getDefault().notify(ErrorManager.WARNING, e);
return null;
}
}
}
return null;
}
}

Import statements:

import java.util.Collections;
import java.util.Map;
import java.util.Set;
import javax.swing.Action;
import org.netbeans.api.sendopts.CommandException;
import org.netbeans.spi.sendopts.Env;
import org.netbeans.spi.sendopts.Option;
import org.netbeans.spi.sendopts.OptionProcessor;
import org.openide.ErrorManager;
import org.openide.cookies.InstanceCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.WindowManager;

I've tried the above in NetBeans IDE, with success, i.e., I see "hello world" in a JOptionPane whenever the IDE starts, as well as in a separate application created on the NetBeans Platform.

Join the discussion

Comments ( 2 )
  • Jean-Marc Borer Monday, February 7, 2011

    Why do you need to use the InstanceCookie? The action beeing registered in the SystemFileSystem insn't it already instanciated and then you only need to lookup the instance via its Class? Or you intentionally create a new instance? I am still learing things in this area of NB. Therefore my question may sound silly.


  • Jesse Glick Monday, February 7, 2011

    Use fo.getName().replace('-',',').equals(actionName) so that the argument to the option matches @ActionID.id. This can also be used to locate the desired FileObject directly rather than searching children. https://netbeans.org/bugzilla/show_bug.cgi?id=169338 would make this simpler still, as would something like findSystemFileSystemPath mentioned in https://netbeans.org/bugzilla/show_bug.cgi?id=183794 but not implemented.

    If you want shorter IDs, use shorter IDs; there is no requirement that the ID be a class name. Or make the argument generic by requiring the @ActionID.category to be prepended:

    --runAction MyActions/Greet

    for

    @ActionID(category="MyActions", id="Greet")


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.