package aQute.bnd.main; import java.io.File; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; 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.service.repository.Repository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import aQute.bnd.build.Container; import aQute.bnd.build.Project; import aQute.bnd.build.Run; import aQute.bnd.build.Workspace; import aQute.bnd.build.model.EE; import aQute.bnd.build.model.OSGI_CORE; import aQute.bnd.build.model.clauses.HeaderClause; import aQute.bnd.build.model.conversions.CollectionFormatter; import aQute.bnd.build.model.conversions.Converter; import aQute.bnd.build.model.conversions.HeaderClauseFormatter; import aQute.bnd.header.Parameters; import aQute.bnd.main.bnd.projectOptions; import aQute.bnd.osgi.Domain; import aQute.bnd.osgi.Processor; import aQute.bnd.osgi.resource.FilterParser; import aQute.bnd.osgi.resource.FilterParser.Expression; import aQute.bnd.osgi.resource.ResourceBuilder; import aQute.bnd.osgi.resource.ResourceUtils.IdentityCapability; import aQute.lib.getopt.Arguments; import aQute.lib.getopt.Description; import aQute.lib.getopt.Options; import aQute.lib.io.IO; import aQute.lib.strings.Strings; import biz.aQute.resolve.Bndrun; import biz.aQute.resolve.ProjectResolver; import biz.aQute.resolve.ResolverValidator; import biz.aQute.resolve.ResolverValidator.Resolution; public class ResolveCommand extends Processor { private final static Logger logger = LoggerFactory.getLogger(ResolveCommand.class); private bnd bnd; public ResolveCommand(bnd bnd) { super(bnd); this.bnd = bnd; getSettings(bnd); } interface FindOptions extends projectOptions { String workspace(); } public void _find(FindOptions options, bnd bnd) throws Exception { List<String> args = options._arguments(); for (String bndrun : args) { Project p = bnd.getProject(options.project()); Workspace workspace = p == null ? bnd.getWorkspace(options.workspace()) : p.getWorkspace(); Run run = new Run(workspace, p != null ? p.getBase() : IO.work, IO.getFile(bndrun)); ProjectResolver pr = new ProjectResolver(run); addClose(pr); pr.resolve(); bnd.out.println("Resolved " + run); for (Container c : pr.getRunBundles()) { bnd.out.printf("%-30s %-20s %-6s %s\n", c.getBundleSymbolicName(), c.getVersion(), c.getType(), c.getFile()); } } } interface QueryOptions extends projectOptions { String workspace(); } public void _query(QueryOptions options) throws Exception { List<String> args = options._arguments(); String bsn = args.remove(0); String version = null; if (!args.isEmpty()) version = args.remove(0); ProjectResolver pr = new ProjectResolver(bnd.getProject(options.project())); addClose(pr); IdentityCapability resource = pr.getResource(bsn, version); bnd.out.printf("%-30s %-20s %s\n", resource.osgi_identity(), resource.version(), resource.description("")); Resource r = resource.getResource(); FilterParser p = new FilterParser(); if (r != null) { List<Requirement> requirements = resource.getResource().getRequirements(null); if (!requirements.isEmpty()) { bnd.out.println("Requirements:"); for (Requirement req : requirements) { Expression parse = p.parse(req); bnd.out.printf(" %-20s %s\n", req.getNamespace(), parse); } } List<Capability> capabilities = resource.getResource().getCapabilities(null); if (!capabilities.isEmpty()) { bnd.out.println("Capabilities:"); for (Capability cap : capabilities) { Map<String,Object> attrs = new HashMap<String,Object>(cap.getAttributes()); Object id = attrs.remove(cap.getNamespace()); Object vv = attrs.remove("version"); if (vv == null) vv = attrs.remove("bundle-version"); bnd.out.printf(" %-20s %-40s %-20s attrs=%s dirs=%s\n", cap.getNamespace(), id, vv, attrs, cap.getDirectives()); } } } } interface RepoOptions extends Options { String workspace(); } public void _repos(RepoOptions options) throws Exception { Workspace ws = bnd.getWorkspace(options.workspace()); if (ws == null) { error("No workspace"); return; } List<Repository> plugins = ws.getPlugins(Repository.class); bnd.out.println(Strings.join("\n", plugins)); } /** * Validate a repository so that it is self consistent */ @Arguments(arg = { "index-path" }) interface ValidateOptions extends Options { EE ee(EE ee); OSGI_CORE core(); String system(); Parameters packages(); Parameters capabilities(); boolean all(); } public void _validate(ValidateOptions options) throws Exception { ResourceBuilder system = new ResourceBuilder(); system.addEE(options.ee(EE.JavaSE_1_8)); if (options.core() != null) system.addManifest(options.core().getManifest()); if (options.packages() != null) system.addExportPackages(options.packages()); if (options.capabilities() != null) system.addProvideCapabilities(options.capabilities()); if (options.system() != null) { File f = IO.getFile(options.system()); if (!f.isFile()) { error("Specified system file but not found: %s", f); return; } Domain domain = Domain.domain(f); system.addManifest(domain); } List<String> args = options._arguments(); File index = getFile(args.remove(0)); logger.debug("validating {}", index); ResolverValidator validator = new ResolverValidator(bnd); validator.use(bnd); validator.addRepository(index.toURI()); validator.setSystem(system.build()); List<Resolution> result = validator.validate(); Set<Requirement> done = new HashSet<>(); for (Resolution res : result) { if (options.all()) { bnd.out.format("%s %-60s%n", res.succeeded ? "OK" : "**", res.resource, res.message == null ? "" : res.message); } if (!res.succeeded) { for (Requirement req : res.missing) { if (done.contains(req)) continue; bnd.out.format(" missing %s%n", req); done.add(req); } if (options.all()) { for (Requirement req : res.repos) { bnd.out.format(" repos %s%n", req); } for (Requirement req : res.system) { bnd.out.format(" system %s%n", req); } for (Requirement req : res.optionals) { bnd.out.format(" optional %s%n", req); } } } } bnd.getInfo(validator); } private static final Converter<String,Collection< ? extends HeaderClause>> runbundlesFormatter = new CollectionFormatter<>( "\n ", new HeaderClauseFormatter(), "", " ", ""); @Arguments(arg = "<path>...") interface ResolveOptions extends Options { @Description("Use the following workspace") String workspace(); @Description("Specify the project directory if not in a project directory") String project(); @Description("Print out the bundles") boolean bundles(); @Description("Write -runbundles instruction to the file") boolean write(); } @Description("Resolve a bndrun file") public void _resolve(ResolveOptions options) throws Exception { Project project = bnd.getProject(options.project()); Workspace ws = null; if (options.workspace() != null) { File file = bnd.getFile(options.workspace()); if (file.isDirectory()) { ws = Workspace.getWorkspace(file); if (!ws.isValid()) { error("Invalid workspace %s", file); return; } } else { error("Workspace directory %s is not a directory", file); return; } } else { if (project != null) ws = project.getWorkspace(); } List<String> paths = options._arguments(); for (String path : paths) { File f = getFile(path); if (!f.isFile()) { error("Missing bndrun file: %s", f); } else { try (Bndrun bndrun = Bndrun.createBndrun(ws, f)) { try { String runbundles = bndrun.resolve(false, options.write(), runbundlesFormatter); if (bndrun.isOk()) { System.out.printf("# %-50s ok%n", f.getName()); if (options.bundles()) { System.out.println(runbundles); } } } catch (Exception e) { System.out.printf("%-50s %s\n", f.getName(), e); exception(e, "Failed to resolve %s: %s", f, e); } getInfo(bndrun); } } } } }