package aQute.bnd.main;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import aQute.bnd.annotation.metatype.Meta;
import aQute.bnd.annotation.plugin.BndPlugin;
import aQute.bnd.build.Workspace;
import aQute.bnd.header.Attrs;
import aQute.bnd.header.OSGiHeader;
import aQute.bnd.header.Parameters;
import aQute.lib.getopt.Arguments;
import aQute.lib.getopt.Options;
import aQute.lib.utf8properties.UTF8Properties;
/**
* Combines plugin management commands
*/
public class Plugins {
private static final Pattern PLUGIN_FILE_P = Pattern.compile("(.*)\\.bnd");
private Map<String,Class< ? >> annotatedPlugins;
private final Workspace ws;
private final bnd bnd;
Plugins(bnd bnd, Workspace ws) throws Exception {
this.bnd = bnd;
this.ws = ws;
}
interface PluginAddOptions extends Options {
String alias();
boolean force();
// boolean interactive();
// String jar();
}
public void _add(PluginAddOptions opts) throws Exception {
List<String> args = opts._arguments();
Map<String,Class< ? >> plugins = getAnnotatedPlugins();
if (args.isEmpty()) {
print(plugins);
return;
}
String pluginName = args.remove(0);
String alias = opts.alias() == null ? pluginName : opts.alias();
Class< ? > plugin = plugins.get(pluginName);
if (plugin == null) {
bnd.error("No such plugin: %s", pluginName);
return;
} else {
Map<String,String> parameters = new HashMap<String,String>();
for (String parameter : args) {
if (parameter.indexOf('=') < 1)
parameter += "=true";
Attrs attrs = OSGiHeader.parseProperties(parameter);
parameters.putAll(attrs);
}
// if ( false && opts.interactive()) {
//
// Interactive interactive = new Interactive(bnd.out, System.in,
// parameters);
// if ( !interactive.go() ) {
// bnd.error("aborted by interactive editor");
// return;
// }
// }
ws.addPlugin(plugin, alias, parameters, opts.force());
}
}
@Arguments(arg = "alias...")
interface PluginRemoveOptions extends Options {}
public void _remove(PluginRemoveOptions opts) {
List<String> args = opts._arguments();
if (args.isEmpty()) {
for (String file : ws.getFile("cnf/ext").list()) {
Matcher m = PLUGIN_FILE_P.matcher(file);
if (m.matches()) {
bnd.out.println(m.group(1));
}
}
return;
}
for (String p : args) {
ws.removePlugin(p);
}
}
private void print(Map<String,Class< ? >> plugins) {
bnd.out.printf("%-30s %s%n", "Type", "Description");
for (Map.Entry<String,Class< ? >> e : plugins.entrySet()) {
bnd.out.printf("%-30s %s%n", e.getKey(), getDescription(e.getValue()));
}
}
/*
* Return the description of the plugin. Requires a plugin that is annotated
* with BndPlugin and that has a Config which is annotated with an OCD.
*/
private String getDescription(Class< ? > clazz) {
String description = clazz.getName();
Meta.OCD ocd = getOCD(clazz);
if (ocd != null && ocd.description() != Meta.NULL)
description = ocd.description();
return description;
}
private Meta.OCD getOCD(Class< ? > pluginClass) {
BndPlugin plugin = pluginClass.getAnnotation(BndPlugin.class);
if (plugin != null) {
Class< ? > configClass = plugin.parameters();
if (configClass != null && configClass != Object.class) {
Meta.OCD ocd = configClass.getAnnotation(Meta.OCD.class);
return ocd;
}
}
return null;
}
private Map<String,Class< ? >> getAnnotatedPlugins() throws IOException {
if (annotatedPlugins == null) {
annotatedPlugins = new TreeMap<String,Class< ? >>();
try (InputStream in = bnd.class.getResourceAsStream("bnd.info")) {
Properties p = new UTF8Properties();
p.load(in);
Parameters classes = new Parameters(p.getProperty("plugins"), bnd);
for (String cname : classes.keySet()) {
try {
Class< ? > c = getClass().getClassLoader().loadClass(cname);
aQute.bnd.annotation.plugin.BndPlugin annotation = c
.getAnnotation(aQute.bnd.annotation.plugin.BndPlugin.class);
if (annotation != null) {
annotatedPlugins.put(annotation.name(), c);
}
} catch (Exception ex) {
bnd.error("Cannot find plugin %s", cname);
}
}
}
}
return annotatedPlugins;
}
}