Temporarily include bndlib 1.47 for testing purposes (not yet on central)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1185095 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/libg/sax/ContentFilter.java b/bundleplugin/src/main/java/aQute/libg/sax/ContentFilter.java
new file mode 100644
index 0000000..62ca259
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sax/ContentFilter.java
@@ -0,0 +1,8 @@
+package aQute.libg.sax;
+
+import org.xml.sax.ContentHandler;
+
+public interface ContentFilter extends ContentHandler {
+	void setParent(ContentHandler parent);
+	ContentHandler getParent();
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/sax/ContentFilterImpl.java b/bundleplugin/src/main/java/aQute/libg/sax/ContentFilterImpl.java
new file mode 100644
index 0000000..7f71568
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sax/ContentFilterImpl.java
@@ -0,0 +1,71 @@
+package aQute.libg.sax;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+public class ContentFilterImpl implements ContentFilter {
+
+	private ContentHandler parent;
+
+	public void setParent(ContentHandler parent) {
+		this.parent = parent;
+		
+	}
+
+	public ContentHandler getParent() {
+		return parent;
+	}
+
+	public void setDocumentLocator(Locator locator) {
+		parent.setDocumentLocator(locator);
+	}
+
+	public void startDocument() throws SAXException {
+		parent.startDocument();
+	}
+
+	public void endDocument() throws SAXException {
+		parent.endDocument();
+	}
+
+	public void startPrefixMapping(String prefix, String uri)
+			throws SAXException {
+		parent.startPrefixMapping(prefix, uri);
+	}
+
+	public void endPrefixMapping(String prefix) throws SAXException {
+		parent.endPrefixMapping(prefix);
+	}
+
+	public void startElement(String uri, String localName, String qName,
+			Attributes atts) throws SAXException {
+		parent.startElement(uri, localName, qName, atts);
+	}
+
+	public void endElement(String uri, String localName, String qName)
+			throws SAXException {
+		parent.endElement(uri, localName, qName);
+	}
+
+	public void characters(char[] ch, int start, int length)
+			throws SAXException {
+		parent.characters(ch, start, length);
+	}
+
+	public void ignorableWhitespace(char[] ch, int start, int length)
+			throws SAXException {
+		parent.ignorableWhitespace(ch, start, length);
+	}
+
+	public void processingInstruction(String target, String data)
+			throws SAXException {
+		parent.processingInstruction(target, data);
+	}
+
+	public void skippedEntity(String name) throws SAXException {
+		parent.skippedEntity(name);
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/sax/SAXElement.java b/bundleplugin/src/main/java/aQute/libg/sax/SAXElement.java
new file mode 100644
index 0000000..b7ce35e
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sax/SAXElement.java
@@ -0,0 +1,36 @@
+package aQute.libg.sax;
+
+import org.xml.sax.Attributes;
+
+public class SAXElement {
+
+	private final String uri;
+	private final String localName;
+	private final String qName;
+	private final Attributes atts;
+
+	public SAXElement(String uri, String localName, String qName,
+			Attributes atts) {
+		this.uri = uri;
+		this.localName = localName;
+		this.qName = qName;
+		this.atts = atts;
+	}
+
+	public String getUri() {
+		return uri;
+	}
+
+	public String getLocalName() {
+		return localName;
+	}
+
+	public String getqName() {
+		return qName;
+	}
+
+	public Attributes getAtts() {
+		return atts;
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/sax/SAXUtil.java b/bundleplugin/src/main/java/aQute/libg/sax/SAXUtil.java
new file mode 100644
index 0000000..87b058e
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sax/SAXUtil.java
@@ -0,0 +1,29 @@
+package aQute.libg.sax;
+
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.XMLReader;
+
+public class SAXUtil {
+	
+	public static XMLReader buildPipeline(Result output, ContentFilter... filters) throws Exception {
+		SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+		TransformerHandler handler = factory.newTransformerHandler();
+		handler.setResult(output);
+		
+		ContentHandler last = handler;
+		if (filters != null) for (ContentFilter filter : filters) {
+			filter.setParent(last);
+			last = filter;
+		}
+		XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
+		reader.setContentHandler(last);
+		
+		return reader;
+	}
+	
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/sax/filters/ElementSelectionFilter.java b/bundleplugin/src/main/java/aQute/libg/sax/filters/ElementSelectionFilter.java
new file mode 100644
index 0000000..4411db9
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sax/filters/ElementSelectionFilter.java
@@ -0,0 +1,49 @@
+package aQute.libg.sax.filters;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import aQute.libg.sax.ContentFilterImpl;
+
+public abstract class ElementSelectionFilter extends ContentFilterImpl{
+	
+	int depth = 0;
+	int hiddenDepth = -1;
+	
+	protected abstract boolean select(int depth, String uri, String localName, String qName, Attributes attribs);
+	
+	@Override
+	public final void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+		if (hiddenDepth < 0) {
+			boolean allow = select(depth, uri, localName, qName, atts);
+			if (allow)
+				super.startElement(uri, localName, qName, atts);
+			else
+				hiddenDepth = 0;
+		} else {
+			hiddenDepth ++;
+		}
+		depth++;
+	}
+	
+	@Override
+	public final void endElement(String uri, String localName, String qName) throws SAXException {
+		if (hiddenDepth < 0) {
+			super.endElement(uri, localName, qName);
+		} else {
+			hiddenDepth --;
+		}
+		depth --;
+	}
+	
+	@Override
+	public void characters(char[] ch, int start, int length) throws SAXException {
+		if (hiddenDepth < 0) super.characters(ch, start, length);
+	}
+	
+	@Override
+	public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+		if (hiddenDepth < 0) super.ignorableWhitespace(ch, start, length);
+	}
+	
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/sax/filters/MergeContentFilter.java b/bundleplugin/src/main/java/aQute/libg/sax/filters/MergeContentFilter.java
new file mode 100644
index 0000000..acf5d12
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sax/filters/MergeContentFilter.java
@@ -0,0 +1,57 @@
+package aQute.libg.sax.filters;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import aQute.libg.sax.ContentFilterImpl;
+import aQute.libg.sax.SAXElement;
+
+public class MergeContentFilter extends ContentFilterImpl {
+
+	private int elementDepth = 0;
+	
+	private final List<SAXElement> rootElements = new LinkedList<SAXElement>();
+	
+	@Override
+	public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+		if (elementDepth++ == 0) {
+			if (rootElements.isEmpty())
+				super.startElement(uri, localName, qName, atts);
+			else if (!rootElements.get(0).getqName().equals(qName))
+				throw new SAXException(String.format("Documents have inconsistent root element names: first was %s, current is %s.", rootElements.get(0).getqName(), qName));
+			rootElements.add(new SAXElement(uri, localName, qName, atts));
+		} else {
+			super.startElement(uri, localName, qName, atts);
+		}
+	}
+
+	@Override
+	public void endElement(String uri, String localName, String qName) throws SAXException {
+		if (--elementDepth > 0) {
+			super.endElement(uri, localName, qName);
+		}
+	}
+	
+	@Override
+	public void processingInstruction(String target, String data) throws SAXException {
+		if (rootElements.isEmpty())
+			super.processingInstruction(target, data);
+	}
+	
+	public void closeRootAndDocument() throws SAXException {
+		if (!rootElements.isEmpty()) {
+			SAXElement root = rootElements.get(0);
+			super.endElement(root.getUri(), root.getLocalName(), root.getqName());
+		}
+		super.endDocument();
+	}
+	
+	public List<SAXElement> getRootElements() {
+		return Collections.unmodifiableList(rootElements);
+	}
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/sax/filters/packageinfo b/bundleplugin/src/main/java/aQute/libg/sax/filters/packageinfo
new file mode 100644
index 0000000..a4f1546
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sax/filters/packageinfo
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/aQute/libg/sax/packageinfo b/bundleplugin/src/main/java/aQute/libg/sax/packageinfo
new file mode 100644
index 0000000..a4f1546
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sax/packageinfo
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file