blob: 975ce7478a6693fc6232cb26966fa0c01b76e9ed [file] [log] [blame]
<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 &quot;optional&quot; clause is
&quot;true&quot;. </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 &gt; f) or (c = f and q &gt;= r))</p>
</li>
<li>compatible Version (a.b.c.q is compatible with d.e.f.r) if:
<p>a = d and ((b &gt; e) or (b = e and c &gt; f) or (b = e and c = f and q &gt;= r)) </p>
</li>
<li>greaterOrEqual Version (a.b.c.q is a higher version than d.e.f.r) if:
<p>a &gt; d or (a = d and b &gt; e) or (a = d and b = e and c &gt; f) or (a = d and b = e and c = f and q &gt;= 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 &quot;a&quot; to &quot;b&quot;
means plug-in &quot;a&quot; requires plug-in &quot;b&quot;. 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>