[
https://issues.apache.org/jira/browse/FELIX-5450?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Thomas Watson resolved FELIX-5450.
----------------------------------
Resolution: Fixed
I committed a fix along with two new tests.
> Fragments with multiple hosts can cause
> java.lang.ArrayIndexOutOfBoundsException
> --------------------------------------------------------------------------------
>
> Key: FELIX-5450
> URL: https://issues.apache.org/jira/browse/FELIX-5450
> Project: Felix
> Issue Type: Bug
> Components: Resolver
> Affects Versions: resolver-1.10.0
> Reporter: Thomas Watson
> Assignee: Thomas Watson
>
> The fix in FELIX-5389 for ShadowList is not complete. There are still cases
> where the underlying ArrayList from the CandidateSelector is reused in the
> ShadowList when it is not intended. This leads to exceptions like the
> following:
> java.lang.ArrayIndexOutOfBoundsException: -1
> at java.util.ArrayList.elementData(ArrayList.java:418)
> at java.util.ArrayList.set(ArrayList.java:446)
> at org.apache.felix.resolver.util.ShadowList.replace(ShadowList.java:81)
> at org.apache.felix.resolver.Candidates.prepare(Candidates.java:915)
> at
> org.apache.felix.resolver.ResolverImpl.getInitialCandidates(ResolverImpl.java:502)
> at
> org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:387)
> at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:375)
> at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:368)
> This is happening when there are multiple hosts for a single fragment and the
> fragment has a requirement that is getting resolved to a candidate from
> another host resource that also has at least one fragment.
> The issue comes up when replacing the capability from the host with a wrapped
> capability for the fragment requirement which is a payload requirement for
> more than one host. It should do this for each WrappedRequirement that is
> wrapping the payload requirement from the fragment to each host. The first
> WrappedRequirement has its candidates modified, but that changes the shared
> ArrayList of the candidates for each of the other WrappedRequirements for the
> other hosts. The fix for this is to ensure the ArrayList from a
> CandidateSelector is never shared with a ShadowList.
> But once I fixed this I ran into another strange issue that ended up causing
> Uses constraint errors like this:
> org.osgi.service.resolver.ResolutionException: Uses constraint violation.
> Unable to resolve resource host [osgi.identity; host] because it is exposed
> to package 'exporter' from resources exporter [osgi.identity; exporter] and
> exporter [osgi.identity; exporter] via two dependency chains.
> Chain 1:
> host [osgi.identity; host]
> import: (osgi.wiring.package=exporter)
> |
> export: osgi.wiring.package: exporter
> exporter [osgi.identity; exporter]
> Chain 2:
> host [osgi.identity; host]
> import: (osgi.wiring.package=exporter)
> |
> export: osgi.wiring.package: exporter
> exporter [osgi.identity; exporter]
> This only happens if a fragment has more than one host and the fragment and
> host have a requirement for a the same package. Additionally the capability
> that satisfies the payload requirement must come from a host that also has at
> least one fragment. The issue here is how we are finding CandidateSelectors
> of depending requirements when we need to replace a capability with a wrapped
> capability. There is a loop in the Candidates.prepare method which is says
> "Copy candidates for fragment requirements to the host.". This loop
> basically copies the candidates from the original requirement from the
> fragment to a CandidateSelector for the WrappedRequirement for the host. But
> it also removes the original requirement from the dependents for the
> capability. If there are multiple hosts this becomes problematic because
> this dependency set is used to find CandidateSelectors that need to be
> modified when wrapping a host. But since we remove the original requirement
> from the fragment that means any other hosts the fragment is attached to will
> not be discovered and therefore will not have the original capability
> properly replaced with the WrappedCapability. That makes the consistency
> check fail and give this bogus message that make it look like there are 2
> identical chains leading to the identical capability. But the two
> capabilities are different because one is wrapped and one is not.
> The fix is to separate out the inner loop that "Copy candidates for fragment
> requirements to the host." to a outer loop that is done before the main loop
> over the hostResources. This way we properly setup all the CandidateSelector
> for the payload WrappedRequirements before actually modifying the
> CandidateSelector capabilities with the WrappedCapabilities.
> Super long story short: Fragments are just horribly complex.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)