Parsing the Command Line to Disable a Module

Yesterday we looked at how to disable a menu item, based on the presence/absence of an option on the command line. However, let's now go a whole step further and... disable a module based on something parsed from the command line. Let's assume we have a module that provides an Admin window, invoked from a menu item in the Help menu, as shown below:

Now, if anyone other than the admin user starts up the application, the window above, as well as the menu item that shows it, should not be there. So, unless the bit in bold below is present, the window and menu item above should be absent:

/bin/sh "/home/geertjan/netbeans-6.0m10/bin/netbeans" --name admin

Everything is the same as yesterday, i.e., create an OptionProcessor and register it in META-INF/services. At this point, you need to know about an XML file that conforms to the http://www.netbeans.org/dtds/module-status-1_0.dtd. Each installed module has such a file, written to the config/Modules folder in the application's user directory. This is how it looks for the module that installs the Admin window above:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//NetBeans//DTD Module Status 1.0//EN"
                        "http://www.netbeans.org/dtds/module-status-1_0.dtd">
<module name="org.netbeans.modules.adminwindowmodule">
    <param name="autoload">false</param>
    <param name="eager">false</param>
    <param name="enabled">true</param>
    <param name="jar">/home/geertjan/NetBeansProjects/
          AdminWindowModule/build/cluster/modules/
          org-netbeans-modules-adminwindowmodule.jar</param>
    <param name="reloadable">true</param>
    <param name="specversion">1.0</param>
</module>

I highlighted the 'enabled' parameter above because that's what we need to set to 'false', if the name set on the command line is not admin. How to do it? Regular readers of this blog will (or at least should) now immediately think "Hurray, we get to use the JAXB Wizard again!" Well, guess what? You're wrong. Initially I thought so too, until I learned about the brand new 6.0 API called Auto Update Services. Basically, this provides an abstraction layer on top of the Module XML file, so that you don't need to deal directly with JAXB, or some other XML parsing alternative. To give you a feel for it, here's my new implementation of the OptionProcessor.process method:

public void process(Env env, Map values) throws CommandException {

    String[] args = (String[]) values.get(name );

    //First check if the user specified 'admin',
    //if NOT, continue with disabling the module:
    if (args.length > 0 && !args[0].equals("admin")) {
        //Get all the modules in the Plugin Manager:
        List updateUnit = UpdateManager.getDefault().getUpdateUnits(UpdateManager.TYPE.MODULE);
        for (int i = 0; i < updateUnit.size(); i++) {
            //Get all the modules that are installed:
            UpdateElement el = updateUnit.get(i).getInstalled();
            //Of those that are installed, if it has the code name base
            //of the module we are interested in, and it is enabled,
            //continue with this procedure to disable it:
            if (el != null && el.getCodeName().equals
                    ("org.netbeans.modules.adminwindowmodule") 
                    && el.isEnabled()) {
                try {
                    //Specify how we want to handle the module; 
                    //here, we want to disable it:
                    OperationContainer oc = OperationContainer.createForDisable();
                    oc.add(el);
                    //Finally, do the operation,
                    //passing a progress handle or, as in this case, null:
                    OperationSupport supp = (OperationSupport) oc.getSupport();
                    supp.doOperation(null);
                } catch (OperationException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }
    //Here, if the user DID specify 'admin',
    //we do the same as the above, except that we enable
    //the module if it is found to be disabled:
    } else if(args[0].equals("admin")) {
        List updateUnit = UpdateManager.getDefault().
                getUpdateUnits(UpdateManager.TYPE.MODULE);
        for (int i = 0; i < updateUnit.size(); i++) {
            UpdateElement el = updateUnit.get(i).getInstalled();
            if (el != null && el.getCodeName().equals
                    ("org.netbeans.modules.adminwindowmodule") 
                    && !el.isEnabled()) {
                try {
                    OperationContainer oc = OperationContainer.createForEnable();
                    oc.add(el);
                    OperationSupport supp = (OperationSupport) oc.getSupport();
                    supp.doOperation(null);

                } catch (OperationException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }
    }
}

As a result of the above, the 'enabled' parameter is set to false, as shown below, whenever the user is not called admin:

<param name="enabled">false</param>

So now, without JAXB or any XML parsing whatsoever, I've changed one parameter in the Module XML file, based on something typed in the command line. Plus, the change is reflected immediately, i.e., the module is reinstalled. How cool is that? I think that's really exactly what I was looking for. No need to parse the XML directly. And no need to reinstall the module via some workaround after making the change. All that is handled by the aforementioned Auto Update Services API. Thanks a lot to the developers who helped me out with this today.

Comments:

is there anyway this tutorial with source code will be post here? or http://www.netbeans.org/kb/trails/platform.html

Posted by my name is on October 11, 2007 at 02:11 AM PDT #

The source code is already posted here. Read above and you see the source code.

Posted by Geertjan on October 11, 2007 at 02:28 AM PDT #

This module disabling code does not work for me. (I'm using NetBeans Platform v.6.5)

I debugged into the NetBeans source and found out that the statement "supp.doOperation(null);" at the end of the disable case, does not really disable the module but just sets some inner data structure.

I could fix this by replacing:
OperationContainer oc = OperationContainer.createForDisable();

with:

OperationContainer oc = OperationContainer.createForDirectDisable();

Posted by Florian Brunner on January 06, 2009 at 11:36 PM PST #

Yes, things like this might change over time. Thanks for mentioning it here.

Posted by Geertjan on January 06, 2009 at 11:37 PM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« September 2015
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today