All Downloads are FREE. Search and download functionalities are using the official Maven repository.

aQute.bnd.osgi.PermissionGenerator Maven / Gradle / Ivy

There is a newer version: 7.0.0
Show newest version
package aQute.bnd.osgi;

import static java.util.stream.Collectors.toCollection;

import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;

import org.osgi.namespace.service.ServiceNamespace;
import org.osgi.resource.Namespace;

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;
import aQute.lib.strings.Strings;

public class PermissionGenerator {
	public 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 = builder.getProvideCapability()
			.stream()
			.filterKey(key -> Processor.removeDuplicateMarker(key)
				.equals(ServiceNamespace.SERVICE_NAMESPACE))
			.values()
			.map(attrs -> attrs.get(ServiceNamespace.CAPABILITY_OBJECTCLASS_ATTRIBUTE))
			.filter(Objects::nonNull)
			.flatMap(Strings::splitAsStream)
			.collect(toCollection(TreeSet::new));
		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 = builder.getRequireCapability()
			.stream()
			.filterKey(key -> Processor.removeDuplicateMarker(key)
				.equals(ServiceNamespace.SERVICE_NAMESPACE))
			.values()
			.map(attrs -> attrs.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE + ":"))
			.filter(Strings::nonNullOrEmpty)
			.flatMap(filter -> new FilterParser().parse(filter)
				.visit(new FindReferencedServices())
				.stream())
			.collect(toCollection(TreeSet::new));

		if (referencedServices.contains(MATCH_ALL)) {
			return Collections.singleton(MATCH_ALL);
		}
		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(Locale.ROOT);
			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();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy