Use local copy of latest bndlib code for pre-release testing purposes

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1347815 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java b/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java
new file mode 100755
index 0000000..7b26f6f
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java
@@ -0,0 +1,138 @@
+package aQute.libg.header;
+
+import java.util.*;
+
+import aQute.libg.generics.*;
+import aQute.libg.qtokens.*;
+import aQute.libg.reporter.*;
+
+public class OSGiHeader {
+
+	static public Parameters parseHeader(String value) {
+		return parseHeader(value, null);
+	}
+
+	/**
+	 * Standard OSGi header parser. This parser can handle the format clauses
+	 * ::= clause ( ',' clause ) + clause ::= name ( ';' name ) (';' key '='
+	 * value )
+	 * 
+	 * This is mapped to a Map { name => Map { attr|directive => value } }
+	 * 
+	 * @param value
+	 *            A string
+	 * @return a Map<String,Map<String,String>>
+	 */
+	static public Parameters parseHeader(String value, Reporter logger) {
+		return parseHeader(value, logger, new Parameters());
+	}
+
+	static public Parameters parseHeader(String value, Reporter logger, Parameters result) {
+		if (value == null || value.trim().length() == 0)
+			return result;
+
+		QuotedTokenizer qt = new QuotedTokenizer(value, ";=,");
+		char del = 0;
+		do {
+			boolean hadAttribute = false;
+			Attrs clause = new Attrs();
+			List<String> aliases = Create.list();
+			String name = qt.nextToken(",;");
+
+			del = qt.getSeparator();
+			if (name == null || name.length() == 0) {
+				if (logger != null && logger.isPedantic()) {
+					logger.warning("Empty clause, usually caused by repeating a comma without any name field or by having spaces after the backslash of a property file: "
+							+ value);
+				}
+				if (name == null)
+					break;
+			} else {
+				name = name.trim();
+
+				aliases.add(name);
+				while (del == ';') {
+					String adname = qt.nextToken();
+					if ((del = qt.getSeparator()) != '=') {
+						if (hadAttribute)
+							if (logger != null) {
+								logger.error("Header contains name field after attribute or directive: "
+										+ adname
+										+ " from "
+										+ value
+										+ ". Name fields must be consecutive, separated by a ';' like a;b;c;x=3;y=4");
+							}
+						if (adname != null && adname.length() > 0)
+							aliases.add(adname.trim());
+					} else {
+						String advalue = qt.nextToken();
+						if (clause.containsKey(adname)) {
+							if (logger != null && logger.isPedantic())
+								logger.warning("Duplicate attribute/directive name " + adname
+										+ " in " + value
+										+ ". This attribute/directive will be ignored");
+						}
+						if (advalue == null) {
+							if (logger != null)
+								logger.error("No value after '=' sign for attribute " + adname);
+							advalue = "";
+						}
+						clause.put(adname.trim(), advalue.trim());
+						del = qt.getSeparator();
+						hadAttribute = true;
+					}
+				}
+
+				// Check for duplicate names. The aliases list contains
+				// the list of nams, for each check if it exists. If so,
+				// add a number of "~" to make it unique.
+				for (String clauseName : aliases) {
+					if (result.containsKey(clauseName)) {
+						if (logger != null && logger.isPedantic())
+							logger.warning("Duplicate name "
+									+ clauseName
+									+ " used in header: '"
+									+ clauseName
+									+ "'. Duplicate names are specially marked in Bnd with a ~ at the end (which is stripped at printing time).");
+						while (result.containsKey(clauseName))
+							clauseName += "~";
+					}
+					result.put(clauseName, clause);
+				}
+			}
+		} while (del == ',');
+		return result;
+	}
+
+	public static Attrs parseProperties(String input) {
+		return parseProperties(input, null);
+	}
+
+	public static Attrs parseProperties(String input, Reporter logger) {
+		if (input == null || input.trim().length() == 0)
+			return new Attrs();
+
+		Attrs result = new Attrs();
+		QuotedTokenizer qt = new QuotedTokenizer(input, "=,");
+		char del = ',';
+
+		while (del == ',') {
+			String key = qt.nextToken(",=");
+			String value = "";
+			del = qt.getSeparator();
+			if (del == '=') {
+				value = qt.nextToken(",=");
+				del = qt.getSeparator();
+			}
+			result.put(key, value);
+		}
+		if (del != 0) {
+			if (logger == null)
+				throw new IllegalArgumentException("Invalid syntax for properties: " + input);
+			logger.error("Invalid syntax for properties: " + input);
+		}
+
+		return result;
+	}
+
+}