private void markResolvedRevisions()

in framework/src/main/java/org/apache/felix/framework/StatefulResolver.java [1020:1243]


    private void markResolvedRevisions(Map<Resource, List<Wire>> wireMap)
        throws ResolveException
    {
        boolean debugLog = m_felix.getLogger().getLogLevel() >= Logger.LOG_DEBUG;

        // DO THIS IN THREE PASSES:
        // 1. Aggregate fragments per host.
        // 2. Attach wires and fragments to hosts.
        //    -> If fragments fail to attach, then undo.
        // 3. Mark hosts and fragments as resolved.

        // 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<>();
            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<>();
                            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<>(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<>(resolverWires.size());

                // Need to special case fragments since they may already have
                // wires if they are already attached to another host; if that
                // is the case, then we want to merge the old host wires with
                // 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<>();
                Map<String, List<BundleRevision>> requiredPkgs =
                    new HashMap<>();
                for (Wire rw : resolverWires)
                {
                    // TODO is a rw already a BundleWire?
                    // 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<>(),
                                    new HashSet<>());
                            for (String pkg : pkgs)
                            {
                                List<BundleRevision> revs = requiredPkgs.get(pkg);
                                if (revs == null)
                                {
                                    revs = new ArrayList<>();
                                    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)
                {
                    // This is a fatal error, so undo everything and
                    // 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;
                }
            }

            // Third pass: Loop through the wire map to mark revision as resolved
            // 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);
            }
        }
    }