aQute.bnd.deployer.repository.providers.R5RepoContentProvider Maven / Gradle / Ivy
The newest version!
package aQute.bnd.deployer.repository.providers;
import static aQute.bnd.deployer.repository.api.Decision.accept;
import static aQute.bnd.deployer.repository.api.Decision.reject;
import static aQute.bnd.deployer.repository.api.Decision.undecided;
import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Set;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.osgi.resource.Resource;
import org.osgi.service.log.LogService;
import org.osgi.service.repository.ContentNamespace;
import aQute.bnd.deployer.repository.api.CheckResult;
import aQute.bnd.deployer.repository.api.IRepositoryContentProvider;
import aQute.bnd.deployer.repository.api.IRepositoryIndexProcessor;
import aQute.bnd.deployer.repository.api.Referral;
import aQute.bnd.osgi.repository.SimpleIndexer;
import aQute.bnd.osgi.resource.CapReqBuilder;
import aQute.bnd.osgi.resource.ResourceBuilder;
import aQute.bnd.service.Registry;
public class R5RepoContentProvider implements IRepositoryContentProvider {
public static final String NAME = "R5";
private static final String NS_URI = "http://www.osgi.org/xmlns/repository/v1.0.0";
private static final String INDEX_NAME_COMPRESSED = "index.xml.gz";
private static final String INDEX_NAME_PRETTY = "index.xml";
private static final String TAG_REPOSITORY = "repository";
private static final String TAG_REFERRAL = "referral";
private static final String TAG_RESOURCE = "resource";
private static final String TAG_CAPABILITY = "capability";
private static final String TAG_REQUIREMENT = "requirement";
private static final String TAG_ATTRIBUTE = "attribute";
private static final String TAG_DIRECTIVE = "directive";
private static final String ATTR_REFERRAL_URL = "url";
private static final String ATTR_REFERRAL_DEPTH = "depth";
private static final String ATTR_NAMESPACE = "namespace";
private static final String ATTR_NAME = "name";
private static final String ATTR_VALUE = "value";
private static final String ATTR_TYPE = "type";
@Override
public String getName() {
return NAME;
}
@Override
public String getDefaultIndexName(boolean pretty) {
return pretty ? INDEX_NAME_PRETTY : INDEX_NAME_COMPRESSED;
}
private static enum ParserState {
beforeRoot,
inRoot,
inResource,
inCapability
}
@Override
public CheckResult checkStream(String name, InputStream stream) throws IOException {
XMLStreamReader reader = null;
try {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
inputFactory.setProperty(XMLInputFactory.IS_VALIDATING, false);
inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
reader = inputFactory.createXMLStreamReader(stream);
ParserState state = ParserState.beforeRoot;
while (reader.hasNext()) {
int type = reader.next();
String localName;
switch (type) {
case START_ELEMENT :
localName = reader.getLocalName();
switch (state) {
case beforeRoot :
String nsUri = reader.getNamespaceURI();
if (nsUri != null)
return CheckResult.fromBool(NS_URI.equals(nsUri), "Corrent namespace",
"Incorrect namespace: " + nsUri, null);
if (!TAG_REPOSITORY.equals(localName))
return new CheckResult(reject, "Incorrect root element name", null);
state = ParserState.inRoot;
break;
case inRoot :
if (TAG_RESOURCE.equals(localName)) {
state = ParserState.inResource;
}
break;
case inResource :
if (TAG_REQUIREMENT.equals(localName))
return new CheckResult(accept, "Recognised element 'requirement' in 'resource'",
null);
if (TAG_CAPABILITY.equals(localName))
state = ParserState.inCapability;
break;
case inCapability :
if (TAG_ATTRIBUTE.equals(localName) || TAG_DIRECTIVE.equals(localName)) {
return new CheckResult(accept, "Recognised element '%s' in 'capability'", null);
}
break;
}
break;
case END_ELEMENT :
localName = reader.getLocalName();
if (state == ParserState.inResource && TAG_RESOURCE.equals(localName))
state = ParserState.inRoot;
if (state == ParserState.inCapability && TAG_CAPABILITY.equals(localName))
state = ParserState.inResource;
break;
default :
break;
}
}
return new CheckResult(undecided, "Reached end of stream", null);
} catch (XMLStreamException e) {
return new CheckResult(reject, "Invalid XML", e);
} finally {
if (reader != null)
try {
reader.close();
} catch (XMLStreamException e) {}
}
}
@Override
public void parseIndex(InputStream stream, URI baseUri, IRepositoryIndexProcessor listener, LogService log)
throws Exception {
XMLStreamReader reader = null;
try {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
inputFactory.setProperty(XMLInputFactory.IS_VALIDATING, false);
inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
reader = inputFactory.createXMLStreamReader(stream);
ResourceBuilder resourceBuilder = null;
CapReqBuilder capReqBuilder = null;
while (reader.hasNext()) {
int type = reader.next();
String localName;
switch (type) {
case START_ELEMENT :
localName = reader.getLocalName();
if (TAG_REFERRAL.equals(localName)) {
String url = reader.getAttributeValue(null, ATTR_REFERRAL_URL);
String depth = reader.getAttributeValue(null, ATTR_REFERRAL_DEPTH);
Referral referral = new Referral(url, parseInt(depth));
listener.processReferral(baseUri, referral, 0, 0);
} else if (TAG_RESOURCE.equals(localName)) {
resourceBuilder = new ResourceBuilder();
} else if (TAG_CAPABILITY.equals(localName) || TAG_REQUIREMENT.equals(localName)) {
String namespace = reader.getAttributeValue(null, ATTR_NAMESPACE);
capReqBuilder = new CapReqBuilder(namespace);
} else if (TAG_ATTRIBUTE.equals(localName)) {
String name = reader.getAttributeValue(null, ATTR_NAME);
String valueStr = reader.getAttributeValue(null, ATTR_VALUE);
String typeAttr = reader.getAttributeValue(null, ATTR_TYPE);
if (capReqBuilder != null) {
// If the attribute is 'url' on the osgi.content
// namespace then resolve it relative to the
// base URI.
if (ContentNamespace.CONTENT_NAMESPACE.equals(capReqBuilder.getNamespace())
&& ContentNamespace.CAPABILITY_URL_ATTRIBUTE.equals(name)) {
URI resolvedUri = resolveUri(valueStr, baseUri);
capReqBuilder.addAttribute(name, resolvedUri);
} else {
Object convertedAttr = convertAttribute(valueStr, typeAttr);
capReqBuilder.addAttribute(name, convertedAttr);
}
}
} else if (TAG_DIRECTIVE.equals(localName)) {
String name = reader.getAttributeValue(null, ATTR_NAME);
String valueStr = reader.getAttributeValue(null, ATTR_VALUE);
if (capReqBuilder != null)
capReqBuilder.addDirective(name, valueStr);
}
break;
case END_ELEMENT :
localName = reader.getLocalName();
if (TAG_CAPABILITY.equals(localName)) {
if (resourceBuilder != null && capReqBuilder != null)
resourceBuilder.addCapability(capReqBuilder);
capReqBuilder = null;
} else if (TAG_REQUIREMENT.equals(localName)) {
if (resourceBuilder != null && capReqBuilder != null)
resourceBuilder.addRequirement(capReqBuilder);
capReqBuilder = null;
} else if (TAG_RESOURCE.equals(localName)) {
if (resourceBuilder != null) {
Resource resource = resourceBuilder.build();
listener.processResource(resource);
resourceBuilder = null;
}
}
break;
}
}
} finally {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {}
}
}
}
private static URI resolveUri(String uriStr, URI baseUri) throws URISyntaxException {
URI resolved;
URI resourceUri = new URI(uriStr);
if (resourceUri.isAbsolute())
resolved = resourceUri;
else
resolved = baseUri.resolve(resourceUri);
return resolved;
}
private static int parseInt(String value) {
if (value == null || "".equals(value))
return 0;
return Integer.parseInt(value);
}
private static Object convertAttribute(String value, String type) {
AttributeType attType = AttributeType.parseTypeName(type);
return attType.parseString(value);
}
@Override
public boolean supportsGeneration() {
return true;
}
@Override
public void generateIndex(Set files, OutputStream output, String repoName, URI baseUri, boolean pretty,
Registry registry, LogService log) throws Exception {
long modified = files.stream()
.mapToLong(File::lastModified)
.max()
.orElse(-1L);
new SimpleIndexer().files(files)
.base(baseUri)
.compress(!pretty)
.name(repoName)
.increment(modified)
.index(output);
}
}