package aQute.library.capreq;
import static javax.xml.stream.XMLStreamConstants.*;
import java.io.*;
import java.util.*;
import javax.xml.stream.*;
import org.osgi.resource.*;
import aQute.library.capreq.FilterParser.Expression;
public class Engine {
FilterParser parser = new FilterParser();
private Set<ResourceImpl> resources = new HashSet<ResourceImpl>();
ResourceImpl local = new ResourceImpl(this);
/**
* Parse an OBR xml file into Resources.
*
* @param obrFile
* @return
* @throws Exception
*/
public void parse(File obrFile) throws Exception {
Set<ResourceImpl> set = new HashSet<ResourceImpl>();
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
inputFactory.setProperty(XMLInputFactory.IS_VALIDATING, false);
inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
FileReader reader = new FileReader(obrFile);
try {
XMLStreamReader xml = inputFactory.createXMLStreamReader(reader);
while (xml.hasNext()) {
int type = xml.next();
String localName;
switch (type) {
case START_ELEMENT :
localName = xml.getLocalName();
if ("resource".equals(localName)) {
set.add(doResource(xml));
}
break;
case END_ELEMENT :
localName = xml.getLocalName();
if (!localName.equals("repository"))
throw new UnsupportedOperationException("Did not expect an END_ELEMENT for "
+ xml.getLocalName());
}
}
}
finally {
reader.close();
}
this.resources = set;
}
private ResourceImpl doResource(XMLStreamReader xml) throws Exception {
ResourceImpl resource = new ResourceImpl(this);
while (xml.hasNext()) {
int type = xml.next();
switch (type) {
case START_ELEMENT : {
String localName = xml.getLocalName();
if ("capability".equals(localName)) {
doNamespace(xml, new CapabilityImpl(resource, xml.getAttributeValue(null, "namespace")));
} else if ("requirement".equals(localName)) {
doNamespace(xml, new RequirementImpl(resource, xml.getAttributeValue(null, "namespace")));
} else
throw new UnsupportedOperationException("Unknwon START_ELEMENT for " + xml.getLocalName());
break;
}
case END_ELEMENT : {
String localName = xml.getLocalName();
if ("resource".equals(localName))
return resource;
throw new UnsupportedOperationException("Unknwon END_ELEMENT for " + xml.getLocalName());
}
}
}
throw new IllegalArgumentException("Invalid XML, expected END_ELEMENT for resource, got eof");
}
private <T extends NamespaceImpl> void doNamespace(XMLStreamReader xml, T ns) throws Exception {
while (xml.hasNext()) {
int type = xml.next();
switch (type) {
case START_ELEMENT : {
String localName = xml.getLocalName();
if ("attribute".equals(localName)) {
if (ns.attributes == null)
ns.attributes = new HashMap<String,Object>();
doAttribute(xml, ns.attributes, null);
} else if ("directive".equals(localName)) {
if (ns.directives == null)
ns.directives = new HashMap<String,String>();
doAttribute(xml, null, ns.directives);
} else
throw new UnsupportedOperationException("Unknwon START_ELEMENT for " + xml.getLocalName());
break;
}
case END_ELEMENT : {
String localName = xml.getLocalName();
if ("capability".equals(localName) || "requirement".equals(localName)) {
return;
} else
throw new UnsupportedOperationException("Unknwon END_ELEMENT for " + xml.getLocalName());
}
}
}
}
private void doAttribute(XMLStreamReader xml, Map<String,Object> attrs, Map<String,String> directives)
throws XMLStreamException {
String name = xml.getAttributeValue(null, "name");
String value = xml.getAttributeValue(null, "value");
if (directives != null) {
directives.put(name, value);
ensure(xml, "directive");
return;
}
String type = xml.getAttributeValue(null, "type");
attrs.put(name, convert(type, value));
ensure(xml, "attribute");
}
private void ensure(XMLStreamReader xml, String string) throws XMLStreamException {
int type = xml.next();
if (type != END_ELEMENT && !xml.getLocalName().equals(string))
throw new IllegalArgumentException("Expected end element for " + string);
}
private Object convert(String type, String value) {
if (type == null || type.equals("String"))
return value;
if (type.startsWith("List<") && type.endsWith(">")) {
type = type.substring(5, type.length() - 1);
String members[] = value.split("\\s*,\\s*");
List<Object> result = new ArrayList<Object>();
for (String member : members) {
result.add(convert(type, member));
}
return result;
} else if ("Long".equals(type)) {
return Long.parseLong(value);
} else if ("Version".equals(type)) {
return org.osgi.framework.Version.parseVersion(value);
} else if ("Double".equals(type)) {
return Double.parseDouble(value);
} else
throw new IllegalArgumentException("Invalid type: " + type);
}
public Collection<ResourceImpl> getResources() {
return resources;
}
public Expression filter(String filter) {
try {
return parser.parse(filter);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
public boolean match(org.osgi.resource.Requirement req, Map<String,Object> attributes) throws IOException {
if (req instanceof RequirementImpl)
return ((RequirementImpl) req).match(attributes);
String f = req.getDirectives().get("filter");
if (f == null)
return false;
Expression parse = parser.parse(f);
return parse.eval(attributes);
}
public RequirementImpl createRequirement(String namespace, String filter) {
RequirementImpl req = new RequirementImpl(local, namespace);
req.setFilter(filter);
return req;
}
public List<Capability> findProviders(Requirement rq) throws IOException {
List<Capability> providers = new ArrayList<Capability>();
Expression exp = null;
if (!(rq instanceof RequirementImpl)) {
exp = parser.parse(rq.getDirectives().get("filter"));
} else
exp = ((RequirementImpl) rq).getFilter();
for (ResourceImpl rs : getResources()) {
for (Capability cap : rs.getCapabilities(rq.getNamespace())) {
if (exp.eval(cap.getAttributes()))
providers.add(cap);
}
}
return providers;
}
public static boolean isMandatory(org.osgi.resource.Requirement req) {
String resolution = req.getDirectives().get("resolution");
if (resolution == null || "mandatory".equalsIgnoreCase(resolution))
return true;
return false;
}
}