Proposed simplifications of module system
Eliminate redundancy between module system and AU
Ever since NB6AutoupdateChanges was implemented, both AU and the module system interpret essentially the same module enablement logic. What in the module system is an autoload is in AU an invisible module (AutoUpdate-Show-In-Client: false); a regular module is in AU a visible module (AutoUpdate-Show-In-Client: true). AU does treat eager modules specially, but these can probably be handled by OpenIDE-Module-Recommends instead.
There is thus a significant redundancy in the system. Worse, the two subsystems are out of synch: many regular modules are invisible in AU, and thus treated like autoloads as far as the GUI is concerned.
Since this logic is not really essential in the module system - for example, it is unused in JNLP mode - we can simplify the Platform by implementing it in just AU. This could also be beneficial for integrating OSGiAndNetBeans.
Specifically, all (non-classpath) modules would be considered "regular"; the module system would cease to have any logic for autoload or eager modules. The module system would continue to enforce module dependencies. The behavior of ModuleManager.enable would be simplified to say that the set of modules must be the same as the expected result of simulateEnable, and similarly for disable and simulateDisable.
The Module System defines a clumsy XML format for enumerating known modules and their status, kept in config/Modules/$cnb.xml in clusters and the userdir. While the API only defines the enabled property, the actual format encodes a fair amount of information which is redundant (available also in the JAR manifest), plus the autoload/eager status (which according to the above section would be obsolete), plus a reloadable status.
Problems with this XML format include:
- necessity to create an extra file just to make a working module
- parsing XML during startup is slow, so we have hacks to optimize reading all these little files
- redundancy, as mentioned above
- complexity of code (ModuleList) to read these files dynamically and persist metadata changes
- difficulty of writing correct code to enable or disable a module (dynamically from another module, or statically from AU)
Propose instead that a single Preferences node (e.g. NbPreferences.root().node("org/netbeans/modules")) maintain the list of which modules are enabled and which disabled. Specifically, all known modules are enabled by default, but if $cnb=disabled then that module is disabled.
The module list algorithm would therefore be:
- At startup, scan for modules/*.jar in userdir & available clusters for modules (OpenIDE-Module attribute). Skip code-name-base.jar in case code.name.base=disabled in preferences.
- Load all remaining modules. If $cnb=reloadable then mark it reloadable. Otherwise ($cnb=enabled or unspecified) do not.
- We may prefer to treat all modules as potentially reloadable when running in development mode, indicated e.g. by a system property to be passed by tryme or run targets.
- Enable these modules.
- If some cannot be enabled, prompt to disable them or exit, as now.
- Currently we load even disabled modules to check their metadata. This may not be necessary, or necessary only if and when Plugin Manager is displayed.
- Upon any change to this preferences node:
- If a key refers to an unknown module, check to see if a matching JAR has appeared in some cluster or userdir; if so, load its metadata.
- If the delta between the current enablement state and that described by the preferences node can be satisfied, enact it; otherwise do nothing, pending another change, or enact a subset of the delta. This policy allows sets of modules with internal dependencies to be enabled without requiring a transaction.
Cluster config replacement
As alluded to in DependencyBasedModuleIncludes, it is painful to maintain lists of modules in each cluster, and to decide how to assemble an app that needs just pieces of certain clusters.
A suite would just contain at least one "kit" module, visible to AU, which has dependencies on anything else (in the platform or suite) that is desired. Just as we do now in VerifyUpdateCenter, it would be an error for there to be an invisible module that no one depends on.
There would be no "cluster configurations". Each module could specify its own cluster in project.properties, but this would control nothing more than destination directory.
There would be a few different "module lists". Each list would name only visible modules. All transitive dependencies would implicitly be included.
Building a module "with all dependencies" would mean what it sounds like, not the current system that builds "dependent clusters" first. There would be no "build cluster" action, and no explicit "cluster dependencies". This would solve problems such as Issue 151538 that are inevitable when we attempt to integrate different IDE features.
Intentionally disabled autoloads
Some deprecated API modules are shipped just so they could be used by third parties. We do not want them on. How would we specify that they should be included in the build? Perhaps include them in the module list without making them visible, and somehow ask the module system to not try to enable them by default. Or just stop shipping them; they can be placed on a separate update center.
Bridge modules and OS-specific helpers
OpenIDE-Module-Recommends might be useful here, but exact semantics are unclear.
Provide-require dependencies and "build with dependencies" action
If I ask to build a config that includes projectuiapi, should projectui automatically be built as well? Would certainly be convenient. Does require an existential search over source modules, however, which would otherwise be unnecessary; and would not work well if there is more than one provider.
Could alternately specify projectui as a dependency of e.g. ide.kit. (In this case it already is.) That would ensure it is included in any module list mentioning ide.kit. Is that a sufficient workaround? Perhaps the build could verify in advance that token dependencies are met within the module list.
Specifying module include list, rather than exclude list, for suites
Really want to tell the module system to load the suite's kit module(s) but only those other modules which are dependencies. Related to issue of intentionally disabled autoloads.
Generally, unclear what relationship should be between explicit list of "entry point" modules (desired in some circumstances) vs. automatic scanning of available module JARs (desired in other circumstances).