-
Type:
Suggestion
-
Resolution: Fixed
-
Component/s: None
We'd like to include plugins in the default confluence distribution (particularly the Conf Repo Client) that are upgradeable, just like user-installable plugins.
The repo client needs to be capable of upgrading itself, which means that it can't be a static plugin. However, all current bundled plugins are static and can't be replaced. So I created a new plugin loader that looks in the {$conf-install-dir}/bundled-plugins directory and dynamically loads plugins from there as well. Perfect!
Next, however, imagine that you've installed your own copy of the repo-client in {$conf-home}/plugins. If you upgrade to Confluence 2.3 containing the bundled copy, the two plugins are going to conflict.
To solve that problem, we have to be able to compare two plugins from different plugin-loaders and choose the more recent. I implemented a compareTo() method on the Plugin class that will attempt to get the plugin's version and determine which is the more recent. It expects standard x.x.x format version. It does a little bit of cleanup (removing spaces, etc.) to try to ensure an accurate comparison.
So now when we find a duplicate plugin key, we check to see if the conflicting plugin is newer than the one we have. If it is, we unload the current plugin and load the new one. If it is the same version or older, we do nothing. If we can't get a valid version (e.g., the format is wrong) we leave the plugin we've already loaded in place.
On the other hand, we always want to get back to a baseline version of Confluence - identical to what shipped from Atlassian. So that means when we load a user-installed verison of a bundled plugin, we don't want to remove the bundled version. So I made sure that my new bundled-plugins plugin loader doesn't actually delete any files. That way, if you ever get into trouble, you can clear your {{{$conf-home}/plugins}) and get back to the original state.
After talking over the design of the bundled-plugins feature with Mike, he pointed out that our simple "look in this directory" plan wouldn't work when deploying in an un-exploded .war. So we need to bundle the zips and then actually extract them into $confluence-home/bundled-plugins.. So I build a step into ConfluencePluginManager that will, on init:
- check for the presence of an atlassian-bundled-plugins.zip
- check for the presence of $confluence-home/bundled-plugins.
- if different, replace the contents of $confluence-home/bundled-plugins with the contents of atlassian-bundled-plugins.zip.
So, that way, we can always ensure that the default set of plugins will be there, but we don't end up copy-ing them out freshly on each startup, which would be wasteful. If a user wants to upgrade a bundled-plugin, he will copy a new version into $confluence-home/bundled-plugins, and the newer version will override the default until uninstalled. If uninstalled, the plugin manager will pick up the older, bundled version.
If the user has a custom-installed version of a bundled plugin, and then we release a newer version as part of a Confluence upgrade, that version will be the one that runs.