
aQute.bnd.osgi.repository.XMLResourceGenerator 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
The newest version!
package aQute.bnd.osgi.repository;
import static aQute.bnd.osgi.repository.XMLResourceConstants.ATTR_NAME;
import static aQute.bnd.osgi.repository.XMLResourceConstants.ATTR_NAMESPACE;
import static aQute.bnd.osgi.repository.XMLResourceConstants.ATTR_REFERRAL_DEPTH;
import static aQute.bnd.osgi.repository.XMLResourceConstants.ATTR_REFERRAL_URL;
import static aQute.bnd.osgi.repository.XMLResourceConstants.ATTR_REPOSITORY_INCREMENT;
import static aQute.bnd.osgi.repository.XMLResourceConstants.ATTR_REPOSITORY_NAME;
import static aQute.bnd.osgi.repository.XMLResourceConstants.ATTR_TYPE;
import static aQute.bnd.osgi.repository.XMLResourceConstants.ATTR_VALUE;
import static aQute.bnd.osgi.repository.XMLResourceConstants.NS_URI;
import static aQute.bnd.osgi.repository.XMLResourceConstants.TAG_ATTRIBUTE;
import static aQute.bnd.osgi.repository.XMLResourceConstants.TAG_CAPABILITY;
import static aQute.bnd.osgi.repository.XMLResourceConstants.TAG_DIRECTIVE;
import static aQute.bnd.osgi.repository.XMLResourceConstants.TAG_REFERRAL;
import static aQute.bnd.osgi.repository.XMLResourceConstants.TAG_REPOSITORY;
import static aQute.bnd.osgi.repository.XMLResourceConstants.TAG_REQUIREMENT;
import static aQute.bnd.osgi.repository.XMLResourceConstants.TAG_RESOURCE;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.zip.GZIPOutputStream;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
import org.osgi.service.repository.ContentNamespace;
import org.osgi.service.repository.Repository;
import aQute.bnd.osgi.resource.ResourceUtils;
import aQute.bnd.osgi.resource.TypedAttribute;
import aQute.bnd.service.resource.SupportingResource;
import aQute.bnd.stream.MapStream;
import aQute.lib.io.IO;
import aQute.lib.tag.Tag;
/**
* Can turn an OSGi repository into an
* {@code http://www.osgi.org/xmlns/repository/v1.0.0} XML file. See the
* Repository spec in OSGi.
*/
public class XMLResourceGenerator {
private Tag repository = new Tag(TAG_REPOSITORY);
private Set visited = new HashSet<>();
private int indent = 0;
private boolean compress = false;
private URI base;
/**
* Creates a new instance of {@code XMLResourceGenerator} with an empty
* repository.
*/
public XMLResourceGenerator() {
repository.addAttribute("xmlns", NS_URI);
}
/**
* Saves the contents of this generator to the specified file.
*
* @param location The file to save the contents to.
* @throws IOException If an I/O error occurs.
*/
public void save(File location) throws IOException {
if (location.getName()
.endsWith(".gz"))
compress = true;
IO.mkdirs(location.getParentFile());
File tmp = IO.createTempFile(location.getParentFile(), "index", ".xml");
try (OutputStream out = IO.outputStream(tmp)) {
save(out);
}
IO.rename(tmp, location);
}
/**
* Saves the contents of this generator to the specified output stream.
*
* @param out The output stream to save the contents to.
* @throws IOException If an I/O error occurs.
*/
public void save(OutputStream out) throws IOException {
try {
if (compress) {
out = new GZIPOutputStream(out);
}
try (Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
PrintWriter pw = new PrintWriter(writer)) {
pw.printf("\n");
repository.print(indent, pw);
}
} finally {
out.close();
}
}
/**
* Note that calling {@link #name(String)} sets increment to
* {@link System#currentTimeMillis()}. In order to retain backward
* compatibility that is not change. Therefore, in order to specify a value
* {@link #increment(long)} should be called after.
*
* @param name
* @return this
*/
public XMLResourceGenerator name(String name) {
repository.addAttribute(ATTR_REPOSITORY_NAME, name);
repository.addAttribute(ATTR_REPOSITORY_INCREMENT, System.currentTimeMillis());
return this;
}
/**
* Note that calling {@link #name(String)} sets increment to
* {@link System#currentTimeMillis()}. In order to retain backward
* compatibility that is not change. Therefore, in order to specify a value
* {@link #increment(long)} should be called after.
*
* @param increment
* @return this
*/
public XMLResourceGenerator increment(long increment) {
repository.addAttribute(ATTR_REPOSITORY_INCREMENT, increment);
return this;
}
/**
* Adds a referral to this generator.
*
* @param reference The URI of the referral.
* @param depth The depth of the referral.
* @return This generator.
*/
public XMLResourceGenerator referral(URI reference, int depth) {
Tag referall = new Tag(repository, TAG_REFERRAL);
referall.addAttribute(ATTR_REFERRAL_URL, reference);
if (depth > 0)
referall.addAttribute(ATTR_REFERRAL_DEPTH, depth);
return this;
}
/**
* Adds all the resources in the specified repository to this generator.
*
* @param repository The repository whose resources to add.
* @return This generator.
*/
public XMLResourceGenerator repository(Repository repository) {
Requirement wildcard = ResourceUtils.createWildcardRequirement();
Map> findProviders = repository
.findProviders(Collections.singleton(wildcard));
findProviders.get(wildcard)
.stream()
.map(Capability::getResource)
.forEach(this::resource);
return this;
}
/**
* Adds all the resources in the specified collection to this generator.
*
* @param resources The resources to add.
* @return This generator.
*/
public XMLResourceGenerator resources(Collection extends Resource> resources) {
resources.forEach(this::resource);
return this;
}
/**
* Adds the specified resource to this generator.
*
* @param resource The resource to add.
* @return This generator.
*/
public XMLResourceGenerator resource(Resource resource) {
if (!visited.contains(resource)) {
visited.add(resource);
resource0(resource);
if (resource instanceof SupportingResource s) {
s.getSupportingResources()
.forEach(this::resource0);
}
}
return this;
}
void resource0(Resource resource) {
Tag r = new Tag(repository, TAG_RESOURCE);
List caps = resource.getCapabilities(null);
caps.forEach(cap -> {
Tag cr = new Tag(r, TAG_CAPABILITY);
cr.addAttribute(ATTR_NAMESPACE, cap.getNamespace());
directives(cr, cap.getDirectives());
attributes(cr, cap.getAttributes());
});
List reqs = resource.getRequirements(null);
reqs.forEach(req -> {
Tag cr = new Tag(r, TAG_REQUIREMENT);
cr.addAttribute(ATTR_NAMESPACE, req.getNamespace());
directives(cr, req.getDirectives());
attributes(cr, req.getAttributes());
});
}
private void directives(Tag cr, Map directives) {
directives.forEach((key, value) -> {
Tag d = new Tag(cr, TAG_DIRECTIVE);
d.addAttribute(ATTR_NAME, key);
d.addAttribute(ATTR_VALUE, value);
});
}
private void attributes(Tag cr, Map attributes) {
boolean isContent = isContent(cr);
MapStream.of(attributes)
.filterValue(Objects::nonNull)
.mapValue(TypedAttribute::getTypedAttribute)
.filterValue(Objects::nonNull)
.forEachOrdered((key, ta) -> {
String value = (isContent && ContentNamespace.CAPABILITY_URL_ATTRIBUTE.equals(key))
? relativize(ta.value)
: ta.value;
Tag d = new Tag(cr, TAG_ATTRIBUTE);
d.addAttribute(ATTR_NAME, key);
d.addAttribute(ATTR_VALUE, value);
if (ta.type != null)
d.addAttribute(ATTR_TYPE, ta.type);
});
}
private boolean isContent(Tag cr) {
return ContentNamespace.CONTENT_NAMESPACE.equals(cr.getAttribute(ATTR_NAMESPACE));
}
private String relativize(String value) {
if (base == null) {
return value;
}
try {
URI uri = new URI(value);
return base.relativize(uri)
.toString();
} catch (URISyntaxException e) {
return value;
}
}
/**
* Sets the indentation level for the generated XML document.
*
* @param n The number of spaces for each indentation level.
* @return This generator.
*/
public XMLResourceGenerator indent(int n) {
this.indent = n;
return this;
}
/**
* Enables compression for the generated XML document.
*
* @return This generator.
*/
public XMLResourceGenerator compress() {
this.compress = true;
return this;
}
/**
* @param base the base URI from which the index urls are relative
*/
public XMLResourceGenerator base(URI base) {
this.base = base;
return this;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy