| <html> |
| <head><title>Plug-in registry resolution</title></head> |
| <body> |
| <h1>Plug-in registry resolution</h1> |
| <EM>Last update: April 23, 2003</EM> |
| <p><cite>This document is intended as a home for gathering as much information |
| about the expected semantics for the registry resolution algorithm as possible. |
| The goal is to keep this knowledge separately from the implementation (which |
| may tell a different story), in order to make easier for developers to enhance/fix |
| it or to develop a new algorithm for registry resolution. Comments and improvements |
| are welcome. </cite></p> |
| <h3>Soft pre-requisites</h3> |
| |
| <p>Soft pre-requisites are pre-requisites whose "optional" clause is |
| "true". </p> |
| |
| <p>Unsatisfied optional pre-requisites should be ignored (handled in the |
| same way as if they didn't exist at all).</p> |
| |
| <p>An optional pre-requisite will be ignored if any of the following |
| conditions apply:</p> |
| <ul> |
| <li>the required plug-in does not exist at all;</li> |
| <li>the required plug-in does exist but there are no versions |
| compatible with the required version;</li> |
| <li>the required plug-in exists and there is a version compatible |
| with the required version but the addition of this plug-in would cause |
| a conflict. A conflict arises if more than one version |
| of a given plug-in are required by other plug-ins, the versions are not compatible |
| with each other, and at least one of the versions is not a library |
| plug-in.</li> |
| </ul> |
| |
| <p>If an optional pre-requisite is ignored for any of the reasons listed above no |
| error message is generated (but an informational message may be output to |
| indicate that this pre-requisite is being ignored). Ignoring an optional |
| pre-requisite does not cause any plug-ins to be disabled. This causes |
| potential error conditions to be more complex. Each time we have a situation |
| where we have a conflict, we must first check to see if this is an optional |
| pre-requisite.</p> |
| |
| <h3>Version matching</h3> |
| |
| <p> The following applies for both plug-in pre-requisites and fragments matching their associated plug-ins.</p> |
| |
| <p>Versions have the following form: major.minor.service.qualifier, where major, minor and service |
| are integers and qualifier is a string.</p> |
| |
| <p>Version Numbers are matched as follows:</p><ul> |
| <li>if no version number is specified, pick the latest version that |
| satisfies any other related constraints (which is not necessarily |
| the latest one available in the registry);</li> |
| <li>perfect Version (a.b.c.q is a perfect match with d.e.f.r) if: |
| <p>a = d and b = e and c = f and q = r</p> |
| </li> |
| <li>equivalent Version (a.b.c.q is an equivalent match with d.e.f.r) if: |
| <p>a = d and b = e and ((c > f) or (c = f and q >= r))</p> |
| </li> |
| <li>compatible Version (a.b.c.q is compatible with d.e.f.r) if: |
| <p>a = d and ((b > e) or (b = e and c > f) or (b = e and c = f and q >= r)) </p> |
| </li> |
| <li>greaterOrEqual Version (a.b.c.q is a higher version than d.e.f.r) if: |
| <p>a > d or (a = d and b > e) or (a = d and b = e and c > f) or (a = d and b = e and c = f and q >= r)</p> |
| </li> |
| </ul> |
| |
| <p>Also:</p> |
| |
| <p>Two or more versions of the same plug-in can only be simultaneously |
| enabled if they all are <cite>library plug-ins</cite> (they do not expose extension |
| points nor contribute extensions).</p> |
| |
| <p>If a highest version of a plug-in is disabled for some reason, the new highest |
| version (if available) should replace it (when possible) - all plug-ins (not |
| fragments) that required the disabled version should refer to the new one. </p> |
| <h3>Questions to be answered</h3> |
| |
| <ol> |
| <li>What happens if a fragment contributes pre-requisites to a plug-in that |
| has multiple versions, and these pre-requisites cannot be satisfied? Currently, |
| the association of a fragment and a plug-in happens before the resolution |
| itself starts. So if a plug-in a fragment contributes to is disabled, the |
| fragment is lost (we don't try the next highest version). Should we? This |
| would cause all versions compatible with the fragment to be successively disabled, |
| if the fragment contributes unsatisfiable pre-requisites. Do we want that?</li> |
| </ol> |
| |
| <h3>Current registry resolution algorithm (RegistryResolver#resolve)</h3> |
| |
| <p>The existing resolution algorithm works based on a directed graph whose nodes |
| represent all versions of a given plug-in, and arc from "a" to "b" |
| means plug-in "a" requires plug-in "b". The algorithm starting |
| point is a set of root vertices (in-degree is 0) - plug-ins that are not required |
| by any other plug-ins. The resolution is done through a depth-first traversal |
| of the graph from the roots to their pre-requisites.</p> |
| |
| <ol> |
| <li>Initial state: Registry initially contains all plug-ins and fragments |
| discovered by the platform - no checking of pre-requisites has been done.</li> |
| <li>Model objects that are missing mandatory fields are ignored (#required*)</li> |
| <li>Create a map of plug-in descriptors where for each plug-in id there is a list |
| of plug-in descriptors that have the same id, ordered by plug-in version, higher to lower (#add)</li> |
| <li>For each fragment in the registry, add it to the list of fragments of the right plug-in descriptor |
| (the highest version that fits the matching criteria) (#linkFragments).</li> |
| <li>For each plug-in which has a fragment:<ul> |
| <li>For each fragment in the plug-in's fragment list (the highest |
| version only), add extensions, extension points, libraries and |
| pre-requisites to the plug-in (#resolvePluginFragments).</li> |
| </ul></li> |
| <li>Create a set with the identifiers of all root plug-ins in the registry.</li> |
| <li>If there are no roots, there is circularity - all plug-ins are disabled and |
| the process is finished (registry is emptied if it was to be trimmed).</li> |
| <li>For each plug-in identifier in the current set of roots:<ul> |
| <li>Look for the right version(s) to enable, doing a depth-first |
| traversal in its children (plug-ins that require it). This includes |
| ensuring: <ul> |
| <li>all mandatory pre-requisites are satisfied |
| (considering versions and match clauses);</li> |
| <li>there are no conflicts (no different versions are |
| required simultaneously of plug-ins that provide |
| extensions/extension points).</li> |
| <li>if a root is disabled, its direct children are promoted |
| to roots if they are not required by any other plug-ins.</li> |
| </ul></li> |
| </ul></li> |
| <li>If the registry is to be trimmed, delete any plug-ins which |
| are not enabled/do not have pre-requisites satisfied |
| (#resolvePluginRegistry).</li> |
| <li>If the registry is to be linked, link extensions to the targetted extension |
| points (#resolvePluginRegistry).</li> |
| </ol> |
| |
| <h3>Problems in the current registry resolution algorithm</h3> |
| |
| <ol> |
| <li>all versions of a plug-in are disabled when the version in use causes a |
| conflict - when a plug-in is disabled for causing a conflict, if there are |
| different versions available, the highest one should be selected and the resolution |
| should try to enable that one;</li> |
| <li>order should not matter - for instance, when a conflict is detected, all |
| plug-ins involved should be disabled not only the one that introduced the |
| conflict (bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34752">34752</a>);</li> |
| <li>fragments not associated with a plug-in or fragments not used because another |
| version of the same fragment exists should be trimmed when the user requests |
| it and currently are not (bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33911">33911</a>).</li> |
| <li>the resulting plug-in descriptor should indicate which portions came from |
| fragments (feature request <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23165">23165</a>).</li> |
| </ol> |
| </body> |
| </html> |