aQute.bnd.print.JarPrinter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of biz.aQute.bnd Show documentation
Show all versions of biz.aQute.bnd Show documentation
This command line utility is the Swiss army knife of OSGi. It provides you with a breadth of tools to understand and manage OSGi based systems. This project basically uses bndlib.
package aQute.bnd.print;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Writer;
import java.lang.reflect.Modifier;
import java.util.Formatter;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.Manifest;
import java.util.zip.ZipException;
import aQute.bnd.header.Attrs;
import aQute.bnd.header.Parameters;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Clazz.Def;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Descriptors.PackageRef;
import aQute.bnd.osgi.Descriptors.TypeRef;
import aQute.bnd.osgi.Domain;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.Packages;
import aQute.bnd.osgi.Processor;
import aQute.bnd.osgi.Resource;
import aQute.bnd.osgi.Verifier;
import aQute.lib.collections.MultiMap;
import aQute.lib.hex.Hex;
import aQute.lib.io.IO;
import aQute.lib.strings.Strings;
import aQute.libg.generics.Create;
public class JarPrinter extends Processor {
final Formatter out = new Formatter();
final public static int VERIFY = 1;
final public static int MANIFEST = 2;
final public static int LIST = 4;
final public static int IMPEXP = 16;
final public static int USES = 32;
final public static int USEDBY = 64;
final public static int COMPONENT = 128;
final public static int METATYPE = 256;
final public static int API = 512;
final public static int CAPABILITIES = 1024;
static public final int HEX = 0;
public JarPrinter(Processor bnd) {
super(bnd);
}
public JarPrinter() {}
public JarPrinter doPrint(Jar jar, int options, boolean java, boolean xport)
throws ZipException, IOException, Exception {
if (jar.getManifest() != null) {
if ((options & VERIFY) != 0) {
doVerify(jar);
}
if ((options & MANIFEST) != 0) {
header("MANIFEST");
doManifest(jar);
}
if ((options & IMPEXP) != 0) {
header("IMPEXP");
doImpExp(jar);
println();
}
if ((options & CAPABILITIES) != 0) {
header("CAPABILITIES");
doCapabilities(jar);
println();
}
if ((options & COMPONENT) != 0) {
header("COMPONENTS");
doComponents(jar);
println();
}
if ((options & METATYPE) != 0) {
header("METATYPE");
doMetatype(jar);
println();
}
if ((options & (USES | USEDBY | API)) != 0) {
doXref(jar, options, java, xport);
println();
}
}
if ((options & LIST) != 0) {
header("LIST");
doList(jar);
println();
}
return this;
}
private void header(String string) {
out.format("[%s]%n%n", string);
}
public void doXref(Jar jar, int options, boolean java, boolean xport) throws Exception, IOException {
println();
try (Analyzer analyzer = new Analyzer()) {
analyzer.setPedantic(isPedantic());
analyzer.setJar(jar);
analyzer.removeClose(jar);
Manifest m = jar.getManifest();
if (m != null) {
String s = m.getMainAttributes()
.getValue(Constants.EXPORT_PACKAGE);
if (s != null)
analyzer.setExportPackage(s);
}
analyzer.analyze();
Packages exports = analyzer.getExports();
if ((options & API) != 0) {
Map> apiUses = analyzer.cleanupUses(analyzer.getAPIUses(), !java);
if (!xport) {
if (exports.isEmpty())
warning("Not filtering on exported only since exports are empty");
else
apiUses.keySet()
.retainAll(analyzer.getExports()
.keySet());
}
header("API USES");
MultiMap.format(apiUses);
Set privates = analyzer.getPrivates();
for (PackageRef export : exports.keySet()) {
Map> xRef = analyzer.getXRef(export, privates,
Modifier.PROTECTED + Modifier.PUBLIC);
if (!xRef.isEmpty()) {
println();
out.format("%s refers to private Packages (not good)\n\n", export);
for (Entry> e : xRef.entrySet()) {
TreeSet refs = new TreeSet<>();
for (TypeRef ref : e.getValue())
refs.add(ref.getPackageRef());
refs.retainAll(privates);
out.format("%60s %-40s %s\n", e.getKey()
.getOwnerType()
.getFQN() //
, e.getKey()
.getName(),
refs);
}
println();
}
}
println();
}
Map> uses = analyzer.cleanupUses(analyzer.getUses(), !java);
if ((options & USES) != 0) {
header("USES");
println(MultiMap.format(uses));
println();
}
if ((options & USEDBY) != 0) {
header("USEDBY");
MultiMap usedBy = new MultiMap<>(uses).transpose();
println(MultiMap.format(usedBy));
}
}
}
public void doList(Jar jar) {
for (Map.Entry> entry : jar.getDirectories()
.entrySet()) {
String name = entry.getKey();
Map contents = entry.getValue();
println(name);
if (contents != null) {
for (String element : contents.keySet()) {
int n = element.lastIndexOf('/');
if (n > 0)
element = element.substring(n + 1);
out.format(" %s", element);
String path = element;
if (name.length() != 0)
path = name + "/" + element;
Resource r = contents.get(path);
if (r != null) {
String extra = r.getExtra();
if (extra != null) {
out.format(" extra='%s'", Hex.toHexString(Resource.decodeExtra(extra)));
}
}
println();
}
} else {
println(name + " ");
}
}
println();
}
public void doCapabilities(Jar jar) throws Exception {
Manifest m = jar.getManifest();
Domain domain = Domain.domain(m);
if (m != null) {
Parameters provide = domain.getProvideCapability();
Parameters require = domain.getRequireCapability();
print(Constants.PROVIDE_CAPABILITY, new TreeMap<>(provide));
print(Constants.REQUIRE_CAPABILITY, new TreeMap<>(require));
} else
warning("File has no manifest");
}
public void doImpExp(Jar jar) throws Exception {
Manifest m = jar.getManifest();
if (m != null) {
Domain domain = Domain.domain(m);
Parameters imports = domain.getImportPackage();
Parameters exports = domain.getExportPackage();
for (String p : exports.keySet()) {
if (imports.containsKey(p)) {
Attrs attrs = imports.get(p);
if (attrs.containsKey(VERSION_ATTRIBUTE)) {
exports.get(p)
.put("imported-as", attrs.get(VERSION_ATTRIBUTE));
}
}
}
print(Constants.IMPORT_PACKAGE, new TreeMap<>(imports));
println();
print(Constants.EXPORT_PACKAGE, new TreeMap<>(exports));
} else
warning("File has no manifest");
}
public void doVerify(Jar jar) throws Exception, IOException {
try (Verifier verifier = new Verifier(jar)) {
verifier.setPedantic(isPedantic());
verifier.verify();
getInfo(verifier);
}
}
public void doManifest(Jar jar) throws Exception {
Manifest manifest = jar.getManifest();
if (manifest == null)
warning("JAR has no manifest %s", jar);
else {
doManifest(manifest);
}
println();
}
private JarPrinter println(String string) {
out.format("%s\n", string);
return this;
}
public JarPrinter println() {
out.format("%n");
return this;
}
/**
* @param manifest
*/
public JarPrinter doManifest(Manifest manifest) {
MultiMap table = new MultiMap<>();
manifest.getMainAttributes()
.forEach((k, v) -> {
String key = k.toString();
if (OSGI_SYNTAX_HEADERS.contains(key)) {
table.put(key, Strings.splitQuoted(v.toString()));
} else {
table.add(key, v.toString());
}
});
println(MultiMap.format(table));
return this;
}
/**
* Print the components in this JAR.
*
* @param jar
*/
private void doComponents(Jar jar) throws Exception {
Manifest manifest = jar.getManifest();
if (manifest == null) {
println("No manifest");
return;
}
String componentHeader = manifest.getMainAttributes()
.getValue(Constants.SERVICE_COMPONENT);
Parameters clauses = new Parameters(componentHeader, this);
for (String path : clauses.keySet()) {
println(path);
Resource r = jar.getResource(path);
if (r != null) {
try (InputStreamReader ir = new InputStreamReader(r.openInputStream(), Constants.DEFAULT_CHARSET)) {
IO.copy(ir, getWriter());
}
} else {
println(" - no resource");
warning("No Resource found for service component: %s", path);
}
}
println();
}
public Writer getWriter() {
return IO.appendableToWriter(out.out());
}
/**
* Print the metatypes in this JAR.
*
* @param jar
*/
public void doMetatype(Jar jar) throws Exception {
Manifest manifest = jar.getManifest();
if (manifest == null) {
println("No manifest");
return;
}
Map map = jar.getDirectories()
.get("OSGI-INF/metatype");
if (map != null) {
for (Map.Entry entry : map.entrySet()) {
println(entry.getKey());
IO.copy(entry.getValue()
.openInputStream(), getWriter());
println();
}
println();
}
}
/**
* @param msg
* @param ports
*/
public void print(String msg, Map, ? extends Map, ?>> ports) {
if (ports.isEmpty())
return;
out.format("%s%n", msg);
for (Entry, ? extends Map, ?>> entry : ports.entrySet()) {
Object key = entry.getKey();
Map, ?> clause = Create.copy((Map, ?>) entry.getValue());
clause.remove("uses:");
out.format(" %-38s %s\n", Processor.removeDuplicateMarker(key.toString()
.trim()), clause.isEmpty() ? "" : clause.toString());
}
}
@Override
public String toString() {
return out.toString();
}
}