Rechtacek's

My notices, hints or tips
 Who Am I?
Which way?
Friday Jan 23, 2009

Quietly disable modules at runtime?

I was given a inquiry from user of NetBeans Platform. He wants to know a way how to disable one or more modules, in running application built on NetBeans Platform, in additional it must be perform silently, i.e. with no end-user intervention or any assistance.

Well, he requirement is clear but its fulfillment has several difficulties: first, modules in NetBeans Platform depends on each other and it's uneasy to discover modules which don't involve any essential module of platform. Second, modules could depend on each other, even thought don't declare such dependency in it meta-data. Such ad-hoc dependencies are mistakes and NetBeans architecture is aiming to avoid them but few of them can still left there. This fact leaded NetBeans team to do disabling of module only in "offline" time, it means when NetBeans application is not running currently. Despite of this, Autoupdate Services still offers this possibility even if it never called in NetBeans IDE.

Okay. It was bad news, good new is Autoupdate Services API has capability to perform disabling of module in currently running application (with awareness of possible problems stated above).

Autoupdate Services has the particular operation container for disabling modules OperationContainer.createForDirectDisable. Now I show a code snippet how to use this container for disabling some modules.

public void doDisable (Collection<String> codeNames) { // codeName contains code name of modules for disbale
Collection<UpdateElement> toDisable = new HashSet<UpdateElement> ();
List<UpdateUnit> allUpdateUnits = UpdateManager.getDefault ().getUpdateUnits (UpdateManager.TYPE.MODULE);
for (UpdateUnit unit : allUpdateUnits) {
if (unit.getInstalled () != null) { // filter all installed modules
UpdateElement el = unit.getInstalled ();
if (el.isEnabled ()) { // filter all enabled modules
if (codeNames.contains (el.getCodeName ())) { // filter given module in the parameter
toDisable.add (el);
}
}
}
}

OperationContainer<OperationSupport> oc = OperationContainer.createForDirectDisable ();

for (UpdateElement module : toDisable) {
if (oc.canBeAdded (module.getUpdateUnit (), module)) { // check if module can be disabled
OperationInfo<OperationSupport> operationInfo = oc.add (module);
if (operationInfo == null) { // it means it's already planned to disable
continue;
}
// get all module depending on this module
Set<UpdateElement> requiredElements = operationInfo.getRequiredElements ();
// add all of them between modules for disable
oc.add (requiredElements);
}
}

// check the container doesn't contain any invalid element
assert oc.listInvalid ().isEmpty ();
try {
// get operation support for complete the disable operation
Restarter restarter = oc.getSupport ().doOperation (null);
// no restart needed in this case
assert restarter == null;
} catch (OperationException ex) {
Exceptions.printStackTrace (ex);
}
}

I hope it helps to achieve the wish. If you have any problem let me know.

Comments:

Hi,

The post is really helpful. However, when I am disabling my module, I am always getting operationInfo as null:
OperationInfo<OperationSupport> operationInfo = oc.add (module);

This is restricting me to disable my module. FYI, I am using NB 6.5 with autoupdate service v1.5.2

Any help would be appreciated.
thanks

Posted by 122.160.107.50 on February 25, 2009 at 11:03 AM CET #

The exact exception is:

java.lang.IllegalArgumentException: Invalid com.module1 for operation DIRECT_DISABLE
at org.netbeans.modules.autoupdate.services.OperationContainerImpl.add(OperationContainerImpl.java:106)
at org.netbeans.api.autoupdate.OperationContainer.add(OperationContainer.java:275)

Posted by Prashant on February 25, 2009 at 11:31 AM CET #

Some more information. The issue is seen only with jnlp applications. It works fine as a normal desktop application. If required, I can share my sample project code.

Posted by Prashant on February 25, 2009 at 02:03 PM CET #

Hi Prashant,
I don't know yet why it doesn't work. Your sample code will be appreciated. It would help to figure out what's wrong. You can send it directly to jiri.rechtacek at sun dot com.
-jiri

Posted by Jiri Rechtacek on February 25, 2009 at 09:08 PM CET #

Hi,

I have an answer on your problem. The reason why it's doesn't work if the application is launched as JNLP, is that ClassLoader loads all modules as 'fixed' modules. But fixed module cannot change its state nor be uninstall. That's why OperationContainer.canBeAdded() will return false for JNLP launched module thus adding such modules for operation DIRECT_DISABLE is invalid and will throw IllegalArgumentException: Invalid module for operation DIRECT_DISABLE.

Look an thread for more background http://209.85.129.132/search?q=cache:GVZsWwVez1MJ:forums.netbeans.org/ptopic8175.html+jnlp+fixedmodule+site:netbeans.org&hl=cs&ct=clnk&cd=2&gl=cz&client=firefox-a

So, all together means you cannot disable any module if application is launched as webstart.

Hope it helps.

Regards,
-jiri

Posted by Jiri Rechtacek on March 01, 2009 at 05:38 PM CET #

Thanks for the post, it is really helpful. I would like to use it to achieve software licensing mechanism per module, so if a module is not licensed it shoud get disabled. My current approach is to use ModuleInstaller, but then I cannot get rid of or customise the startup dialog allowing one to accept module disablement and continue, or exit. So, would the above code work if run in ModuleInstaller of a dedicated module, thus trying to disable other modules? How would this behave if a module is not yet loaded or has been loaded?

Posted by Ivailo Kolev on July 14, 2009 at 10:33 AM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed

Archives
Locations of visitors to this page
Links
Referrers