Skip to content

Fix FilterImpl.WrapperCapability: Filter.matches(Map) always throws - #554

Open
paulrutter wants to merge 3 commits into
masterfrom
fix-filterimpl-wrappercapability
Open

Fix FilterImpl.WrapperCapability: Filter.matches(Map) always throws#554
paulrutter wants to merge 3 commits into
masterfrom
fix-filterimpl-wrappercapability

Conversation

@paulrutter

Copy link
Copy Markdown
Contributor

org.apache.felix.framework.FilterImpl.WrapperCapability has two defects, both introduced by 466eb93 "[fw] reduce warning related to types Classes" — a generics cleanup that changed behaviour by accident. They surfaced while running the OSGi Core R8 TCK for #433, which reported 33 errors across BundleContextFilterTests and DivTests; both trace back here.

1. Filter.matches(Map) throws for any non-empty map

The constructor lost its assignment into a stray empty if block:

public WrapperCapability(Map<String, ?> map)
{
    super(null, null, Collections.emptyMap(), Collections.emptyMap());
        m_map = Collections.emptyMap();
        if(map != null ) {
    }
    m_map.putAll(map);
}

m_map refers to an immutable empty map, so putAll throws UnsupportedOperationException for any non-empty argument, and NullPointerException for a null one. It previously read:

m_map = (map == null) ? Collections.EMPTY_MAP : map;

which is restored here. Filter.matches(Map) has been unusable since April 2025, so this affects released versions independently of any Java version work.

2. WrapperCapability(ServiceReference) requires an OSGi Core 1.10 method

It was rewritten to new DictionaryToMap(sr.getProperties(), false). ServiceReference.getProperties() was only added in Core 1.10 and is not implemented by every ServiceReference — the TCK's own mock throws UnsupportedOperationException for it. Restored to the getPropertyKeys()/getProperty() loop, which every implementation supports.

Tests

Adds regression tests for both cases. They construct org.apache.felix.framework.FilterImpl directly, because FrameworkUtil.createFilter returns the unrelated org.osgi.framework.FilterImpl and does not exercise this code at all — worth knowing, as it is an easy trap when testing this class.

Verified both ways: the new tests fail with UnsupportedOperationException against current master and pass with the fix.

@stbischof — flagging you as the author of 466eb93 so you can sanity-check the intent. The generics conversion itself looks right; it just seems the m_map = map assignment and the property loop were lost in the edit. Happy to adjust if you had something else in mind for either constructor.

These are independent of the Java 25 work in #433, which is why they are proposed separately against master; #433 carries the same fix so its TCK run can pass, and that will drop out when this merges.

🤖 Generated with Claude Code

paulrutter and others added 2 commits August 29, 2026 22:41
Two defects were introduced in 466eb93 ("[fw] reduce warning related to types
Classes"), both in org.apache.felix.framework.FilterImpl.WrapperCapability. They were
found by the OSGi Core R8 TCK, which reported 33 errors across BundleContextFilterTests
and DivTests.

1. Filter.matches(Map) throws for any non-empty map.

The constructor lost its assignment into a stray empty if block:

    m_map = Collections.emptyMap();
    if(map != null ) {
    }
    m_map.putAll(map);

m_map therefore refers to an immutable empty map and putAll throws
UnsupportedOperationException, or NullPointerException when map is null. It
previously read:

    m_map = (map == null) ? Collections.EMPTY_MAP : map;

which is restored. Filter.matches(Map) has been unusable since April 2025.

2. WrapperCapability(ServiceReference) requires an OSGi Core 1.10 method.

It was rewritten to read properties via new DictionaryToMap(sr.getProperties(),
false). ServiceReference.getProperties() was only added in Core 1.10 and is not
implemented by every ServiceReference; the TCK's own mock throws
UnsupportedOperationException for it. Restored to the getPropertyKeys()/getProperty()
loop, which every implementation supports.

Adds regression tests for both. They exercise org.apache.felix.framework.FilterImpl
directly, since FrameworkUtil.createFilter returns the unrelated
org.osgi.framework.FilterImpl. Verified that both fail with
UnsupportedOperationException against the current code and pass with the fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The OSGi Core TCK currently cannot resolve on any JDK, so framework.tck fails before
executing a single test. That is what hid the FilterImpl defects fixed in this branch,
and it also means CI cannot demonstrate the fix without repairing it.

Two ranges were left behind when assertj-core was bumped from 3.27.3 to 3.27.7 in
#478:

- tck.bndrun still required assertj-core [3.27.3,3.27.4), so the bndrun could not be
  resolved at all: "assertj-core;version=[3.27.3,3.27.4) Not found in [...
  assertj-core;version=3.27.7 ...]".
- assertj-core 3.27.7 imports net.bytebuddy [1.18.0,2.0.0) but byte-buddy was pinned
  at 1.17.5, so assertj-core then failed to start with an unresolved
  osgi.wiring.package requirement.

Also removes a duplicate junit-platform-launcher dependency, which Maven reports as a
malformed model and warns it may reject in future.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@paulrutter

Copy link
Copy Markdown
Contributor Author

Added the TCK dependency fixes to this branch, because the TCK cannot resolve on master at all and it is the thing that demonstrates the FilterImpl fix.

CI on the first push failed with:

Error : assertj-core;version=[3.27.3,3.27.4) Not found in [... assertj-core;version=3.27.7 ...]

That is pre-existing master breakage, not fallout from this change. Two ranges were left behind when assertj-core was bumped 3.27.3 to 3.27.7 in #478:

  1. tck.bndrun still required assertj-core [3.27.3,3.27.4), so the bndrun could not resolve and no test ran.
  2. Once that resolves, assertj-core 3.27.7 imports net.bytebuddy [1.18.0,2.0.0) while byte-buddy was pinned at 1.17.5, so assertj-core failed to start with an unresolved osgi.wiring.package requirement.

Both are fixed here, along with a duplicate junit-platform-launcher declaration that Maven flags as a malformed model.

Scope note: #433 additionally moves the bnd plugins and biz.aQute.junit to 7.4.0, because bnd 6.4.1's launcher calls Policy.setPolicy() unguarded and Java 24+ rejects that. That one is JDK-24-and-later specific, so it is deliberately left in #433 rather than pulled in here — master's matrix is 17, 21 and 23, which are unaffected.

With these in place the TCK should actually execute on this branch, which is what makes the FilterImpl fix verifiable rather than just asserted.

The framework step ran clean verify, which does not install. The TCK is a separate
Maven invocation, so it resolves org.apache.felix.framework from the repository
rather than from the build that just ran, and org.apache.felix.framework
7.1.0-SNAPSHOT exists in apache.snapshots. Resolution therefore succeeded against the
published snapshot and the TCK never exercised the code under test.

That matters for this pull request in particular: the FilterImpl defects it fixes are
exactly what the TCK reports, so a green TCK run proved nothing while the framework
was being resolved from elsewhere.

Running clean install makes the TCK test the framework this build produced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@paulrutter

Copy link
Copy Markdown
Contributor Author

Added a CI fix, because the green TCK run on the previous commit did not actually validate anything in this PR.

The workflow ran --file framework/pom.xml clean verify, which does not install. The TCK is a separate Maven invocation, so it resolves org.apache.felix.framework from the repository rather than from the build that just ran — and 7.1.0-SNAPSHOT exists in apache.snapshots. Resolution therefore succeeded against the published snapshot, and the TCK never exercised the code under test.

That matters most for this PR specifically: the FilterImpl defects fixed here are exactly what the TCK reports, so a green TCK proved nothing while the framework was being resolved from elsewhere.

This surfaced on #433, where renaming the framework to 8.0.0-SNAPSHOT removed the fallback and turned the silent substitution into a loud error:

Could not find artifact org.apache.felix:org.apache.felix.framework:jar:8.0.0-SNAPSHOT
in apache.snapshots

The step now runs clean install, so the TCK tests the framework this build produces. The next run here is the first one whose TCK result actually says something about this change.

For what it is worth, the fix was verified locally against the real thing: the TCK went from 33 errors, to 14 after repairing the Map constructor, to BUILD SUCCESS with 0 errors after repairing the ServiceReference constructor. The unit tests added here were also checked in both directions — they fail with UnsupportedOperationException against current master and pass with the fix.

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.

1 participant