package aQute.bnd.osgi.repository; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; import org.osgi.resource.Resource; import org.osgi.service.repository.Repository; import aQute.bnd.header.Attrs; import aQute.bnd.header.Parameters; import aQute.bnd.osgi.Constants; import aQute.bnd.osgi.resource.CapReqBuilder; import aQute.bnd.osgi.resource.ResourceBuilder; import aQute.bnd.osgi.resource.ResourceUtils; import aQute.lib.collections.MultiMap; public class AugmentRepository extends BaseRepository { private final Repository repository; private final Map<Capability,Capability> wrapped = new HashMap<Capability,Capability>(); private final List<Capability> augmentedCapabilities = new ArrayList<>(); private final List<Resource> augmentedBundles = new ArrayList<>(); public AugmentRepository(Parameters augments, Repository repository) throws Exception { this.repository = repository; init(augments); } @Override public Map<Requirement,Collection<Capability>> findProviders(Collection< ? extends Requirement> requirements) { Map<Requirement,Collection<Capability>> fromRepos = repository.findProviders(requirements); for (Requirement requirement : requirements) { List<Capability> provided = new ArrayList<>(); boolean replaced = false; for (Capability originalCapability : fromRepos.get(requirement)) { if (isValid(originalCapability)) { Capability wrappedCapability = wrapped.get(originalCapability); if (wrappedCapability != null) { provided.add(wrappedCapability); replaced = true; } else provided.add(originalCapability); } } Collection<Capability> additional = ResourceUtils.findProviders(requirement, augmentedCapabilities); replaced |= provided.addAll(additional); if (replaced) fromRepos.put(requirement, provided); } return fromRepos; } public boolean isValid(Capability capability) { return true; } static class Augment { Parameters additionalRequirements; Parameters additionalCapabilities; } private void init(Parameters augments) throws Exception { MultiMap<Requirement,Augment> operations = new MultiMap<>(); for (Map.Entry<String,Attrs> e : augments.entrySet()) { String bsn = e.getKey(); Attrs attrs = e.getValue(); createAugmentOperation(operations, bsn, attrs); } Map<Requirement,Collection<Capability>> allBundles = repository.findProviders(operations.keySet()); for (Entry<Requirement,List<Augment>> e : operations.entrySet()) { executeAugmentOperations(allBundles, e.getKey(), e.getValue()); } } private void createAugmentOperation(MultiMap<Requirement,Augment> operations, String bsn, Attrs attrs) { String range = attrs.getVersion(); Requirement bundleRequirement = CapReqBuilder.createBundleRequirement(bsn, range).buildSyntheticRequirement(); Augment augment = new Augment(); augment.additionalCapabilities = new Parameters(attrs.get(Constants.AUGMENT_CAPABILITY_DIRECTIVE)); augment.additionalRequirements = new Parameters(attrs.get(Constants.AUGMENT_REQUIREMENT_DIRECTIVE)); operations.add(bundleRequirement, augment); } private void executeAugmentOperations(Map<Requirement,Collection<Capability>> allBundles, Requirement bundleRequirement, List<Augment> augments) throws Exception { Collection<Capability> matchedBundleCapabilities = allBundles.get(bundleRequirement); Collection<Resource> bundles = ResourceUtils.getResources(matchedBundleCapabilities); for (Resource bundle : bundles) { ResourceBuilder wrappedBundleBuilder = new ResourceBuilder(); Map<Capability,Capability> originalToWrapper = wrappedBundleBuilder.from(bundle); wrapped.putAll(originalToWrapper); List<Augment> bundleAugments = augments; for (Augment augment : bundleAugments) { List<Capability> addedCapabilities = augment(augment, wrappedBundleBuilder); augmentedCapabilities.addAll(addedCapabilities); } Resource wrappedBundle = wrappedBundleBuilder.build(); augmentedBundles.add(wrappedBundle); } } private List<Capability> augment(Augment augment, ResourceBuilder builder) throws Exception { builder.addRequireCapabilities(augment.additionalRequirements); return builder.addProvideCapabilities(augment.additionalCapabilities); } }