aQute.bnd.header.OSGiHeader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bndlib Show documentation
Show all versions of bndlib Show documentation
The bndlib project is a general library to be used with OSGi bundles. It contains
lots of cool functionality that calculates dependencies, etc.
package aQute.bnd.header;
import java.util.*;
import aQute.libg.generics.*;
import aQute.libg.qtokens.*;
import aQute.service.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>
*/
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 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;
}
}