aQute.bnd.osgi.PermissionGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of biz.aQute.bndlib Show documentation
Show all versions of biz.aQute.bndlib Show documentation
bndlib: A Swiss Army Knife for OSGi
package aQute.bnd.osgi;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import aQute.bnd.header.Attrs;
import aQute.bnd.osgi.Descriptors.PackageRef;
import aQute.bnd.osgi.resource.FilterParser;
import aQute.bnd.osgi.resource.FilterParser.Expression;
import aQute.bnd.osgi.resource.FilterParser.ExpressionVisitor;
import aQute.bnd.osgi.resource.FilterParser.Op;
import aQute.bnd.osgi.resource.FilterParser.Or;
import aQute.bnd.osgi.resource.FilterParser.PatternExpression;
import aQute.bnd.osgi.resource.FilterParser.SimpleExpression;
public class PermissionGenerator {
public static enum Parameter {
ADMIN {
@Override
public void generate(StringBuilder sb, Builder builder) {
sb.append("(org.osgi.framework.AdminPermission)\n");
}
},
CAPABILITIES {
@Override
public void generate(StringBuilder sb, Builder builder) {
for (String namespace : builder.getProvideCapability().keySet()) {
if (!Processor.isDuplicate(namespace)) {
sb.append("(org.osgi.framework.CapabilityPermission \"")
.append(namespace)
.append("\" \"provide\")\n");
}
}
for (String namespace : builder.getRequireCapability().keySet()) {
if (!Processor.isDuplicate(namespace)) {
sb.append("(org.osgi.framework.CapabilityPermission \"")
.append(namespace)
.append("\" \"require\")\n");
}
}
}
},
PACKAGES {
@Override
public void generate(StringBuilder sb, Builder builder) {
if (builder.getImports() != null) {
for (PackageRef imp : builder.getImports().keySet()) {
if (!imp.isJava()) {
sb.append("(org.osgi.framework.PackagePermission \"");
sb.append(imp);
sb.append("\" \"import\")\n");
}
}
}
if (builder.getExports() != null) {
for (PackageRef exp : builder.getExports().keySet()) {
sb.append("(org.osgi.framework.PackagePermission \"");
sb.append(exp);
sb.append("\" \"export\")\n");
}
}
}
},
SERVICES {
@Override
public void generate(StringBuilder sb, Builder builder) {
for (String declaredService : getDeclaredServices(builder)) {
sb.append("(org.osgi.framework.ServicePermission \"")
.append(declaredService)
.append("\" \"register\")\n");
}
for (String referencedService : getReferencedServices(builder)) {
sb.append("(org.osgi.framework.ServicePermission \"")
.append(referencedService)
.append("\" \"get\")\n");
}
}
};
public abstract void generate(StringBuilder sb, Builder builder);
}
public static final String KEY = "permissions";
public static Set getDeclaredServices(Builder builder) {
Set declaredServices = new TreeSet<>();
for (Entry entry : builder.getProvideCapability().entrySet()) {
if (Processor.removeDuplicateMarker(entry.getKey()).equals("osgi.service")) {
Attrs attrs = entry.getValue();
String ifaces = attrs.get("objectClass");
if (ifaces != null) {
for (String iface : ifaces.split(",")) {
declaredServices.add(iface.trim());
}
}
}
}
return declaredServices;
}
private static final String MATCH_ALL = "*";
private static final String VALID_WILDCARD = ".*";
static final class FindReferencedServices extends ExpressionVisitor> {
public FindReferencedServices() {
super(Collections. emptySet());
}
@Override
public Set visit(SimpleExpression expr) {
if ("objectClass".equals(expr.getKey())) {
if (expr.getOp() == Op.EQUAL) {
String v = expr.getValue();
if (!v.contains(MATCH_ALL) || v.equals(MATCH_ALL)) {
return Collections.singleton(v);
} else if (v.endsWith(VALID_WILDCARD) && !v.substring(0, v.length() - 2).contains(MATCH_ALL)) {
return Collections.singleton(v);
} else {
// All other matchings have no meaning to us, the user
// should generate them by hand
return Collections.emptySet();
}
} else {
// All other matchings have no meaning, so match nothing
return Collections.emptySet();
}
}
return Collections.emptySet();
}
@Override
public Set visit(PatternExpression expr) {
// Simply use the default visit method for simple expressions, since
// the patterns are also supported in the permissions
return visit((SimpleExpression) expr);
}
@Override
public Set visit(Or expr) {
Set matches = new HashSet<>();
for (Expression expression : expr.getExpressions()) {
matches.addAll(expression.visit(this));
}
return matches;
}
@Override
public Set visitTrue() {
return Collections.singleton(MATCH_ALL);
}
}
public static Set getReferencedServices(Builder builder) {
Set referencedServices = new TreeSet<>();
for (Entry entry : builder.getRequireCapability().entrySet()) {
if (Processor.removeDuplicateMarker(entry.getKey()).equals("osgi.service")) {
Attrs attrs = entry.getValue();
String filter = attrs.get("filter:");
if (filter != null && !filter.isEmpty()) {
FilterParser filterParser = new FilterParser();
Expression expr = filterParser.parse(filter);
referencedServices.addAll(expr.visit(new FindReferencedServices()));
}
}
}
if (referencedServices.contains(MATCH_ALL)) {
return Collections.singleton(MATCH_ALL);
} else {
return referencedServices;
}
}
private static EnumSet parseParams(Builder builder, final String... args) {
EnumSet parameters = EnumSet.noneOf(Parameter.class);
// Skip the key name, so start at index 1
for (int ix = 1; ix < args.length; ix++) {
String name = args[ix].toUpperCase();
try {
parameters.add(Parameter.valueOf(name));
} catch (IllegalArgumentException ex) {
builder.error("Could not parse argument for ${permissions}: %s", args[ix]);
}
}
return parameters;
}
private final Builder builder;
private final Set parameters;
public PermissionGenerator(Builder builder, final String... args) {
assert args.length > 0 && KEY.equals(args[0]);
this.builder = builder;
this.parameters = parseParams(builder, args);
}
public String generate() {
StringBuilder sb = new StringBuilder();
for (Parameter param : parameters) {
param.generate(sb, builder);
}
return sb.toString();
}
}