equinox |
Summary | |
Above the Eclipse Registry, we have modified the UI plugins providing a
dynanic Workbench,
which reacts to extensions appearing or disappearing.
We actually only
had to modify two plugins: org.eclipse.ui.workbench and org.eclipse.ui.views.
All extension points in the UI plugin are now dynamic. The approach taken was
simple but effective: considering partial shutdown. The Workbench already had
the ability to save its state when Eclipse shutdowns, in order to be able to
recreate perspectives and views on restart. We have fragmented the process
to work at an extension level. So plugins can be updated seamlessly from a
Workbench point of view. For instance, enough information is saved about the
impacted perspectives, views, action sets so that they can be automatically
recreated once the update is done.
Nota Bene: This document describes the current prototype, not the final decisions of Equinox. | |
Definitions | |
The term "dynamic loading" in this document refers to the feature of an Eclipse system in which plugins that are already loaded can be removed from the runtime; and new plugins currently not accessible by the runtime can be loaded and made accessible in the runtime. These activities are performed with the Eclipse system continuing executing in a consistent state. Note that the removal and load actions on a particular plugin can be combined to perform the update function on this plugin. The Eclipse UI in this document refers to the group of plugins that provide the default workbench and various user interface parts associated with the workbench. Typical workbench UI parts include the following: perspectives, views,editors, and wizards. The Eclipse UI provides extension points so that other plugins can extends Eclipse UI and create their own customized workbench environment. | |
Existing Workbench | |
The workbench is the arena in which UI interactions take place. It provides menus and action bars that are the entry point from which actions are invoked. For example, new perspectives and new views can be activated through the workbench menu. It also keeps track of the current state of UI such that when it is restarted, it will try to recreate the UI based on the last-saved state. To make the system more efficient, the workbench maintains cached information for various UI parts so that whenever one of the cached UI part is invoked, the workbench needs not reprocess its plugin extension information in the plugin registry to regenerate the knowledge of this UI. In other words, the workbench manages a set of UI registries that stored knowledge about various UI parts. The knowledge about a UI part is derived from processing the plugin extension information of this UI part stored in the plugin registry. In the existing workbench, once these UI registries are constructed, the workbench sees each UI part it manages as an individual UI component whose information is stored in the workbench's own cached data. Hence once the runtime passes the stage when the workbench builds its cached data, the information about plugins and their extensions are no longer relevant to the workbench. Afterwards, the UI part information cached by the workbench becomes static and not changeable. | |
What "Dynamic Loading" Means to the Workbench? | |
Based on the aforementioned definition, when a plugin is removed from the Eclipse runtime, the runtime should remain in a consistent state. This means that all active traces of this plugin should be revoked from the runtime. For UI, this means that all cached UI parts for this plugin must be removed from the workbench's UI part cach. In short, the workbench needs to clean up all traces of the UI parts that belong to the target plugin that is going away. Conversely, when a plugin is loaded into the runtime, the workbench must then update its cache to add information of the UI parts that are provided by this plugin. The existing workbench cache for UI parts are in the forms of registries and other data structures used for various types of UI parts. These structures once constructed remains static until the Eclipse system terminates. I have made changes to these structures to make them dynamic so that each item in them can be removed and inserted dynamically. | |
The UI Extension Points Are a Starting Point | |
The Eclipse UI provides a large number of extension points which allow for custom UI extensions. These extension points determine which custom plugin extensions are UI extensions. The workbench does not cache information for all UI extensions. To find out the extension points whose extensions are cached by the workbench, I used the inside-out approach by first identify the data structures (e.g., registries) used by the workbench to cached UI part information. From these structures, I then trace back the particular extension points whose extensions are used to create the respective cached UI part information. So far, I have identified the following UI extension points that are affected by dynamic loading:
| |
Handling Extension Events | |
Olivier and I designed an event framework in which a plugin can register with the Eclipse platform to listen to extension events that are associated with extension points provided by this plugin. An extension event is defined as a particular extension being removed from or added to the plugin registry. This event model gives an extension point provider an opportunity to clean up itself after an extension of this extension point is removed from or added to the runtime. To support "dynamic loading", the new workbench plugin now listens to extension events associated with its extension points. Upon receiving a removal extension event, the workbench checks to see if the event refers to one of the UI extension points affected by "dynamic loading" (see above extension point list). If so, the target extension is used to find the entry in the cached registry that is associated with the extension point of this extension. Next, this entry is removed from the associated cache and all other affected data structures are updated accordingly. When the workbench receives a load extension event, it determines if the extension to be loaded belongs to one of the extension points listed above. If so, this UI information for this extension is created and inserted into the appropriate cached registry, with all other affected data structures being updated accordingly. From the workbench’s point of view, the removal of a plugin means a removal extension event is triggered for each of this plugin’s UI extension. Conversely, the loading of a plugin means a load extension event is triggered for each of this plugin’s UI extension. The extension-level granularity of this event model makes sense to the workbench as the latter needs not to be aware of plugins during runtime. This way, the workbench only focuses on one extension at a time, making the event processing much simpler. Furthermore, such a model is well suited to the partial synchronization approach that may one day be adopted for live update of certain plugins. | |
Saving UI Extension State? | |
When an extension is removed, do we need to save its state? We think it depends. If the extension goes away permanently, then saving its state is not necessary. But if we are replacing an active extension with a new version by invoking consecutive removal and load actions, we may want to save the state when this extension is removed and restore the state when a new version of this extension is reloaded. For example, an active editor extension is being updated to a newer version. When the newer version comes up, we still want it to associate with the same file the older version is associated with. Currently, I have written code to preserve state for the following three UI extension types:
The state for these extension types are only saved if they were active during removal. I reuse the existing saveState() and restoreState() APIs as much as possible to preserve and recover the state. The saved state however is not externally stored hence is only recoverable while the system remains up. | |
UI Registry Management | |
The workbench maintains a registry structure for each of the aforementioned UI extension points. During the start-up phase, the workbench reads the UI extensions from the plugin register and creates UI part entries that populate these UI registries. Afterwards, these UI registries remain static during runtime. For each of the UI registry, I have added code to allow entries to be removed and inserted while the Eclipse system is running. | |
UI Mapping Data Structure Management | |
While populating the UI registries, the workbench also resolves various mappings between UI extensions and other information. The examples of this kind of mapping include view-category mapping and editor-filename/extension mapping. These mapping data structure code have also been changed to allow for dynamic update. | |
Workbench Menu Management | |
Some UI extensions are activated through the workbench menu (e.g., perspectives, views, new wizards). The actionSets extension further allows an application plugin to create submenu and menu entries in the workbench menu. When these extensions are removed or loaded, the workbench menu should be updated to reflect the change. I have traced down the intermediate data structures that the workbench uses to create its menu items. During a UI extension event processing, I have add routines that update these intermediate data structures accordingly so that the workbench menu and its items reflect the updated state of the system. List of Changes Made to the Existing R3C Code
|