bndlib: A Swiss Army Knife for OSGi providing comprehensive bundle manipulation and analysis capabilities
—
OSGi manifest header parsing and manipulation utilities for working with bundle metadata and dependency declarations.
Represents parsed OSGi manifest header parameters as a map of clause names to attributes.
/**
* Represents parsed OSGi manifest header parameters
*/
public class Parameters implements Map<String, Attrs> {
/** Create empty parameters */
public Parameters();
/** Parse parameters from header string */
public Parameters(String header);
/** Parse parameters from header string with processor */
public Parameters(String header, Processor processor);
/** Get attributes for clause */
public Attrs get(String clause);
/** Put clause with attributes */
public Attrs put(String clause, Attrs attrs);
/** Remove clause */
public Attrs remove(String clause);
/** Check if clause exists */
public boolean containsKey(String clause);
/** Get all clause names */
public Set<String> keySet();
/** Get all attributes collections */
public Collection<Attrs> values();
/** Get entry set */
public Set<Map.Entry<String, Attrs>> entrySet();
/** Merge with other parameters */
public void mergeWith(Parameters other, boolean override);
/** Convert back to header string */
public String toString();
/** Get size */
public int size();
/** Check if empty */
public boolean isEmpty();
/** Clear all parameters */
public void clear();
}Usage Examples:
import aQute.bnd.header.Parameters;
import aQute.bnd.header.Attrs;
// Parse Export-Package header
String exportHeader = "com.example.api;version=\"1.0\";uses:=\"com.example.spi,com.example.util\"," +
"com.example.impl;version=\"1.0\";x-internal:=true";
Parameters exports = new Parameters(exportHeader);
for (Map.Entry<String, Attrs> entry : exports.entrySet()) {
String packageName = entry.getKey();
Attrs attrs = entry.getValue();
System.out.println("Package: " + packageName);
System.out.println(" Version: " + attrs.get("version"));
System.out.println(" Uses: " + attrs.get("uses"));
System.out.println(" Internal: " + attrs.get("x-internal"));
}
// Create new parameters
Parameters imports = new Parameters();
Attrs attrs = new Attrs();
attrs.put("version", "[1.0,2.0)");
attrs.put("resolution", "optional");
imports.put("javax.servlet", attrs);
System.out.println("Import-Package: " + imports.toString());
// Output: javax.servlet;version="[1.0,2.0)";resolution:=optionalRepresents attributes in OSGi headers as a map of attribute names to values with type conversion support.
/**
* Represents attributes in OSGi headers
*/
public class Attrs extends LinkedHashMap<String, String> {
/** Create empty attributes */
public Attrs();
/** Create attributes from map */
public Attrs(Map<String, String> map);
/** Get typed attribute value */
public <T> T getTyped(String key);
/** Get version attribute */
public Version getVersion();
/** Get version attribute with key */
public Version getVersion(String key);
/** Put typed value */
public <T> T putTyped(String key, T value);
/** Get as version range */
public VersionRange getVersionRange();
/** Get as version range with key */
public VersionRange getVersionRange(String key);
/** Get as list */
public List<String> getList(String key);
/** Put list value */
public void putList(String key, List<String> list);
/** Get as boolean */
public boolean getBoolean(String key, boolean defaultValue);
/** Put boolean value */
public void putBoolean(String key, boolean value);
/** Get as integer */
public int getInt(String key, int defaultValue);
/** Put integer value */
public void putInt(String key, int value);
/** Get as long */
public long getLong(String key, long defaultValue);
/** Put long value */
public void putLong(String key, long value);
/** Clone attributes */
public Attrs clone();
/** Merge with other attributes */
public void merge(Attrs other);
}Usage Examples:
import aQute.bnd.header.Attrs;
import aQute.bnd.version.Version;
import aQute.bnd.version.VersionRange;
// Create and populate attributes
Attrs attrs = new Attrs();
attrs.put("version", "1.2.3");
attrs.put("resolution", "optional");
attrs.put("cardinality", "multiple");
attrs.put("effective", "resolve");
// Type conversion
Version version = attrs.getVersion(); // Converts "1.2.3" to Version object
System.out.println("Version: " + version);
// Version range
attrs.put("version", "[1.0,2.0)");
VersionRange range = attrs.getVersionRange();
System.out.println("Range: " + range);
// Boolean values
attrs.put("optional", "true");
boolean isOptional = attrs.getBoolean("optional", false);
System.out.println("Optional: " + isOptional);
// List values
attrs.put("uses", "com.example.api,com.example.spi");
List<String> uses = attrs.getList("uses");
System.out.println("Uses: " + uses);
// Integer values
attrs.put("timeout", "5000");
int timeout = attrs.getInt("timeout", 1000);
System.out.println("Timeout: " + timeout);Utility class for parsing and manipulating specific OSGi headers.
/**
* Utility for OSGi header parsing and manipulation
*/
public class OSGiHeader {
/** Parse header into parameters */
public static Parameters parseHeader(String header);
/** Parse header with processor for macro expansion */
public static Parameters parseHeader(String header, Processor processor);
/** Join parameters into header string */
public static String join(Map<String, ? extends Map<String, String>> map);
/** Join with custom separator */
public static String join(Map<String, ? extends Map<String, String>> map, String separator);
/** Parse single clause */
public static Map.Entry<String, Attrs> parseClause(String clause);
/** Quote value if needed */
public static String quote(String value);
/** Unquote value */
public static String unquote(String value);
/** Check if value needs quoting */
public static boolean needsQuoting(String value);
/** Validate header syntax */
public static boolean isValidHeader(String header);
}Utilities for working with JAR manifests and OSGi headers.
/**
* Utilities for manifest manipulation
*/
public class ManifestUtil {
/** Get main attributes from manifest */
public static Attributes getMainAttributes(Manifest manifest);
/** Set main attribute */
public static void setMainAttribute(Manifest manifest, String name, String value);
/** Get OSGi header as parameters */
public static Parameters getOSGiHeader(Manifest manifest, String headerName);
/** Set OSGi header from parameters */
public static void setOSGiHeader(Manifest manifest, String headerName, Parameters params);
/** Clean manifest (remove empty headers) */
public static void clean(Manifest manifest);
/** Copy manifest */
public static Manifest copy(Manifest source);
/** Merge manifests */
public static Manifest merge(Manifest base, Manifest overlay);
/** Validate manifest for OSGi compliance */
public static List<String> validate(Manifest manifest);
}Common header processing patterns and use cases.
/**
* Common header processing patterns
*/
public class HeaderProcessingExamples {
/** Parse Export-Package header */
public static void parseExportPackage(String header) {
Parameters exports = new Parameters(header);
for (Map.Entry<String, Attrs> entry : exports.entrySet()) {
String packageName = entry.getKey();
Attrs attrs = entry.getValue();
Version version = attrs.getVersion();
List<String> uses = attrs.getList("uses");
boolean mandatory = "mandatory".equals(attrs.get("resolution"));
System.out.println("Export: " + packageName +
" version=" + version +
" uses=" + uses +
" mandatory=" + mandatory);
}
}
/** Parse Import-Package header */
public static void parseImportPackage(String header) {
Parameters imports = new Parameters(header);
for (Map.Entry<String, Attrs> entry : imports.entrySet()) {
String packageName = entry.getKey();
Attrs attrs = entry.getValue();
VersionRange versionRange = attrs.getVersionRange();
boolean optional = "optional".equals(attrs.get("resolution"));
System.out.println("Import: " + packageName +
" version=" + versionRange +
" optional=" + optional);
}
}
/** Parse Require-Bundle header */
public static void parseRequireBundle(String header) {
Parameters requires = new Parameters(header);
for (Map.Entry<String, Attrs> entry : requires.entrySet()) {
String bundleName = entry.getKey();
Attrs attrs = entry.getValue();
VersionRange bundleVersion = attrs.getVersionRange("bundle-version");
boolean optional = "optional".equals(attrs.get("resolution"));
String visibility = attrs.get("visibility");
System.out.println("Require: " + bundleName +
" bundle-version=" + bundleVersion +
" optional=" + optional +
" visibility=" + visibility);
}
}
}Complete Header Processing Example:
import aQute.bnd.header.*;
import aQute.bnd.version.*;
import java.util.jar.Manifest;
// Complete header processing workflow
public class HeaderProcessingWorkflow {
public void processBundle(File bundleFile) throws Exception {
try (Jar jar = new Jar(bundleFile)) {
Manifest manifest = jar.getManifest();
// Process Export-Package header
String exportHeader = manifest.getMainAttributes().getValue("Export-Package");
if (exportHeader != null) {
Parameters exports = new Parameters(exportHeader);
System.out.println("Exported packages:");
for (Map.Entry<String, Attrs> entry : exports.entrySet()) {
String pkg = entry.getKey();
Attrs attrs = entry.getValue();
Version version = attrs.getVersion();
List<String> uses = attrs.getList("uses");
System.out.println(" " + pkg + " v" + version);
if (uses != null && !uses.isEmpty()) {
System.out.println(" uses: " + uses);
}
}
}
// Process Import-Package header
String importHeader = manifest.getMainAttributes().getValue("Import-Package");
if (importHeader != null) {
Parameters imports = new Parameters(importHeader);
System.out.println("Imported packages:");
for (Map.Entry<String, Attrs> entry : imports.entrySet()) {
String pkg = entry.getKey();
Attrs attrs = entry.getValue();
VersionRange range = attrs.getVersionRange();
boolean optional = "optional".equals(attrs.get("resolution"));
System.out.println(" " + pkg + " " + range +
(optional ? " (optional)" : ""));
}
}
// Create new headers
Parameters newExports = new Parameters();
// Add new export
Attrs exportAttrs = new Attrs();
exportAttrs.putTyped("version", new Version(2, 0, 0));
exportAttrs.putList("uses", Arrays.asList("java.util", "java.io"));
newExports.put("com.example.newapi", exportAttrs);
// Update manifest
manifest.getMainAttributes().putValue("Export-Package",
exportHeader + "," + newExports.toString());
// Validate updated manifest
List<String> validationErrors = ManifestUtil.validate(manifest);
if (!validationErrors.isEmpty()) {
System.err.println("Validation errors:");
for (String error : validationErrors) {
System.err.println(" " + error);
}
} else {
System.out.println("Manifest is valid");
}
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-biz-a-qute-bnd--biz-a-qute-bndlib