Search in sources :

Example 31 with BundleCapability

use of org.osgi.framework.wiring.BundleCapability in project felix-dev by apache.

the class StatefulResolver method selectSingletonsUsingHooks.

/*
     * Groups singletons based on resolver hook filtering and then selects
     * the singleton from each group with the highest version that is in
     * the resolver hook whitelist. No selection is made if a group already
     * has a resolved singleton in it.
     */
private void selectSingletonsUsingHooks(ResolverHookRecord record) throws BundleException {
    // Convert singleton bundle revision map into a map using
    // bundle capabilities instead, since this is what the resolver
    // hooks require.
    Map<BundleCapability, Collection<BundleCapability>> allCollisions = new HashMap<BundleCapability, Collection<BundleCapability>>();
    for (Entry<String, List<BundleRevision>> entry : m_singletons.entrySet()) {
        Collection<BundleCapability> bundleCaps = new ArrayList<BundleCapability>();
        for (BundleRevision br : entry.getValue()) {
            List<BundleCapability> caps = br.getDeclaredCapabilities(BundleRevision.BUNDLE_NAMESPACE);
            if (!caps.isEmpty()) {
                bundleCaps.add(caps.get(0));
            }
        }
        for (BundleCapability bc : bundleCaps) {
            Collection<BundleCapability> capCopy = new ShrinkableCollection<BundleCapability>(new ArrayList<BundleCapability>(bundleCaps));
            capCopy.remove(bc);
            allCollisions.put(bc, capCopy);
        }
    }
    // Invoke hooks to allow them to filter singleton collisions.
    for (ResolverHook hook : record.getResolverHooks()) {
        for (Entry<BundleCapability, Collection<BundleCapability>> entry : allCollisions.entrySet()) {
            try {
                Felix.m_secureAction.invokeResolverHookSingleton(hook, entry.getKey(), entry.getValue());
            } catch (Throwable ex) {
                throw new BundleException("Resolver hook exception: " + ex.getMessage(), BundleException.REJECTED_BY_HOOK, ex);
            }
        }
    }
    // Create groups according to how the resolver hooks filtered the
    // collisions.
    List<List<BundleRevision>> groups = new ArrayList<List<BundleRevision>>();
    while (!allCollisions.isEmpty()) {
        BundleCapability target = allCollisions.entrySet().iterator().next().getKey();
        groups.add(groupSingletons(allCollisions, target, new ArrayList<BundleRevision>()));
    }
    // Now select the singletons available for this resolve operation.
    for (List<BundleRevision> group : groups) {
        selectSingleton(record, group);
    }
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ResolverHook(org.osgi.framework.hooks.resolver.ResolverHook) ArrayList(java.util.ArrayList) BundleRevision(org.osgi.framework.wiring.BundleRevision) ShrinkableCollection(org.apache.felix.framework.util.ShrinkableCollection) Collection(java.util.Collection) List(java.util.List) ArrayList(java.util.ArrayList) ShrinkableCollection(org.apache.felix.framework.util.ShrinkableCollection) BundleException(org.osgi.framework.BundleException) BundleCapability(org.osgi.framework.wiring.BundleCapability)

Example 32 with BundleCapability

use of org.osgi.framework.wiring.BundleCapability in project felix-dev by apache.

the class StatefulResolver method indexCapabilities.

private synchronized void indexCapabilities(BundleRevision br) {
    List<BundleCapability> caps = (Util.isFragment(br) || (br.getWiring() == null)) ? br.getDeclaredCapabilities(null) : br.getWiring().getCapabilities(null);
    if (caps != null) {
        for (BundleCapability cap : caps) {
            // attached hosts for fragments.
            if (cap.getRevision() == br) {
                CapabilitySet capSet = m_capSets.get(cap.getNamespace());
                if (capSet == null) {
                    capSet = new CapabilitySet(null, true);
                    m_capSets.put(cap.getNamespace(), capSet);
                }
                capSet.addCapability(cap);
            }
        }
    }
}
Also used : CapabilitySet(org.apache.felix.framework.capabilityset.CapabilitySet) BundleCapability(org.osgi.framework.wiring.BundleCapability)

Example 33 with BundleCapability

use of org.osgi.framework.wiring.BundleCapability in project felix-dev by apache.

the class StatefulResolver method groupSingletons.

private List<BundleRevision> groupSingletons(Map<BundleCapability, Collection<BundleCapability>> allCollisions, BundleCapability target, List<BundleRevision> group) {
    if (!group.contains(target.getRevision())) {
        // Add the target since it is implicitly part of the group.
        group.add(target.getRevision());
        // Recursively add the revisions of any singleton's in the
        // target's collisions.
        Collection<BundleCapability> collisions = allCollisions.remove(target);
        for (BundleCapability collision : collisions) {
            groupSingletons(allCollisions, collision, group);
        }
        // Need to check the values of other collisions for this target
        // and add those to the target's group too, since collisions are
        // treated as two-way relationships. Repeat until there are no
        // collision groups left that contain the target capability.
        boolean repeat;
        do {
            repeat = false;
            for (Entry<BundleCapability, Collection<BundleCapability>> entry : allCollisions.entrySet()) {
                if (entry.getValue().contains(target)) {
                    repeat = true;
                    groupSingletons(allCollisions, entry.getKey(), group);
                    break;
                }
            }
        } while (repeat);
    }
    return group;
}
Also used : ShrinkableCollection(org.apache.felix.framework.util.ShrinkableCollection) Collection(java.util.Collection) BundleCapability(org.osgi.framework.wiring.BundleCapability)

Example 34 with BundleCapability

use of org.osgi.framework.wiring.BundleCapability in project felix-dev by apache.

the class StatefulResolver method findProvidersInternal.

synchronized List<BundleCapability> findProvidersInternal(final ResolverHookRecord record, final Requirement req, final boolean obeyMandatory, final boolean invokeHooksAndSecurity) {
    List<BundleCapability> result = new ArrayList<BundleCapability>();
    CapabilitySet capSet = m_capSets.get(req.getNamespace());
    if (capSet != null) {
        // Get the requirement's filter; if this is our own impl we
        // have a shortcut to get the already parsed filter, otherwise
        // we must parse it from the directive.
        SimpleFilter sf;
        if (req instanceof BundleRequirementImpl) {
            sf = ((BundleRequirementImpl) req).getFilter();
        } else {
            String filter = req.getDirectives().get(Constants.FILTER_DIRECTIVE);
            if (filter == null) {
                sf = new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
            } else {
                sf = SimpleFilter.parse(filter);
            }
        }
        // Find the matching candidates.
        Set<Capability> matches = capSet.match(sf, obeyMandatory);
        // Filter matching candidates.
        for (Capability cap : matches) {
            if (!(cap instanceof BundleCapability))
                continue;
            BundleCapability bcap = (BundleCapability) cap;
            // Filter according to security.
            if (invokeHooksAndSecurity && filteredBySecurity((BundleRequirement) req, bcap)) {
                continue;
            }
            // dynamic attachment of fragments.
            if (req.getNamespace().equals(BundleRevision.HOST_NAMESPACE) && (bcap.getRevision().getWiring() != null)) {
                continue;
            }
            result.add(bcap);
        }
    }
    if (invokeHooksAndSecurity) {
        // based on a whitelist and/or fine-grained candidate filtering.
        if (!result.isEmpty() && !record.getResolverHookRefs().isEmpty()) {
            // from disallowed revisions.
            if (record.getBundleRevisionWhitelist() != null) {
                for (Iterator<BundleCapability> it = result.iterator(); it.hasNext(); ) {
                    if (!record.getBundleRevisionWhitelist().contains(it.next().getRevision())) {
                        it.remove();
                    }
                }
            }
            // Now give the hooks a chance to do fine-grained filtering.
            ShrinkableCollection<BundleCapability> shrinkable = new ShrinkableCollection<BundleCapability>(result);
            for (ResolverHook hook : record.getResolverHooks()) {
                try {
                    Felix.m_secureAction.invokeResolverHookMatches(hook, (BundleRequirement) req, shrinkable);
                } catch (Throwable th) {
                    m_logger.log(Logger.LOG_WARNING, "Resolver hook exception.", th);
                }
            }
        }
    }
    Collections.sort(result, new CandidateComparator());
    return result;
}
Also used : BundleCapability(org.osgi.framework.wiring.BundleCapability) Capability(org.osgi.resource.Capability) ResolverHook(org.osgi.framework.hooks.resolver.ResolverHook) ArrayList(java.util.ArrayList) BundleRequirementImpl(org.apache.felix.framework.wiring.BundleRequirementImpl) BundleRequirement(org.osgi.framework.wiring.BundleRequirement) CandidateComparator(org.apache.felix.framework.resolver.CandidateComparator) SimpleFilter(org.apache.felix.framework.capabilityset.SimpleFilter) CapabilitySet(org.apache.felix.framework.capabilityset.CapabilitySet) ShrinkableCollection(org.apache.felix.framework.util.ShrinkableCollection) BundleCapability(org.osgi.framework.wiring.BundleCapability)

Example 35 with BundleCapability

use of org.osgi.framework.wiring.BundleCapability in project felix-dev by apache.

the class StatefulResolver method markResolvedRevisions.

private void markResolvedRevisions(Map<Resource, List<Wire>> wireMap) throws ResolveException {
    boolean debugLog = m_felix.getLogger().getLogLevel() >= Logger.LOG_DEBUG;
    // First pass.
    if (wireMap != null) {
        // First pass: Loop through the wire map to find the host wires
        // for any fragments and map a host to all of its fragments.
        Map<Resource, List<BundleRevision>> hosts = new HashMap<Resource, List<BundleRevision>>();
        for (Entry<Resource, List<Wire>> entry : wireMap.entrySet()) {
            Resource revision = entry.getKey();
            List<Wire> wires = entry.getValue();
            if (Util.isFragment(revision)) {
                for (Wire w : wires) {
                    List<BundleRevision> fragments = hosts.get(w.getProvider());
                    if (fragments == null) {
                        fragments = new ArrayList<BundleRevision>();
                        hosts.put(w.getProvider(), fragments);
                    }
                    if (w.getRequirer() instanceof BundleRevision)
                        fragments.add((BundleRevision) w.getRequirer());
                }
            }
        }
        // Second pass: Loop through the wire map to do three things:
        // 1) convert resolver wires to bundle wires 2) create wiring
        // objects for revisions and 3) record dependencies among
        // revisions. We don't actually set the wirings here because
        // that indicates that a revision is resolved and we don't want
        // to mark anything as resolved unless we succussfully create
        // all wirings.
        Map<BundleRevision, BundleWiringImpl> wirings = new HashMap<BundleRevision, BundleWiringImpl>(wireMap.size());
        for (Entry<Resource, List<Wire>> entry : wireMap.entrySet()) {
            Resource resource = entry.getKey();
            if (!(resource instanceof BundleRevision))
                continue;
            BundleRevision revision = (BundleRevision) resource;
            List<Wire> resolverWires = entry.getValue();
            List<BundleWire> bundleWires = new ArrayList<BundleWire>(resolverWires.size());
            // the new ones.
            if ((revision.getWiring() != null) && Util.isFragment(revision)) {
                // Fragments only have host wires, so just add them all.
                bundleWires.addAll(revision.getWiring().getRequiredWires(null));
            }
            // Loop through resolver wires to calculate the package
            // space implied by the wires as well as to record the
            // dependencies.
            Map<String, BundleRevision> importedPkgs = new HashMap<String, BundleRevision>();
            Map<String, List<BundleRevision>> requiredPkgs = new HashMap<String, List<BundleRevision>>();
            for (Wire rw : resolverWires) {
                // TODO can we optimize this?
                if (!(rw.getRequirer() instanceof BundleRevision))
                    continue;
                BundleRevision requirer = (BundleRevision) rw.getRequirer();
                if (!(rw.getRequirement() instanceof BundleRequirement))
                    continue;
                BundleRequirement requirement = (BundleRequirement) rw.getRequirement();
                if (!(rw.getProvider() instanceof BundleRevision))
                    continue;
                BundleRevision provider = (BundleRevision) rw.getProvider();
                if (!(rw.getCapability() instanceof BundleCapability))
                    continue;
                BundleCapability capability = (BundleCapability) rw.getCapability();
                BundleWire bw = new BundleWireImpl(requirer, requirement, provider, capability);
                bundleWires.add(bw);
                if (Util.isFragment(revision)) {
                    if (debugLog) {
                        m_felix.getLogger().log(Logger.LOG_DEBUG, "FRAGMENT WIRE: " + rw.toString());
                    }
                } else {
                    if (debugLog) {
                        m_felix.getLogger().log(Logger.LOG_DEBUG, "WIRE: " + rw.toString());
                    }
                    if (capability.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE)) {
                        importedPkgs.put((String) capability.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE), provider);
                    } else if (capability.getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE)) {
                        Set<String> pkgs = calculateExportedAndReexportedPackages(provider, wireMap, new HashSet<String>(), new HashSet<BundleRevision>());
                        for (String pkg : pkgs) {
                            List<BundleRevision> revs = requiredPkgs.get(pkg);
                            if (revs == null) {
                                revs = new ArrayList<BundleRevision>();
                                requiredPkgs.put(pkg, revs);
                            }
                            revs.add(provider);
                        }
                    }
                }
            }
            List<BundleRevision> fragments = hosts.get(revision);
            try {
                wirings.put(revision, new BundleWiringImpl(m_felix.getLogger(), m_felix.getConfig(), this, (BundleRevisionImpl) revision, fragments, bundleWires, importedPkgs, requiredPkgs));
            } catch (Exception ex) {
                // throw an exception.
                for (Entry<BundleRevision, BundleWiringImpl> wiringEntry : wirings.entrySet()) {
                    // Dispose of wiring.
                    try {
                        wiringEntry.getValue().dispose();
                    } catch (Exception ex2) {
                        // We are in big trouble.
                        RuntimeException rte = new RuntimeException("Unable to clean up resolver failure.", ex2);
                        m_felix.getLogger().log(Logger.LOG_ERROR, rte.getMessage(), ex2);
                        throw rte;
                    }
                }
                ResolveException re = new ResolveException("Unable to resolve " + revision, revision, null);
                re.initCause(ex);
                m_felix.getLogger().log(Logger.LOG_ERROR, re.getMessage(), ex);
                throw re;
            }
        }
        // and update the resolver state.
        for (Entry<BundleRevision, BundleWiringImpl> entry : wirings.entrySet()) {
            BundleRevisionImpl revision = (BundleRevisionImpl) entry.getKey();
            // Mark revision as resolved.
            BundleWiring wiring = entry.getValue();
            revision.resolve(entry.getValue());
            // Record dependencies.
            for (BundleWire bw : wiring.getRequiredWires(null)) {
                m_felix.getDependencies().addDependent(bw);
            }
            // Reindex the revision's capabilities since its resolved
            // capabilities could be different than its declared ones
            // (e.g., due to substitutable exports).
            addRevision(revision);
            // Update the state of the revision's bundle to resolved as well.
            markBundleResolved(revision);
        }
    }
}
Also used : CapabilitySet(org.apache.felix.framework.capabilityset.CapabilitySet) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) Wire(org.osgi.resource.Wire) BundleWire(org.osgi.framework.wiring.BundleWire) BundleRequirement(org.osgi.framework.wiring.BundleRequirement) Entry(java.util.Map.Entry) BundleRevision(org.osgi.framework.wiring.BundleRevision) List(java.util.List) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) BundleWireImpl(org.apache.felix.framework.wiring.BundleWireImpl) BundleWiring(org.osgi.framework.wiring.BundleWiring) Resource(org.osgi.resource.Resource) BundleWire(org.osgi.framework.wiring.BundleWire) BundleException(org.osgi.framework.BundleException) ResolveException(org.apache.felix.framework.resolver.ResolveException) ResolutionException(org.osgi.service.resolver.ResolutionException) NoSuchElementException(java.util.NoSuchElementException) ResolveException(org.apache.felix.framework.resolver.ResolveException) BundleCapability(org.osgi.framework.wiring.BundleCapability)

Aggregations

BundleCapability (org.osgi.framework.wiring.BundleCapability)164 ArrayList (java.util.ArrayList)65 Bundle (org.osgi.framework.Bundle)57 BundleRevision (org.osgi.framework.wiring.BundleRevision)52 HashMap (java.util.HashMap)48 BundleWire (org.osgi.framework.wiring.BundleWire)47 BundleRequirement (org.osgi.framework.wiring.BundleRequirement)44 BundleWiring (org.osgi.framework.wiring.BundleWiring)44 List (java.util.List)41 Test (org.junit.Test)28 HashSet (java.util.HashSet)27 BundleException (org.osgi.framework.BundleException)25 ResolverHook (org.osgi.framework.hooks.resolver.ResolverHook)25 Collection (java.util.Collection)24 Set (java.util.Set)24 Version (org.osgi.framework.Version)22 Map (java.util.Map)18 ResolverHookFactory (org.osgi.framework.hooks.resolver.ResolverHookFactory)18 File (java.io.File)16 Module (org.eclipse.osgi.container.Module)14