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);
}
}
}
}
}