Search in sources :

Example 6 with HostedCapability

use of org.osgi.service.resolver.HostedCapability in project felix by apache.

the class Candidates method prepare.

/**
 * Merges fragments into their hosts. It does this by wrapping all host
 * modules and attaching their selected fragments, removing all unselected
 * fragment modules, and replacing all occurrences of the original fragments
 * in the internal data structures with the wrapped host modules instead.
 * Thus, fragment capabilities and requirements are merged into the
 * appropriate host and the candidates for the fragment now become
 * candidates for the host. Likewise, any module depending on a fragment now
 * depend on the host. Note that this process is sort of like
 * multiplication, since one fragment that can attach to two hosts
 * effectively gets multiplied across the two hosts. So, any modules being
 * satisfied by the fragment will end up having the two hosts as potential
 * candidates, rather than the single fragment.
 *
 * @return  ResolutionError if the removal of any unselected fragments
 * result in the root module being unable to resolve.
 */
public ResolutionError prepare() {
    // Maps a host capability to a map containing its potential fragments;
    // the fragment map maps a fragment symbolic name to a map that maps
    // a version to a list of fragments requirements matching that symbolic
    // name and version.
    Map<Capability, Map<String, Map<Version, List<Requirement>>>> hostFragments = getHostFragments();
    // This method performs the following steps:
    // 1. Select the fragments to attach to a given host.
    // 2. Wrap hosts and attach fragments.
    // 3. Remove any unselected fragments. This is necessary because
    // other revisions may depend on the capabilities of unselected
    // fragments, so we need to remove the unselected fragments and
    // any revisions that depends on them, which could ultimately cause
    // the entire resolve to fail.
    // 4. Replace all fragments with any host it was merged into
    // (effectively multiplying it).
    // * This includes setting candidates for attached fragment
    // requirements as well as replacing fragment capabilities
    // with host's attached fragment capabilities.
    // Steps 1 and 2
    List<WrappedResource> hostResources = new ArrayList<WrappedResource>();
    List<Resource> unselectedFragments = new ArrayList<Resource>();
    for (Entry<Capability, Map<String, Map<Version, List<Requirement>>>> hostEntry : hostFragments.entrySet()) {
        // Step 1
        Capability hostCap = hostEntry.getKey();
        Map<String, Map<Version, List<Requirement>>> fragments = hostEntry.getValue();
        List<Resource> selectedFragments = new ArrayList<Resource>();
        for (Entry<String, Map<Version, List<Requirement>>> fragEntry : fragments.entrySet()) {
            boolean isFirst = true;
            for (Entry<Version, List<Requirement>> versionEntry : fragEntry.getValue().entrySet()) {
                for (Requirement hostReq : versionEntry.getValue()) {
                    // each fragment with a given symbolic name.
                    if (isFirst) {
                        selectedFragments.add(hostReq.getResource());
                        isFirst = false;
                    } else // For any fragment that wasn't selected, remove the
                    // current host as a potential host for it and remove it
                    // as a dependent on the host. If there are no more
                    // potential hosts for the fragment, then mark it as
                    // unselected for later removal.
                    {
                        m_dependentMap.get(hostCap).remove(hostReq);
                        CandidateSelector hosts = removeCandidate(hostReq, hostCap);
                        if (hosts.isEmpty()) {
                            unselectedFragments.add(hostReq.getResource());
                        }
                    }
                }
            }
        }
        // Step 2
        WrappedResource wrappedHost = new WrappedResource(hostCap.getResource(), selectedFragments);
        hostResources.add(wrappedHost);
        m_allWrappedHosts.put(hostCap.getResource(), wrappedHost);
    }
    // Step 3
    for (Resource fragment : unselectedFragments) {
        removeResource(fragment, new FragmentNotSelectedError(fragment));
    }
    // First copy candidates for wrapped requirements to the host.
    for (WrappedResource hostResource : hostResources) {
        for (Requirement r : hostResource.getRequirements(null)) {
            Requirement origReq = ((WrappedRequirement) r).getDeclaredRequirement();
            CandidateSelector cands = m_candidateMap.get(origReq);
            if (cands != null) {
                if (cands instanceof ShadowList) {
                    m_candidateMap.put(r, ShadowList.deepCopy((ShadowList) cands));
                } else {
                    m_candidateMap.put(r, cands.copy());
                }
                for (Capability cand : cands.getRemainingCandidates()) {
                    Set<Requirement> dependents = m_dependentMap.get(cand);
                    dependents.remove(origReq);
                    dependents.add(r);
                }
            }
        }
    }
    for (WrappedResource hostResource : hostResources) {
        // from the merged host.
        for (Capability c : hostResource.getCapabilities(null)) {
            // really be attached to the original host, not the wrapper.
            if (!c.getNamespace().equals(HostNamespace.HOST_NAMESPACE)) {
                Capability origCap = ((HostedCapability) c).getDeclaredCapability();
                // Note that you might think we could remove the original cap
                // from the dependent map, but you can't since it may come from
                // a fragment that is attached to multiple hosts, so each host
                // will need to make their own copy.
                CopyOnWriteSet<Requirement> dependents = m_dependentMap.get(origCap);
                if (dependents != null) {
                    dependents = new CopyOnWriteSet<Requirement>(dependents);
                    m_dependentMap.put(c, dependents);
                    for (Requirement r : dependents) {
                        // We have synthesized hosted capabilities for all
                        // fragments that have been attached to hosts by
                        // wrapping the host bundle and their attached
                        // fragments. We need to use the ResolveContext to
                        // determine the proper priority order for hosted
                        // capabilities since the order may depend on the
                        // declaring host/fragment combination. However,
                        // internally we completely wrap the host revision
                        // and make all capabilities/requirements point back
                        // to the wrapped host not the declaring host. The
                        // ResolveContext expects HostedCapabilities to point
                        // to the declaring revision, so we need two separate
                        // candidate lists: one for the ResolveContext with
                        // HostedCapabilities pointing back to the declaring
                        // host and one for the resolver with HostedCapabilities
                        // pointing back to the wrapped host. We ask the
                        // ResolveContext to insert its appropriate HostedCapability
                        // into its list, then we mirror the insert into a
                        // shadow list with the resolver's HostedCapability.
                        // We only need to ask the ResolveContext to find
                        // the insert position for fragment caps since these
                        // were synthesized and we don't know their priority.
                        // However, in the resolver's candidate list we need
                        // to replace all caps with the wrapped caps, no
                        // matter if they come from the host or fragment,
                        // since we are completing replacing the declaring
                        // host and fragments with the wrapped host.
                        CandidateSelector cands = m_candidateMap.get(r);
                        ShadowList shadow;
                        if (!(cands instanceof ShadowList)) {
                            shadow = ShadowList.createShadowList(cands);
                            m_candidateMap.put(r, shadow);
                            cands = shadow;
                        } else {
                            shadow = (ShadowList) cands;
                        }
                        // shadow copy of the list accordingly.
                        if (!origCap.getResource().equals(hostResource.getDeclaredResource())) {
                            shadow.insertHostedCapability(m_session.getContext(), (HostedCapability) c, new SimpleHostedCapability(hostResource.getDeclaredResource(), origCap));
                        } else // If the original capability is from the host, then
                        // we just need to replace it in the shadow list.
                        {
                            shadow.replace(origCap, c);
                        }
                    }
                }
            }
        }
    }
    // selecting fragments/singletons.
    for (Resource resource : m_session.getMandatoryResources()) {
        if (!isPopulated(resource)) {
            return getResolutionError(resource);
        }
    }
    populateSubstitutables();
    m_candidateMap.trim();
    m_dependentMap.trim();
    // mark the selectors as unmodifiable now
    m_candidateSelectorsUnmodifiable.set(true);
    return null;
}
Also used : Version(org.osgi.framework.Version) HostedCapability(org.osgi.service.resolver.HostedCapability) HostedCapability(org.osgi.service.resolver.HostedCapability)

Example 7 with HostedCapability

use of org.osgi.service.resolver.HostedCapability in project rt.equinox.framework by eclipse.

the class Candidates method prepare.

/**
 * Merges fragments into their hosts. It does this by wrapping all host
 * modules and attaching their selected fragments, removing all unselected
 * fragment modules, and replacing all occurrences of the original fragments
 * in the internal data structures with the wrapped host modules instead.
 * Thus, fragment capabilities and requirements are merged into the
 * appropriate host and the candidates for the fragment now become
 * candidates for the host. Likewise, any module depending on a fragment now
 * depend on the host. Note that this process is sort of like
 * multiplication, since one fragment that can attach to two hosts
 * effectively gets multiplied across the two hosts. So, any modules being
 * satisfied by the fragment will end up having the two hosts as potential
 * candidates, rather than the single fragment.
 *
 * @return  ResolutionError if the removal of any unselected fragments
 * result in the root module being unable to resolve.
 */
public ResolutionError prepare() {
    // Maps a host capability to a map containing its potential fragments;
    // the fragment map maps a fragment symbolic name to a map that maps
    // a version to a list of fragments requirements matching that symbolic
    // name and version.
    Map<Capability, Map<String, Map<Version, List<Requirement>>>> hostFragments = getHostFragments();
    // This method performs the following steps:
    // 1. Select the fragments to attach to a given host.
    // 2. Wrap hosts and attach fragments.
    // 3. Remove any unselected fragments. This is necessary because
    // other revisions may depend on the capabilities of unselected
    // fragments, so we need to remove the unselected fragments and
    // any revisions that depends on them, which could ultimately cause
    // the entire resolve to fail.
    // 4. Replace all fragments with any host it was merged into
    // (effectively multiplying it).
    // * This includes setting candidates for attached fragment
    // requirements as well as replacing fragment capabilities
    // with host's attached fragment capabilities.
    // Steps 1 and 2
    List<WrappedResource> hostResources = new ArrayList<WrappedResource>();
    List<Resource> unselectedFragments = new ArrayList<Resource>();
    for (Entry<Capability, Map<String, Map<Version, List<Requirement>>>> hostEntry : hostFragments.entrySet()) {
        // Step 1
        Capability hostCap = hostEntry.getKey();
        Map<String, Map<Version, List<Requirement>>> fragments = hostEntry.getValue();
        List<Resource> selectedFragments = new ArrayList<Resource>();
        for (Entry<String, Map<Version, List<Requirement>>> fragEntry : fragments.entrySet()) {
            boolean isFirst = true;
            for (Entry<Version, List<Requirement>> versionEntry : fragEntry.getValue().entrySet()) {
                for (Requirement hostReq : versionEntry.getValue()) {
                    // each fragment with a given symbolic name.
                    if (isFirst) {
                        selectedFragments.add(hostReq.getResource());
                        isFirst = false;
                    } else // For any fragment that wasn't selected, remove the
                    // current host as a potential host for it and remove it
                    // as a dependent on the host. If there are no more
                    // potential hosts for the fragment, then mark it as
                    // unselected for later removal.
                    {
                        m_dependentMap.get(hostCap).remove(hostReq);
                        CandidateSelector hosts = removeCandidate(hostReq, hostCap);
                        if (hosts.isEmpty()) {
                            unselectedFragments.add(hostReq.getResource());
                        }
                    }
                }
            }
        }
        // Step 2
        WrappedResource wrappedHost = new WrappedResource(hostCap.getResource(), selectedFragments);
        hostResources.add(wrappedHost);
        m_allWrappedHosts.put(hostCap.getResource(), wrappedHost);
    }
    // Step 3
    for (Resource fragment : unselectedFragments) {
        removeResource(fragment, new FragmentNotSelectedError(fragment));
    }
    // First copy candidates for wrapped requirements to the host.
    for (WrappedResource hostResource : hostResources) {
        for (Requirement r : hostResource.getRequirements(null)) {
            Requirement origReq = ((WrappedRequirement) r).getDeclaredRequirement();
            CandidateSelector cands = m_candidateMap.get(origReq);
            if (cands != null) {
                if (cands instanceof ShadowList) {
                    m_candidateMap.put(r, ShadowList.deepCopy((ShadowList) cands));
                } else {
                    m_candidateMap.put(r, cands.copy());
                }
                for (Capability cand : cands.getRemainingCandidates()) {
                    Set<Requirement> dependents = m_dependentMap.get(cand);
                    dependents.remove(origReq);
                    dependents.add(r);
                }
            }
        }
    }
    for (WrappedResource hostResource : hostResources) {
        // from the merged host.
        for (Capability c : hostResource.getCapabilities(null)) {
            // really be attached to the original host, not the wrapper.
            if (!c.getNamespace().equals(HostNamespace.HOST_NAMESPACE)) {
                Capability origCap = ((HostedCapability) c).getDeclaredCapability();
                // Note that you might think we could remove the original cap
                // from the dependent map, but you can't since it may come from
                // a fragment that is attached to multiple hosts, so each host
                // will need to make their own copy.
                CopyOnWriteSet<Requirement> dependents = m_dependentMap.get(origCap);
                if (dependents != null) {
                    dependents = new CopyOnWriteSet<Requirement>(dependents);
                    m_dependentMap.put(c, dependents);
                    for (Requirement r : dependents) {
                        // We have synthesized hosted capabilities for all
                        // fragments that have been attached to hosts by
                        // wrapping the host bundle and their attached
                        // fragments. We need to use the ResolveContext to
                        // determine the proper priority order for hosted
                        // capabilities since the order may depend on the
                        // declaring host/fragment combination. However,
                        // internally we completely wrap the host revision
                        // and make all capabilities/requirements point back
                        // to the wrapped host not the declaring host. The
                        // ResolveContext expects HostedCapabilities to point
                        // to the declaring revision, so we need two separate
                        // candidate lists: one for the ResolveContext with
                        // HostedCapabilities pointing back to the declaring
                        // host and one for the resolver with HostedCapabilities
                        // pointing back to the wrapped host. We ask the
                        // ResolveContext to insert its appropriate HostedCapability
                        // into its list, then we mirror the insert into a
                        // shadow list with the resolver's HostedCapability.
                        // We only need to ask the ResolveContext to find
                        // the insert position for fragment caps since these
                        // were synthesized and we don't know their priority.
                        // However, in the resolver's candidate list we need
                        // to replace all caps with the wrapped caps, no
                        // matter if they come from the host or fragment,
                        // since we are completing replacing the declaring
                        // host and fragments with the wrapped host.
                        CandidateSelector cands = m_candidateMap.get(r);
                        ShadowList shadow;
                        if (!(cands instanceof ShadowList)) {
                            shadow = ShadowList.createShadowList(cands);
                            m_candidateMap.put(r, shadow);
                            cands = shadow;
                        } else {
                            shadow = (ShadowList) cands;
                        }
                        // shadow copy of the list accordingly.
                        if (!origCap.getResource().equals(hostResource.getDeclaredResource())) {
                            shadow.insertHostedCapability(m_session.getContext(), (HostedCapability) c, new SimpleHostedCapability(hostResource.getDeclaredResource(), origCap));
                        } else // If the original capability is from the host, then
                        // we just need to replace it in the shadow list.
                        {
                            shadow.replace(origCap, c);
                        }
                    }
                }
            }
        }
    }
    // selecting fragments/singletons.
    for (Resource resource : m_session.getMandatoryResources()) {
        if (!isPopulated(resource)) {
            return getResolutionError(resource);
        }
    }
    populateSubstitutables();
    m_candidateMap.trim();
    m_dependentMap.trim();
    // mark the selectors as unmodifiable now
    m_candidateSelectorsUnmodifiable.set(true);
    return null;
}
Also used : Version(org.osgi.framework.Version) HostedCapability(org.osgi.service.resolver.HostedCapability) HostedCapability(org.osgi.service.resolver.HostedCapability)

Aggregations

HostedCapability (org.osgi.service.resolver.HostedCapability)7 Capability (org.osgi.resource.Capability)5 ArrayList (java.util.ArrayList)4 Collection (java.util.Collection)4 List (java.util.List)3 Requirement (org.osgi.resource.Requirement)3 Resource (org.osgi.resource.Resource)3 ResolveContext (org.osgi.service.resolver.ResolveContext)3 HashMap (java.util.HashMap)2 Map (java.util.Map)2 Version (org.osgi.framework.Version)2 Wiring (org.osgi.resource.Wiring)2 BufferedReader (java.io.BufferedReader)1 File (java.io.File)1 InputStream (java.io.InputStream)1 Logger (org.apache.felix.resolver.Logger)1 ResolverImpl (org.apache.felix.resolver.ResolverImpl)1 CandidateComparator (org.apache.felix.resolver.test.util.CandidateComparator)1 CapabilitySet (org.apache.felix.resolver.test.util.CapabilitySet)1 GenericCapability (org.apache.felix.resolver.test.util.GenericCapability)1