in atomos/src/main/java/org/apache/felix/atomos/impl/modules/AtomosModules.java [498:623]
private void generateHeaders(Map<String, String> headers, Module m)
{
ModuleDescriptor desc = m.getDescriptor();
StringBuilder capabilities = new StringBuilder();
StringBuilder requirements = new StringBuilder();
String bsn = headers.get(Constants.BUNDLE_SYMBOLICNAME);
if (bsn == null)
{
// NOTE that we depend on the framework connect implementation to allow connect bundles
// to export java.* packages
headers.put(Constants.BUNDLE_MANIFESTVERSION, "2");
// set the symbolic name for the module; don't allow fragments to attach
headers.put(Constants.BUNDLE_SYMBOLICNAME,
desc.name() + "; " + Constants.FRAGMENT_ATTACHMENT_DIRECTIVE + ":="
+ Constants.FRAGMENT_ATTACHMENT_NEVER);
// set the version
Version v;
try
{
v = Version.parseVersion(desc.version().map(
java.lang.module.ModuleDescriptor.Version::toString).orElse("0"));
}
catch (IllegalArgumentException e)
{
v = Version.emptyVersion;
}
headers.put(Constants.BUNDLE_VERSION, v.toString());
// only do exports for non bundle modules
// real OSGi bundles already have good export capabilities
StringBuilder exportPackageHeader = new StringBuilder();
// ModuleDescriptor.exports() is empty for an automatic module, which is different from
// JPMS at runtime where all packages in the automatic module are exported
if (desc.isAutomatic()) {
desc.packages().stream().sorted().forEach((packageName) -> {
if (exportPackageHeader.length() > 0)
{
exportPackageHeader.append(", ");
}
exportPackageHeader.append(packageName);
});
}
else {
desc.exports().stream().sorted().forEach((exported) -> {
if (exportPackageHeader.length() > 0)
{
exportPackageHeader.append(", ");
}
exportPackageHeader.append(exported.source());
// TODO map targets to x-friends directive?
});
}
if (exportPackageHeader.length() > 0)
{
headers.put(Constants.EXPORT_PACKAGE, exportPackageHeader.toString());
}
// Note that for generated manifests based of module descriptor
// will have their requires calculated later.
// Place a header indicating this is generated
headers.put(ATOMOS_GENERATED, Boolean.TRUE.toString());
if (calculateRequires(headers, m, Function.identity()))
{
// Set a temporary header if we need to recalculate later
headers.put(ATOMOS_TEMPORARY_GENERATED_REQUIRES, Boolean.TRUE.toString());
}
}
else
{
String origCaps = headers.get(Constants.PROVIDE_CAPABILITY);
if (origCaps != null)
{
capabilities.append(origCaps);
}
String origReqs = headers.get(Constants.REQUIRE_CAPABILITY);
if (origReqs != null)
{
requirements.append(origReqs);
}
}
// map provides to a made up namespace only to give proper resolution errors
// (although JPMS will likely complain first
for (ModuleDescriptor.Provides provides : desc.provides())
{
if (capabilities.length() > 0)
{
capabilities.append(", ");
}
capabilities.append(JavaServiceNamespace.JAVA_SERVICE_NAMESPACE).append(
"; ");
capabilities.append(JavaServiceNamespace.JAVA_SERVICE_NAMESPACE).append(
"=").append(provides.service()).append("; ");
capabilities.append(
JavaServiceNamespace.CAPABILITY_PROVIDES_WITH_ATTRIBUTE).append(
"=\"").append(String.join(",", provides.providers())).append(
"\"");
}
// map uses to a made up namespace only to give proper resolution errors
// (although JPMS will likely complain first)
for (String uses : desc.uses())
{
if (requirements.length() > 0)
{
requirements.append(", ");
}
requirements.append(JavaServiceNamespace.JAVA_SERVICE_NAMESPACE).append(
"; ");
requirements.append(Constants.RESOLUTION_DIRECTIVE).append(":=").append(
Constants.RESOLUTION_OPTIONAL).append("; ");
requirements.append(Constants.FILTER_DIRECTIVE).append(":=").append(
"\"(").append(JavaServiceNamespace.JAVA_SERVICE_NAMESPACE).append(
"=").append(uses).append(")\"");
}
if (capabilities.length() > 0)
{
headers.put(Constants.PROVIDE_CAPABILITY, capabilities.toString());
}
if (requirements.length() > 0)
{
headers.put(Constants.REQUIRE_CAPABILITY, requirements.toString());
}
}