package org.xpect.registry;
import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xpect.util.ClasspathUtil;
import com.google.common.base.Function;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.io.Closeables;
public class StandaloneExtensionRegistry implements IExtensionInfo.Registry {
protected static class PluginXMLContentHandler extends DefaultHandler {
private int depth;
private final Multimap<String, IExtensionInfo> extensions;
private String point;
private final URL url;
public PluginXMLContentHandler(URL url, Multimap<String, IExtensionInfo> extensions) {
super();
this.url = url;
this.extensions = extensions;
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
switch (depth) {
case 1:
point = null;
break;
}
depth--;
}
@Override
public void startDocument() throws SAXException {
this.depth = 0;
this.point = null;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
switch (depth) {
case 1:
if ("extension".equals(qName))
point = attributes.getValue("point");
break;
case 2:
if (point != null && attributes.getLength() > 0) {
Map<String, String> attrs = Maps.newHashMap();
for (int i = 0; i < attributes.getLength(); i++)
attrs.put(attributes.getQName(i), attributes.getValue(i));
extensions.put(point, new StandaloneExtension(url.toString(), qName, attrs));
}
break;
}
depth++;
}
}
private static class StandaloneExtension implements IExtensionInfo {
private final Map<String, String> attribtues;
private final String loacation;
private final String name;
public StandaloneExtension(String location, String name, Map<String, String> attribtues) {
this.loacation = location;
this.name = name;
this.attribtues = ImmutableMap.copyOf(attribtues);
}
public Collection<String> getAttributes() {
return this.attribtues.keySet();
}
public String getAttributeValue(String name) {
return this.attribtues.get(name);
}
public Function<String, Class<?>> getClassLoader() {
return new Function<String, Class<?>>() {
public Class<?> apply(String input) {
try {
return ClassLoader.getSystemClassLoader().loadClass(input);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
};
}
public String getLocation() {
return loacation;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append("<");
result.append(name);
List<String> attrs = Lists.newArrayList(getAttributes());
Collections.sort(attrs);
for (String attr : attrs) {
result.append(" ");
result.append(attr);
result.append("=\"");
result.append(getAttributeValue(attr));
result.append("\"");
}
result.append(" />");
return result.toString();
}
}
private final static Logger LOG = Logger.getLogger(StandaloneExtensionRegistry.class);
public static void main(String[] args) {
System.out.println(new StandaloneExtensionRegistry().toString());
}
private final Multimap<String, IExtensionInfo> extensions;
public StandaloneExtensionRegistry() {
this.extensions = ImmutableMultimap.copyOf(collectExtensions());
}
public StandaloneExtensionRegistry(URL url, InputStream in) {
this.extensions = ImmutableMultimap.copyOf(collectExtensions(url, in));
}
private Multimap<String, IExtensionInfo> collectExtensions() {
Multimap<String, IExtensionInfo> result = HashMultimap.create();
try {
XMLReader reader = XMLReaderFactory.createXMLReader();
for (URL url : ClasspathUtil.findResources("plugin.xml", "fragment.xml")) {
reader.setContentHandler(new PluginXMLContentHandler(url, result));
InputStream openStream = null;
try {
openStream = url.openStream();
reader.parse(new InputSource(openStream));
} catch (Throwable e) {
LOG.error("Error parsing " + url, e);
} finally {
Closeables.closeQuietly(openStream);
}
}
} catch (Throwable e) {
LOG.error(e.getMessage(), e);
}
return result;
}
private Multimap<String, IExtensionInfo> collectExtensions(URL url, InputStream in) {
Multimap<String, IExtensionInfo> result = HashMultimap.create();
try {
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setContentHandler(new PluginXMLContentHandler(url, result));
reader.parse(new InputSource(in));
} catch (Throwable e) {
LOG.error("Error parsing " + url, e);
}
return result;
}
public Collection<String> getExtensionPoints() {
return extensions.keySet();
}
public Collection<IExtensionInfo> getExtensions(String extensionPointName) {
return this.extensions.get(extensionPointName);
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append("<plugin>\n");
for (String point : getExtensionPoints()) {
result.append(" <extension point=\"");
result.append(point);
result.append("\">\n");
for (IExtensionInfo ext : getExtensions(point)) {
result.append(" ");
result.append(ext.toString());
result.append("\n");
}
}
result.append(" </extension>\n");
result.append("</plugin>");
return result.toString();
}
}