package aQute.p2.provider;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.osgi.framework.Version;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import aQute.lib.converter.Converter;
import aQute.lib.converter.TypeReference;
import aQute.lib.filter.Filter;
import aQute.libg.sed.Domain;
import aQute.libg.sed.ReplacerAdapter;
import aQute.p2.api.Artifact;
/**
* @formatter:off
* <pre>
* <?xml version='1.0' encoding='UTF-8'?>
* <?artifactRepository version='1.1.0'?>
* <repository name='Bndtools' type='org.eclipse.equinox.p2.artifact.repository.simpleRepository' version='1'>
* <properties size='2'>
* <property name='p2.timestamp' value='1463781466748'/>
* <property name='p2.compressed' value='true'/>
* </properties>
* <mappings size='3'>
* <rule filter='(& (classifier=osgi.bundle))' output='${repoUrl}/plugins/${id}_${version}.jar'/>
* <rule filter='(& (classifier=binary))' output='${repoUrl}/binary/${id}_${version}'/>
* <rule filter='(& (classifier=org.eclipse.update.feature))' output='${repoUrl}/features/${id}_${version}.jar'/>
* </mappings>
* <artifacts size='22'>
* <artifact classifier='osgi.bundle' id='org.bndtools.versioncontrol.ignores.plugin.git' version='3.3.0.201605202157'>
* <properties size='3'>
* <property name='artifact.size' value='9356'/>
* <property name='download.size' value='9356'/>
* <property name='download.md5' value='745f389a49189112a785848ad466097b'/>
* </properties>
* </artifact>
* </artifacts>
* </pre>
* @formatter:on
*/
class ArtifactRepository extends XML {
static class Rule {
final Filter filter;
String output;
Rule(String filter, String output) {
this.filter = new Filter(filter);
this.output = output;
}
public boolean matches(Map<String,String> map) throws Exception {
return filter.matchMap(map);
}
}
public static class XMLArtifact {
public String classifier;
public String id;
public String version;
public String format;
}
List<Rule> rules;
List<Artifact> artifacts = new ArrayList<>();
private URI base;
ArtifactRepository(InputStream in, URI base) throws Exception {
super(getDocument(in));
this.base = base;
parse();
}
private Rule createRule(Node ruleNode) {
String filter = getAttribute(ruleNode, "filter");
String output = getAttribute(ruleNode, "output");
return new Rule(filter, output);
}
void parse() throws Exception {
final Map<String,String> properties = getProperties("repository/properties/property");
properties.put("repoUrl", base.resolve("").toString());
final Domain parent = new Domain() {
@Override
public Map<String,String> getMap() {
return properties;
}
@Override
public Domain getParent() {
return null;
}
};
rules = getRules();
NodeList artifactNodes = getNodes("repository/artifacts/artifact");
for (int i = 0; i < artifactNodes.getLength(); i++) {
final Node artifactNode = artifactNodes.item(i).cloneNode(true);
final XMLArtifact xmlArtifact = getFromType(artifactNode, XMLArtifact.class);
final Map<String,String> map = Converter.cnv(new TypeReference<Map<String,String>>() {}, xmlArtifact);
if ("osgi.bundle".equals(xmlArtifact.classifier)) {
Domain domain = new Domain() {
@Override
public Map<String,String> getMap() {
return map;
}
@Override
public Domain getParent() {
return parent;
}
};
ReplacerAdapter ra = new ReplacerAdapter(domain);
for (Rule r : rules) {
if (r.matches(map)) {
String s = ra.process(r.output);
URI uri = new URI(s).normalize();
Artifact artifact = new Artifact();
artifact.uri = uri;
artifact.id = xmlArtifact.id;
artifact.version = new Version(xmlArtifact.version);
artifact.md5 = getProperties(artifactNode, "properties/property").get("download.md5");
artifacts.add(artifact);
break;
}
}
}
}
}
/**
* * <artifact classifier='osgi.bundle'
* id='org.bndtools.versioncontrol.ignores.plugin.git'
* version='3.3.0.201605202157'>
*
* @param item
* @return
* @throws Exception
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
List<Rule> getRules() throws Exception {
List<Rule> rules = new ArrayList<>();
NodeList ruleNodes = getNodes("repository/mappings/rule");
for (int i = 0; i < ruleNodes.getLength(); i++) {
Node ruleNode = ruleNodes.item(i);
Rule rule = createRule(ruleNode);
rules.add(rule);
}
return rules;
}
public List<Artifact> getArtifacts() {
return artifacts;
}
}