package biz.aQute.resolve; import static aQute.bnd.osgi.resource.CapReqBuilder.createRequirementFromCapability; import static aQute.bnd.osgi.resource.ResourceUtils.createWildcardRequirement; import static aQute.bnd.osgi.resource.ResourceUtils.getIdentityCapability; import static java.util.Collections.singleton; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; import org.osgi.resource.Resource; import org.osgi.resource.Wire; import org.osgi.service.repository.Repository; import org.osgi.service.resolver.ResolutionException; import org.osgi.service.resolver.Resolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import aQute.bnd.deployer.repository.FixedIndexedRepo; import aQute.bnd.osgi.Processor; import aQute.bnd.osgi.repository.ResourcesRepository; import aQute.bnd.osgi.repository.XMLResourceParser; import aQute.bnd.osgi.resource.ResolutionDirective; import aQute.bnd.osgi.resource.ResourceBuilder; import aQute.bnd.osgi.resource.ResourceUtils; import aQute.bnd.osgi.resource.ResourceUtils.IdentityCapability; import aQute.lib.strings.Strings; public class ResolverValidator extends Processor { private final static Logger logger = LoggerFactory.getLogger(ResolverValidator.class); LogReporter reporter = new LogReporter(this); Resolver resolver = new BndResolver(reporter); List<URI> repositories = new ArrayList<>(); Resource system = null; public static class Resolution { public Resource resource; public boolean succeeded; public String message; public Set<Resource> resolved = new LinkedHashSet<>(); public List<Requirement> system = new ArrayList<>(); public List<Requirement> repos = new ArrayList<>(); public List<Requirement> missing = new ArrayList<>(); public List<Requirement> optionals = new ArrayList<>(); public List<Requirement> unresolved = new ArrayList<>(); } public ResolverValidator(Processor parent) throws Exception { super(parent); } public ResolverValidator() {} public void addRepository(URI url) throws Exception { repositories.add(url); } public void setSystem(Resource resource) throws Exception { assert resource != null; this.system = resource; } public List<Resolution> validate() throws Exception { FixedIndexedRepo repository = getRepository(); Set<Resource> resources = getAllResources(repository); return validateResources(repository, resources); } public List<Resolution> validate(Collection<Resource> toBeChecked) throws Exception { Set<Resource> allResources = new LinkedHashSet<Resource>(); for (URI uri : repositories) { allResources.addAll(XMLResourceParser.getResources(uri)); } allResources.addAll(toBeChecked); ResourcesRepository repository = new ResourcesRepository(allResources); return validateResources(repository, toBeChecked); } FixedIndexedRepo getRepository() throws MalformedURLException, URISyntaxException { FixedIndexedRepo repository = new FixedIndexedRepo(); repository.setLocations(Strings.join(repositories)); return repository; } public List<Resolution> validateResources(Repository repository, Collection<Resource> resources) throws Exception { setProperty("-runfw", "dummy"); List<Resolution> result = new ArrayList<>(); List<Resource> resourceList = new ArrayList<>(resources); while (!resourceList.isEmpty()) { Resource resource = resourceList.remove(0); Resolution resolution = resolve(repository, resource); result.add(resolution); for (Resource resolved : resolution.resolved) { if (resourceList.remove(resolved)) { Resolution curResolution = new Resolution(); curResolution.resource = resolved; curResolution.succeeded = true; result.add(curResolution); } } } return result; } public static Set<Resource> getAllResources(Repository repository) { Requirement r = createWildcardRequirement(); Map<Requirement,Collection<Capability>> providers = repository.findProviders(Collections.singleton(r)); Set<Resource> resources = ResourceUtils.getResources(providers.get(r)); return resources; } private BndrunResolveContext getResolveContext() throws Exception { BndrunResolveContext context = new BndrunResolveContext(this, null, this, reporter) { @Override void loadFramework(ResourceBuilder systemBuilder) throws Exception { systemBuilder.addCapabilities(system.getCapabilities(null)); } }; return context; } public Requirement getIdentity(Resource resource) { IdentityCapability identityCapability = getIdentityCapability(resource); return createRequirementFromCapability(identityCapability).buildSyntheticRequirement(); } public Resolution resolve(Repository repository, Resource resource) throws Exception { Resolution resolution = new Resolution(); Requirement identity = getIdentity(resource); setProperty("-runrequires", ResourceUtils.toRequireCapability(identity)); BndrunResolveContext context = getResolveContext(); context.addRepository(repository); context.init(); resolution.resource = resource; try { Map<Resource,List<Wire>> resolve2 = resolver.resolve(context); resolution.succeeded = true; resolution.resolved = resolve2.keySet(); logger.debug("resolving {} succeeded", resource); } catch (ResolutionException e) { logger.debug("resolving {} failed", resource); resolution.succeeded = false; resolution.message = e.getMessage(); for (Requirement req : e.getUnresolvedRequirements()) { logger.debug(" missing {}", req); resolution.unresolved.add(req); } ResourcesRepository systemRepository = new ResourcesRepository(system); for (Requirement r : resource.getRequirements(null)) { Collection<Capability> caps = systemRepository.findProvider(r); boolean missing = caps.isEmpty(); if (missing) { Set<Requirement> requirements = singleton(r); caps = repository.findProviders(requirements).get(r); missing = caps.isEmpty(); if (missing) { if (ResourceUtils.getResolution(r) == ResolutionDirective.optional) resolution.optionals.add(r); else resolution.missing.add(r); } else { logger.debug(" found {} in repo", r); resolution.repos.add(r); } } else { logger.debug(" found {} in system", r); resolution.system.add(r); } } error("resolving %s failed with %s", resource, resolution.message); } catch (Exception e) { e.printStackTrace(); error("resolving %s failed with %s", context.getInputResource().getRequirements(null), e); resolution.message = e.getMessage(); } return resolution; } }