Skip to content

Support Eclipse features on -buildpath and container paths (#7322) - #7339

Open
peterkir wants to merge 1 commit into
masterfrom
ecl-fea-buildpath
Open

Support Eclipse features on -buildpath and container paths (#7322)#7339
peterkir wants to merge 1 commit into
masterfrom
ecl-fea-buildpath

Conversation

@peterkir

Copy link
Copy Markdown
Contributor

Features are now first-class citizens on -buildpath, -testpath, -runpath and -runbundles. The canonical syntax is:

-buildpath: org.eclipse.e4.rcp;version='4.40.0';type=org.eclipse.update.feature

A feature expands to its member bundles: references and
recursively, with platform filtering and exact→highest version fallback.

Core changes (biz.aQute.bndlib):

  • Container.TYPE.FEATURE with member expansion via Project.getFeatureMembers()
  • Type-aware version lookup via Repository.findProviders (not RepositoryPlugin.versions)
  • EclipsePlatform matcher for os/ws/arch platform filters
  • Project.getBundles() flattens features for all consumers (classpath, launcher, IDE)

Index changes (biz.aQute.repository):

  • Feature.toResource() enrichment with bnd.relation/id/version/type/os/ws/arch attributes
  • P2Indexer self-healing reindex for stale caches + .feature.jar cache-link suffix

UI changes (bndtools.core):

  • RepositoryBundleSelectionPart: canonical clause on DND and wizard add
  • SelectionDragAdapter: text drag produces canonical clause
  • VersionedClauseLabelProvider: feature icon in buildpath list
  • RepoBundleSelectionWizardPage: type-aware selection keying

SWTBot infrastructure (bndtools.core.test):

  • launch.rendered.bnd: RenderedLauncher for real Eclipse widgets
  • swtbot.tests.bnd: SWTBot test bundle with fixture workspace
  • FeatureBuildPathWizardSwtbotTest: Add Bundle dialog feature selection
  • FeatureBuildPathDndSwtbotTest: Repositories view drag→Build Path

Tests:

  • FeatureBuildpathTest (6 cases: nested, platform filter, cycles, fallback, optional, error)
  • FeatureParserTest.testMemberRelationAttributes (enrichment contract)
  • SWTBot UI tests (green on win32)

API changes:

  • aQute.bnd.build 4.7.1 → 4.8.0 (Container.TYPE.FEATURE)
  • aQute.bnd.osgi.resource 5.1.0 → 5.2.0 (TYPE_ECLIPSE_FEATURE, FEATURE_RELATION_*)
  • aQute.p2.provider 1.0.0 → 1.1.0 (relation attributes)

All changes additive; full backward compatibility.

Comment on lines +38 to +43
* An Eclipse feature (identity type
* {@code org.eclipse.update.feature}). A feature is a container of
* included bundles and included features; on a path it expands to its
* members, see {@link Container#getMembers()}.
*/
FEATURE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just thought: Since this is core bnd, we should maybe be careful about wording and don't make it specific for "Eclipse". But since the "OSGi-Feature-Launcher" & OSGi Feature Runtime is a new "thing" we shoukd maybe just call it FEATURE. Eclipse would be just one specific instance of a feature and OSGi feature could be another thing.

@timothyjward @peterkir @juergen-albert

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch. I will rename it to ECLIPSE_FEATURE

@chrisrueger chrisrueger Jul 31, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No sorry, I mean the exact opposite.
the enum should be called FEATURE but also the javadoc should only talk about "feature" and not "Eclipse Feature" (if anything, then maybe only mention Eclipse as an example of a feature).

The word Eclipse should only start appearing in "Eclipse land" which is e.g. the P2Repo/P2Indexer

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the osgi.identity is really org.eclipse.update.feature, which is eclipse specific, the constant should also mention that it is an eclipse feature and not only a feature.
There OSGi features, Eclipse Feature, Karaf Features - and those needs to be distinguished properly.
So I would use the ECLIPSE_FEATURE constant.

@chrisrueger chrisrueger Aug 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's talk this week :) maybe I wasn't clear but my idea is basically that Project does not know "Eclipse" but just knows "type" and if type is present it delegates all the work to the Repositories by asking each repo if it can handle the type (e.g. org.eclipse.update.feature) (P2Repository knows about Eclipse features) .
org.eclipse.update.feature would just be a String.

Example

Developer writes:

-buildpath: org.eclipse.e4.rcp;version=4.40.0;type=org.eclipse.update.feature

The type=org.eclipse.update.feature flows through as an attribute
and only P2Repository recognizes it and expands it. The other repos ignore it.

Container{
public enum TYPE {
    REPO,
    PROJECT,
    EXTERNAL,
    LIBRARY,
    ERROR,
    TYPED_RESOURCE  // Generic: any typed OSGi resource that needs expansion
}
}

For that we may need to extend RepositoryPlugin to handle your current method Project.getFeatureMembers()

public interface RepositoryPlugin {
    // ... existing methods ...
    
    /**
     * Expand a typed resource (e.g., Eclipse feature) into its constituent bundles.
     * Repositories that don't support the requested type should return null.
     * 
     * @param bsn the identity of the resource
     * @param version the version
     * @param type the identity type (e.g., "org.eclipse.update.feature")
     * @param attrs additional attributes from the buildpath clause
     * @return list of constituent containers, or null if this repository doesn't handle this type
     */
    default List<Container> expandResource(String bsn, String version, String type, Map<String, String> attrs) throws Exception {
        return null; // repositories that don't handle expansion return null
    }
}

The P2Repository can handle Eclipse Feature specific logic (basically most of what Project.getFeatureMembers() contains in the current PR

public class P2Repository extends BaseRepository implements RepositoryPlugin {
    
    @Override
    public List<Container> expandResource(String bsn, String version, String type, 
                                         Map<String, String> attrs) throws Exception {
        // Only handle Eclipse features
        if (!ResourceUtils.TYPE_ECLIPSE_FEATURE.equals(type)) {
            return null;  // Not our type
        }
        
        // All Eclipse-specific logic HERE in P2Repository where it belongs:
        return members;
    }
}

And Project.java only delegates to the Repositories:


// In Project.toContainer()
else if (attrs != null && attrs.get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE) != null)
    container = new Container(this, bsn, range, Container.TYPE.TYPED_RESOURCE, f, null, attrs, db);
else
    container = new Container(this, bsn, range, Container.TYPE.REPO, f, null, attrs, db);

List<Container> getMembers(Set<String> visitedFeatures) throws Exception {
    List<Container> result = newList();
        
    // Typed resources delegate to repository
    if (getType() == TYPE.TYPED_RESOURCE) {
        String resourceType = getIdentityType();
        
        // Ask each repository if it can expand this type
        for (RepositoryPlugin repo : project.getRepositories()) {
            List<Container> members = repo.expandResource(
                getBundleSymbolicName(),
                getVersion(),
                resourceType,
                getAttributes()
            );
            
            if (members != null) {
                return result;
            }
        }
        
        // No repository could expand it
    }
}
  • New feature types (e.g. Karaf, OSGi...) don't require changes to Container.TYPE enum and no changes to Project.java
  • Just implement expandResource() in the repository
  • One enum value handles all typed resources

Features are now first-class citizens on -buildpath, -testpath, -runpath and
-runbundles. The canonical syntax is:

    -buildpath: org.eclipse.e4.rcp;version='4.40.0';type=org.eclipse.update.feature

A feature expands to its member bundles: <plugin> references and <includes>
recursively, with platform filtering and exact→highest version fallback.

Core changes (biz.aQute.bndlib):
- Container.TYPE.FEATURE with member expansion via Project.getFeatureMembers()
- Type-aware version lookup via Repository.findProviders (not RepositoryPlugin.versions)
- EclipsePlatform matcher for os/ws/arch platform filters
- Project.getBundles() flattens features for all consumers (classpath, launcher, IDE)

Index changes (biz.aQute.repository):
- Feature.toResource() enrichment with bnd.relation/id/version/type/os/ws/arch attributes
- P2Indexer self-healing reindex for stale caches + .feature.jar cache-link suffix

UI changes (bndtools.core):
- RepositoryBundleSelectionPart: canonical clause on DND and wizard add
- SelectionDragAdapter: text drag produces canonical clause
- VersionedClauseLabelProvider: feature icon in buildpath list
- RepoBundleSelectionWizardPage: type-aware selection keying

SWTBot infrastructure (bndtools.core.test):
- launch.rendered.bnd: RenderedLauncher for real Eclipse widgets
- swtbot.tests.bnd: SWTBot test bundle with fixture workspace
- FeatureBuildPathWizardSwtbotTest: Add Bundle dialog feature selection
- FeatureBuildPathDndSwtbotTest: Repositories view drag→Build Path

Tests:
- FeatureBuildpathTest (6 cases: nested, platform filter, cycles, fallback, optional, error)
- FeatureParserTest.testMemberRelationAttributes (enrichment contract)
- SWTBot UI tests (green on win32)

API changes:
- aQute.bnd.build 4.7.1 → 4.8.0 (Container.TYPE.FEATURE)
- aQute.bnd.osgi.resource 5.1.0 → 5.2.0 (TYPE_ECLIPSE_FEATURE, FEATURE_RELATION_*)
- aQute.p2.provider 1.0.0 → 1.1.0 (relation attributes)

All changes additive; full backward compatibility.

Signed-off-by: Peter Kirschner <peter@klib.io>
@peterkir
peterkir force-pushed the ecl-fea-buildpath branch from caa5d30 to fc6c3ec Compare August 4, 2026 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants