Parser for structured metadata.

This commit is contained in:
akwizgran
2016-01-04 17:31:39 +00:00
parent 7be7ce8eda
commit a419948147
6 changed files with 281 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
package org.briarproject.api.data;
import java.util.Hashtable;
public class BdfDictionary extends Hashtable<String, Object> {
public Boolean getBoolean(String key, Boolean defaultValue) {
Object o = get(key);
if (o instanceof Boolean) return (Boolean) o;
return defaultValue;
}
public Long getInteger(String key, Long defaultValue) {
Object o = get(key);
if (o instanceof Long) return (Long) o;
return defaultValue;
}
public Double getFloat(String key, Double defaultValue) {
Object o = get(key);
if (o instanceof Double) return (Double) o;
return defaultValue;
}
public String getString(String key, String defaultValue) {
Object o = get(key);
if (o instanceof String) return (String) o;
return defaultValue;
}
public byte[] getRaw(String key, byte[] defaultValue) {
Object o = get(key);
if (o instanceof byte[]) return (byte[]) o;
return defaultValue;
}
public BdfList getList(String key, BdfList defaultValue) {
Object o = get(key);
if (o instanceof BdfList) return (BdfList) o;
return defaultValue;
}
public BdfDictionary getDictionary(String key, BdfDictionary defaultValue) {
Object o = get(key);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
return defaultValue;
}
}

View File

@@ -0,0 +1,48 @@
package org.briarproject.api.data;
import java.util.Vector;
public class BdfList extends Vector<Object> {
public Boolean getBoolean(int index, Boolean defaultValue) {
Object o = get(index);
if (o instanceof Boolean) return (Boolean) o;
return defaultValue;
}
public Long getInteger(int index, Long defaultValue) {
Object o = get(index);
if (o instanceof Long) return (Long) o;
return defaultValue;
}
public Double getFloat(int index, Double defaultValue) {
Object o = get(index);
if (o instanceof Double) return (Double) o;
return defaultValue;
}
public String getString(int index, String defaultValue) {
Object o = get(index);
if (o instanceof String) return (String) o;
return defaultValue;
}
public byte[] getRaw(int index, byte[] defaultValue) {
Object o = get(index);
if (o instanceof byte[]) return (byte[]) o;
return defaultValue;
}
public BdfList getList(int index, BdfList defaultValue) {
Object o = get(index);
if (o instanceof BdfList) return (BdfList) o;
return defaultValue;
}
public BdfDictionary getDictionary(int index, BdfDictionary defaultValue) {
Object o = get(index);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
return defaultValue;
}
}

View File

@@ -0,0 +1,9 @@
package org.briarproject.api.data;
import org.briarproject.api.FormatException;
import org.briarproject.api.db.Metadata;
public interface MetadataParser {
BdfDictionary parse(Metadata m) throws FormatException;
}

View File

@@ -0,0 +1,6 @@
package org.briarproject.api.db;
import java.util.Hashtable;
public class Metadata extends Hashtable<String, byte[]> {
}

View File

@@ -4,6 +4,7 @@ import com.google.inject.AbstractModule;
import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.data.MetadataParser;
public class DataModule extends AbstractModule {
@@ -11,5 +12,6 @@ public class DataModule extends AbstractModule {
protected void configure() {
bind(BdfReaderFactory.class).to(BdfReaderFactoryImpl.class);
bind(BdfWriterFactory.class).to(BdfWriterFactoryImpl.class);
bind(MetadataParser.class).to(MetadataParserImpl.class);
}
}

View File

@@ -0,0 +1,168 @@
package org.briarproject.data;
import org.briarproject.api.FormatException;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataParser;
import org.briarproject.api.db.Metadata;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import static org.briarproject.data.Types.DICTIONARY;
import static org.briarproject.data.Types.END;
import static org.briarproject.data.Types.FALSE;
import static org.briarproject.data.Types.FLOAT_64;
import static org.briarproject.data.Types.INT_16;
import static org.briarproject.data.Types.INT_32;
import static org.briarproject.data.Types.INT_64;
import static org.briarproject.data.Types.INT_8;
import static org.briarproject.data.Types.LIST;
import static org.briarproject.data.Types.NULL;
import static org.briarproject.data.Types.RAW_16;
import static org.briarproject.data.Types.RAW_32;
import static org.briarproject.data.Types.RAW_8;
import static org.briarproject.data.Types.STRING_16;
import static org.briarproject.data.Types.STRING_32;
import static org.briarproject.data.Types.STRING_8;
import static org.briarproject.data.Types.TRUE;
class MetadataParserImpl implements MetadataParser {
@Override
public BdfDictionary parse(Metadata m) throws FormatException {
BdfDictionary dict = new BdfDictionary();
for (Map.Entry<String, byte[]> e : m.entrySet())
dict.put(e.getKey(), parseObject(e.getValue()));
return dict;
}
private Object parseObject(byte[] b) throws FormatException {
if (b == null) return null;
ByteArrayInputStream in = new ByteArrayInputStream(b);
Object o = parseObject(in);
if (in.available() > 0) throw new FormatException();
return o;
}
private Object parseObject(ByteArrayInputStream in) throws FormatException {
switch(in.read()) {
case NULL:
return null;
case TRUE:
return Boolean.TRUE;
case FALSE:
return Boolean.FALSE;
case INT_8:
return (long) parseInt8(in);
case INT_16:
return (long) parseInt16(in);
case INT_32:
return (long) parseInt32(in);
case INT_64:
return parseInt64(in);
case FLOAT_64:
return Double.longBitsToDouble(parseInt64(in));
case STRING_8:
return parseString(in, parseInt8(in));
case STRING_16:
return parseString(in, parseInt16(in));
case STRING_32:
return parseString(in, parseInt32(in));
case RAW_8:
return parseRaw(in, parseInt8(in));
case RAW_16:
return parseRaw(in, parseInt16(in));
case RAW_32:
return parseRaw(in, parseInt32(in));
case LIST:
return parseList(in);
case DICTIONARY:
return parseDictionary(in);
default:
throw new FormatException();
}
}
private String parseString(ByteArrayInputStream in) throws FormatException {
switch(in.read()) {
case STRING_8:
return parseString(in, parseInt8(in));
case STRING_16:
return parseString(in, parseInt16(in));
case STRING_32:
return parseString(in, parseInt32(in));
default:
throw new FormatException();
}
}
private byte parseInt8(ByteArrayInputStream in) throws FormatException {
if (in.available() < 1) throw new FormatException();
return (byte) in.read();
}
private short parseInt16(ByteArrayInputStream in) throws FormatException {
if (in.available() < 2) throw new FormatException();
return (short) (((in.read() & 0xFF) << 8) + (in.read() & 0xFF));
}
private int parseInt32(ByteArrayInputStream in) throws FormatException {
if (in.available() < 4) throw new FormatException();
int value = 0;
for (int i = 0; i < 4; i++)
value |= (in.read() & 0xFF) << (24 - i * 8);
return value;
}
private long parseInt64(ByteArrayInputStream in) throws FormatException {
if (in.available() < 8) throw new FormatException();
long value = 0;
for (int i = 0; i < 8; i++)
value |= (in.read() & 0xFFL) << (56 - i * 8);
return value;
}
private String parseString(ByteArrayInputStream in, int len)
throws FormatException {
if (len < 0) throw new FormatException();
byte[] b = new byte[len];
if (in.read(b, 0, len) != len) throw new FormatException();
try {
return new String(b, 0, len, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException();
}
}
private byte[] parseRaw(ByteArrayInputStream in, int len)
throws FormatException {
if (len < 0) throw new FormatException();
byte[] b = new byte[len];
if (in.read(b, 0, len) != len) throw new FormatException();
return b;
}
private BdfList parseList(ByteArrayInputStream in) throws FormatException {
BdfList list = new BdfList();
while (peek(in) != END) list.add(parseObject(in));
if (in.read() != END) throw new FormatException();
return list;
}
private BdfDictionary parseDictionary(ByteArrayInputStream in)
throws FormatException {
BdfDictionary dict = new BdfDictionary();
while (peek(in) != END) dict.put(parseString(in), parseObject(in));
if (in.read() != END) throw new FormatException();
return dict;
}
private int peek(ByteArrayInputStream in) {
in.mark(1);
int next = in.read();
in.reset();
return next;
}
}