| <html> |
| <head><title>Features Framework Specification</title></head> |
| <body> |
| <font face="Arial" size="-1"> |
| |
| <center> |
| |
| <font size="+0"><b>Features Framework Specification</b></font><br/><br/> |
| |
| <b><i>initial design by</i></b><br/> |
| Ted Bashor [<a href="mailto:tbashor@bea.com"><i>tbashor@bea.com</i></a>], |
| Chuck Bridgham [<a href="mailto:cbridgha@us.ibm.com"><i>cbridgha@us.ibm.com</i></a>],<br/> |
| Tim Deboer [<a href="mailto:deboer@ca.ibm.com"><i>deboer@ca.ibm.com</i></a>], |
| Michael Elder [<a href="mailto:mdelder@us.ibm.com"><i>mdelder@us.ibm.com</i></a>],<br/> |
| Konstantin Komissarchik [<a href="mailto:kosta@bea.com"><i>kosta@bea.com</i></a>], |
| Jason Sholl [<a href="mailto:jsholl@us.ibm.com"><i>jsholl@us.ibm.com</i></a>],<br/> |
| Thomas Yip [<a href="mailto:tyip@bea.com"><i>tyip@bea.com</i></a>], |
| Elson Yuen [<a href="mailto:eyuen@ca.ibm.com"><i>eyuen@ca.ibm.com</i></a>] |
| <br/><br/> |
| |
| <b><i>written by</i></b><br/> |
| Konstantin Komissarchik [<a href="mailto:kosta@bea.com"><i>kosta@bea.com</i></a>] |
| <br/></br/> |
| |
| <b><i>revision date</i></b><br/> |
| 2005-08-29 |
| <br/><br/> |
| |
| </center> |
| |
| <b>Summary</b> |
| <hr/> |
| |
| <p>This framework provides a common mechanism and ui for adding and |
| removing units of functionality from a project. A unit of functionality (or a |
| "feature") is a marker that can be used, for instance, to enable |
| feature-specific UI. A feature also has a great deal of flexibility to |
| manipulate the project when it's being installed. It can add natures, builders, |
| and classpath entries. It can also lay down feature-specific metadata files |
| and other resources into the project directory.</p> |
| |
| <b>Feature vs. Nature</b> |
| <hr/> |
| |
| <p>A feature is similar to a nature, but it's scope is much wider.</p> |
| |
| <ol> |
| <li> |
| Features are designed to be added and removed by the end user, while natures are an |
| implementation detail. A feature can, if necessary, add a nature to the project as |
| part of it's installation logic. Not all features will use natures. |
| </li> |
| <li> |
| Features can be versioned. Feature A can declare that it depends on feature B version |
| 1.2 or newer. Upgrade handling can be associated with moving from version 1.2 to 1.3. |
| </li> |
| <li> |
| Features support a richer constraint expression language than natures. |
| </li> |
| <li> |
| It would be difficult to add additional lifecycle event methods to the |
| IProjectNature interface, because doing so will break all of the existing |
| implementations. The feature framework, on the other hand, uses a delegate |
| mechanism where every event method is represented by a separate interface. |
| This makes it very easy to add support for new lifecycle events without |
| effecting existing code. See the <a href="#delegates">Delegates</a> |
| section for more information. |
| </li> |
| <li> |
| The IProjectNature's configure and deconfigure methods do not take any |
| parameters. This makes them of limited use in situations where input from |
| UI needs to be taken into account and has resulted in a situation where |
| most of the necessary work happens in the wizards. This makes it quite |
| difficult for someone to say add java functionality to a project at the |
| API level. The features framework addresses this problem by allowing the |
| install and uninstall delegates to take a configuration object. The |
| configuration object can either be filled out by the UI or someone working |
| at the API level. |
| </li> |
| </ol> |
| |
| <b>Version Support</b> |
| <hr/> |
| |
| <p>The framework supports defining multiple versions of the same feature. This |
| makes it possible to, for example, express that feature A depends on version |
| 1.3 or newer of feature B. There are no limitations placed on the format of the |
| version string. The feature author is responsible for providing an |
| implementation of a version comparator. If one is not provided, a default |
| implementation will be used.</p> |
| |
| <b>Constraints</b> |
| <hr/> |
| |
| <p>Each feature version can declaratively specify what constraints must be |
| satisfied before the feature can be installed. Four operators are supported: |
| and, or, requires, and oneof.<p> |
| |
| <font size="+0"><pre> |
| <requires feature="<i>string</i>" version="<i>string</i>" allow-newer="<i>boolean</i>" soft="<i>boolean</i>"/> |
| </pre></font> |
| |
| <p>The <i>feature</i> and <i>version</i> attributes are required. The |
| <i>allow-newer</i> and <i>soft</i> attributes are optional and both are |
| defaulted to <i>false</i>. The <i>soft</i> attribute is used to indicate that |
| the feature is allowed to be installed even if the required feature is missing, |
| but if the required feature is selected, this feature should be installed after |
| it.</p> |
| |
| <font size="+0"><pre> |
| <oneof set="<i>string</i>"/> |
| </pre></font> |
| |
| <p>The <i>set</i> attribute is required. This constraint is used to indicate |
| that the feature conflicts with members of the specified set.</p> |
| |
| <font size="+0"><pre> |
| <and>...</and>, <or>...</or> |
| </pre></font> |
| |
| <p>Both of these operators work with two or more sub-constraints.</p> |
| |
| <table cellpadding="10"><tr><td bgcolor="#C0C0C0"> |
| <font size="-1" face="Arial"><p><b>Example:</b></p></font> |
| <font size="+0"><pre> |
| <extension point="...core.features"> |
| <feature-version id="web" version="1.0"> |
| ... |
| <constraint> |
| <and> |
| <requires feature="java" version="5.0"/> |
| <requires feature="flexible.project" version="1.0"/> |
| <oneof set="modules"/> |
| </and> |
| </constraint> |
| ... |
| </feature-version> |
| </extension> |
| </pre></font> |
| </td></tr></table> |
| |
| <p><b><a name="delegates">Delegates</a></b></p> |
| <hr/> |
| <p>Each feature version can implement any number of the supported delegate |
| interfaces to be given a chance to do some work during some event in a feature's |
| life cycle. Six delegates are supported: <i>install</i>, <i>uninstall</i>, |
| <i>update</i>, <i>upgrade</i>, <i>activate</i>, and <i>deactivate</i>. Most, if |
| not all, features will implement at least the <i>install</i> delegate.</p> |
| |
| <p><i>install</i> - Invoked when the feature is being added to a project. This |
| can happen either during project creation or when the user chooses to add a |
| feature to an existing project. This delegate will be invoked after all the |
| features that this feature depends on are installed. This delegate can take |
| input from UI through a config object. See the <a href="#wizard">Wizard |
| Framework</a> section for more information.</p> |
| |
| <p><i>uninstall</i> - Invoked when the feature is being removed from a project. |
| This delegate can take input from UI through a config object. See the |
| <a href="#wizard">Wizard Framework</a> section for more information.</p> |
| |
| <p><i>update</i> - Invoked on an installed feature when there is significant |
| change to some of the feature's dependencies. Some examples of a signficiant |
| change include: installing or installing a soft dependency, upgrading of a |
| dependent feature, and installing or uninstalling a hard dependency where an |
| "OR" constraint is involved. |
| </p> |
| |
| <p><i>upgrade</i> - Invoked when the user changes the version of a feature |
| that's already installed.</p> |
| |
| <p><i>activate</i> - Invoked when a project containing this feature is loaded. |
| The feature's author should use caution when taking advantage of this delegate, |
| since this will cause the plugin that contains the delegate to be loaded every |
| time any project containing this feature is loaded.</p> |
| |
| <p><i>deactivate</i> - Invoked when a project containing this feature is closed. |
| The feature's author should use caution when taking advantage of this delegate, |
| since this will cause the plugin that contains the delegate to be loaded every |
| time any project containing this feature is closed.</p> |
| |
| <table cellpadding="10"><tr><td bgcolor="#C0C0C0"> |
| <font size="-1" face="Arial"><p><b>Example:</b></p></font> |
| <font size="+0"><pre> |
| <extension point="...core.features"> |
| <feature-version id="web" version="1.0"> |
| ... |
| <delegate type="install" class="...WebFeatureInstallDelegate"/> |
| <delegate type="uninstall" class="...WebFeatureUninstallDelegate"/> |
| ... |
| </feature-version> |
| </extension> |
| </pre></font> |
| </td></tr></table> |
| |
| <p><b>Categories</b></p> |
| <hr /> |
| |
| <p>A category is a grouping of several related features that would frequently |
| be added to a project as a set. Categories allow the feature author to provide a |
| fine-grained feature breakdown for an expert user wihout complicating matters |
| for a novice. A feature can belong to at most one category.</p> |
| |
| <p><b>Presets</b></p> |
| <hr /> |
| <p>A preset is a user convenience mechanism for quickly selecting a set of |
| features. Presets are intended as a quick starting point for doing a certain |
| type of development. For instance a server vendor might create a preset that can |
| be used when developing exclusively for that server platform or there might |
| be presets for doing webservice development vs. web ui development. After |
| applying a preset, the user can further tweak the set of selected features and |
| change their configurations.</p> |
| |
| <p>A user can also define custom presets, which are stored in workspace |
| metadata. Once a custom preset is created it can be used just like a preset |
| defined through the extension point.</p> |
| |
| <p>Presets would manifest in the UI as a drop-down above the feature selection |
| panel. The list of presets will be filtered to only show presets that would |
| not conflict with fixed features. A preset is allowed to change the version of |
| a fixed feature, but not deselect it.</p> |
| |
| <table cellpadding="10"><tr><td bgcolor="#C0C0C0"> |
| <font size="-1" face="Arial"><p><b>Example:</b></p></font> |
| <font size="+0"><pre> |
| <extension point="...core.features"> |
| ... |
| <preset id="wls.web.preset"> |
| <label>WebLogic Web App</label> |
| <feature id="java" version="5.0"/> |
| <feature id="wtp.framework" version="1.0"/> |
| <feature id="web" version="1.0"/> |
| <feature id="wls.web" version="9.0" |
| <feature id="struts" version="1.1"/> |
| <feature id="wls.struts" version="9.0"/> |
| </preset> |
| ... |
| </extension> |
| </pre></font> |
| </td></tr></table> |
| |
| <p><b>Runtime Modeling</b></p> |
| <hr /> |
| <p>A runtime is a container or an environment that projects will execute within. |
| Sun Java VM and Apache Tomcat are both examples of a runtime. Some features can |
| only run on specific types of runtimes. For instance, a Web Module feature |
| cannot run on a base Sun Java VM runtime. It needs a J2EE server such as Apache |
| Tomcat. A vendor-specific feature might only run on that vendor's runtime.</p> |
| |
| <p>The framework provides a way to declare runtime types and to map features to |
| them. The runtimes are versioned and features can be mapped to either a specific |
| version, specific version or newer, or all versions. It is not necessary to map |
| all features to all runtimes that they will run on. If feature x depends on |
| feature y and feature x will run on all runtimes that y will run on, it is not |
| necessary to provide mappings for x. In fact, a feature will run on all runtimes |
| unless it is explicitly restricted by runtime mappings or features it depends |
| on.</p> |
| |
| <p>If the set of features that a runtime supports varries based on it's |
| configuration, the "runtime extension" concept can help in modeling these |
| situations. A feature can be mapped to either a runtime or a runtime extension. |
| A runtime can have any number of extensions.</p> |
| |
| <table cellpadding="10"><tr><td bgcolor="#C0C0C0"> |
| <font size="-1" face="Arial"><p><b>Example:</b></p></font> |
| <font size="+0"><pre> |
| <extension point="...core.runtime"> |
| ... |
| <runtime id="sun.vm" version="1.4"/> |
| <runtime id="sun.vm" version="5.0"/> |
| <runtime id="apache.tomcat" version="4.0"/> |
| <runtime id="apache.tomcat" version="5.0"/> |
| <runtime id="jboss" version="1.0"/> |
| <runtime-extension id="jboss.ejb.extension" version="1.0"/> |
| ... |
| <runtime-mapping> |
| <feature id="java" version="1.4"/> |
| <runtime id="sun.vm" version="1.4" allow-newer="true"/> |
| </runtime-mapping> |
| <runtime-mapping> |
| <feature id="java" version="5.0"/> |
| <runtime id="sun.vm" version="5.0" allow-newer="true"/> |
| </runtime-mapping> |
| <runtime-mapping> |
| <feature id="web" version="1.0"/> |
| <runtime id="apache.tomcat" version="4.0" allow-newer="true"/> |
| </runtime-mapping> |
| <runtime-mapping> |
| <feature id="web" version="1.0"/> |
| <runtime id="jboss" version="1.0"/> |
| </runtime-mapping> |
| <runtime-mapping> |
| <feature id="ejb" version="1.0"/> |
| <runtime-extension id="jboss.ejb.extension" version="1.0"/> |
| </runtime-mapping> |
| ... |
| </extension> |
| </pre></font> |
| </td></tr></table> |
| |
| <p>A runtime instance is formed by taking a particular version of the runtime |
| type and combining it with any applicable extensions. A runtime instance can |
| also "build-on" another runtime instance. For example, one can create "My JBoss" |
| runtime that's an instance of "jboss v.1.0" with "jboss.ejb.extension v.1.0" |
| installed and that builds on "My JVM Install" runtime instance. The framework |
| provides a way to register runtime instance, but tooling is left to runtime |
| vendors.</p> |
| |
| <p>A user can choose to associate the project with a particular runtime at the |
| time of creation. If the user chooses to do that, the selected runtime instance |
| is available to feature wizard pages and the delegates. The features can adjust |
| their behavior based on the selected runtime. One common use of this is for |
| classpath setup. A feature can ask the runtime if it can provide classpath |
| entries for it. If the runtime is unable to provide classpath entries for a |
| particular feature, or if no runtime is selected, the feature is responsible for |
| setting up the classpath on it's own. This might mean gathering additional |
| input from the user. When the user changes the runtime associated with a |
| project, all of the installed features are notified so that they can adjust |
| the classpath accordingly.</p> |
| |
| <b>Fixed Features</b> |
| <hr/> |
| |
| <p>While it would be possible to allow the user to pick from the complete list |
| of available features when creating a project, the generality of that would |
| likely lead to user confusion. As such, certain features can be "fixed" at |
| project creation to define a "project type". Any features that conflict with |
| the fixed features are not displayed to the user. The user cannot de-select a |
| fixed feature, but can change it's version.</p> |
| |
| <b><a name="wizard">Wizard Framework</a></b> |
| <hr/> |
| |
| <p>Part of the features framework is a wizard that provides a common way to add |
| and remove features. The wizard consists of a feature selection page followed |
| by pages associated with actions that the user takes in the feature selection |
| page (such as install feature or uninstall feature). The feature action pages are |
| displayed in dependency order. The wizard can either be used stand-alone on an |
| existing project or as part of a project creation wizard. In fact the framework |
| provides an abstract project creation wizard that prepends a page that allows |
| the user to specify project name and location. The abstract project creation |
| wizard is subclassed to specify the set of fixed features and which preset to |
| start with.</p> |
| |
| <p>Feature authors can register pages and the config objects through the |
| provided extension point. The config object will be instantiated and passed to |
| all of the pages. The same config object will then be passed to the delegate |
| implementing the action. The framework places only one restriction on the config |
| object: it has to have a zero-argument constructor.</p> |
| |
| <p>Wizard pages associated with particular feature can peek at the config of the |
| other features currently being operated on. That's done through the wizard |
| context that's available to all of the pages.</p> |
| |
| <table cellpadding="10"><tr><td bgcolor="#C0C0C0"> |
| <font size="-1" face="Arial"><p><b>Example:</b></p></font> |
| <font size="+0"><pre> |
| <extension point="...ui.wizard"> |
| ... |
| <wizard-pages feature="web" version="1.0"> |
| <install> |
| <config class="...WebFeatureInstallConfig"/> |
| <page class="...WebFeatureInstallPage1"/> |
| <page class="...WebFeatureInstallPage2"/> |
| </install> |
| <wizard-pages> |
| ... |
| </extension> |
| </pre></font> |
| </td></tr></table> |
| |
| <p/> |
| |
| <b>Open Issues</b> |
| <hr/> |
| |
| <ol> |
| <li> |
| Should this be kept inside WTP or contributed to eclipse core? |
| </li> |
| <li> |
| Are features a property of a project or of a component? |
| </li> |
| </ol> |
| |
| <b>Apendix A: Extension Points</b> |
| <hr/> |
| |
| <font size="+0"><pre> |
| <extension point="...core.features"> |
| <feature id=""> <i>(0 or more)</i> |
| <label>...</label> |
| <description>...</description> <i>(optional)</i> |
| <icon>...</icon> <i>(optional)</i> |
| <version-comparator class=""/> <i>(optional)</i> |
| <category>...</category> <i>(optional)</i> |
| </feature> |
| <feature-version feature="" version=""> <i>(0 or more)</i> |
| <constraint> <i>(optional)</i> |
| <i>[choice]</i> |
| <and> |
| ... |
| </and> |
| <or> |
| ... |
| </or> |
| <requires feature="" version="" allow-newer="" soft=""/> |
| <one-of set=""/> |
| <i>[/choice]</i> |
| </constraint> |
| <set-member id=""/> <i>(0 or more)</i> |
| <delegate type="" class=""/> <i>(0 or more)</i> |
| </feature-version> |
| <category name=""> <i>(0 or more)</i> |
| <label>...</label> |
| <description>...</description> <i>(optional)</i> |
| <icon>...</icon> <i>(optional)</i> |
| </category> |
| <preset id=""> <i>(0 or more)</i> |
| <label>...</label> |
| <feature id="" version=""/> <i>(1 or more)</i> |
| </preset> |
| </extension> |
| |
| <extension point="...core.runtime"> |
| <runtime id="" version=""/> <i>(0 or more)</i> |
| <runtime-extension id="" version=""/> <i>(0 or more)</i> |
| <runtime-mapping> <i>(0 or more)</i> |
| <feature id="" version=""/> |
| <i>[choice]</i> |
| <runtime id="" version="" allow-newer=""/> |
| <runtime-extension id="" version="" allow-newer=""/> |
| <i>[/choice]</i> |
| </runtime-mapping> |
| </extension> |
| |
| <extension point="...ui.wizard"> |
| <wizard-pages feature="" version=""> <i>(1 or more)</i> |
| <install> <i>(optional)</i> |
| <config class=""/> |
| <page class=""/> <i>(1 or more)</i> |
| </install> |
| <uninstall> <i>(optional)</i> |
| <config class=""/> |
| <page class=""/> <i>(1 or more)</i> |
| </uninstall> |
| <wizard-pages> |
| </extension> |
| </pre></font> |
| |
| </font> |
| </body> |
| </html> |