Moved to own MsgPack implementation
This commit is contained in:
parent
3f8980e236
commit
10a45cc79c
@ -10,6 +10,7 @@ subprojects {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
@ -25,7 +25,7 @@ artifacts {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'org.slf4j:slf4j-api:1.7.12'
|
compile 'org.slf4j:slf4j-api:1.7.12'
|
||||||
compile 'org.msgpack:msgpack-core:0.8.11'
|
compile 'ch.dissem.msgpack:msgpack:development-SNAPSHOT'
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
testCompile 'org.hamcrest:hamcrest-library:1.3'
|
testCompile 'org.hamcrest:hamcrest-library:1.3'
|
||||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
testCompile 'org.mockito:mockito-core:1.10.19'
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package ch.dissem.bitmessage.entity.valueobject;
|
package ch.dissem.bitmessage.entity.valueobject;
|
||||||
|
|
||||||
import ch.dissem.bitmessage.exception.ApplicationException;
|
import ch.dissem.bitmessage.exception.ApplicationException;
|
||||||
import org.msgpack.core.MessagePack;
|
import ch.dissem.msgpack.types.MPMap;
|
||||||
import org.msgpack.core.MessagePacker;
|
import ch.dissem.msgpack.types.MPString;
|
||||||
import org.msgpack.core.MessageUnpacker;
|
import ch.dissem.msgpack.types.MPType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -39,13 +39,10 @@ public class ExtendedEncoding implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte[] zip() {
|
public byte[] zip() {
|
||||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream();
|
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||||
DeflaterOutputStream zipper = new DeflaterOutputStream(out)) {
|
try (DeflaterOutputStream zipper = new DeflaterOutputStream(out)) {
|
||||||
|
content.pack().pack(zipper);
|
||||||
MessagePacker packer = MessagePack.newDefaultPacker(zipper);
|
}
|
||||||
content.pack(packer);
|
|
||||||
packer.close();
|
|
||||||
zipper.close();
|
|
||||||
return out.toByteArray();
|
return out.toByteArray();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ApplicationException(e);
|
throw new ApplicationException(e);
|
||||||
@ -68,12 +65,12 @@ public class ExtendedEncoding implements Serializable {
|
|||||||
public interface Unpacker<T extends ExtendedType> {
|
public interface Unpacker<T extends ExtendedType> {
|
||||||
String getType();
|
String getType();
|
||||||
|
|
||||||
T unpack(MessageUnpacker unpacker, int size);
|
T unpack(MPMap<MPString, MPType<?>> map);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ExtendedType extends Serializable {
|
public interface ExtendedType extends Serializable {
|
||||||
String getType();
|
String getType();
|
||||||
|
|
||||||
void pack(MessagePacker packer) throws IOException;
|
MPMap<MPString, MPType<?>> pack() throws IOException;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,7 @@ package ch.dissem.bitmessage.entity.valueobject.extended;
|
|||||||
import ch.dissem.bitmessage.entity.Plaintext;
|
import ch.dissem.bitmessage.entity.Plaintext;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.ExtendedEncoding;
|
import ch.dissem.bitmessage.entity.valueobject.ExtendedEncoding;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||||
import org.msgpack.core.MessagePacker;
|
import ch.dissem.msgpack.types.*;
|
||||||
import org.msgpack.core.MessageUnpacker;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -15,6 +14,10 @@ import java.net.URLConnection;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static ch.dissem.bitmessage.entity.valueobject.extended.Attachment.Disposition.attachment;
|
||||||
|
import static ch.dissem.bitmessage.utils.Strings.str;
|
||||||
|
import static ch.dissem.msgpack.types.Utils.mp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended encoding type 'message'. Properties 'parents' and 'files' not yet supported by PyBitmessage, so they might not work
|
* Extended encoding type 'message'. Properties 'parents' and 'files' not yet supported by PyBitmessage, so they might not work
|
||||||
* properly with future PyBitmessage implementations.
|
* properly with future PyBitmessage implementations.
|
||||||
@ -74,45 +77,33 @@ public class Message implements ExtendedEncoding.ExtendedType {
|
|||||||
return Objects.hash(subject, body, parents, files);
|
return Objects.hash(subject, body, parents, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pack(MessagePacker packer) throws IOException {
|
@Override
|
||||||
int size = 3;
|
public MPMap<MPString, MPType<?>> pack() throws IOException {
|
||||||
|
MPMap<MPString, MPType<?>> result = new MPMap<>();
|
||||||
|
result.put(mp(""), mp(TYPE));
|
||||||
|
result.put(mp("subject"), mp(subject));
|
||||||
|
result.put(mp("body"), mp(body));
|
||||||
|
|
||||||
if (!files.isEmpty()) {
|
if (!files.isEmpty()) {
|
||||||
size++;
|
MPArray<MPMap<MPString, MPType<?>>> items = new MPArray<>();
|
||||||
}
|
result.put(mp("files"), items);
|
||||||
if (!parents.isEmpty()) {
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
packer.packMapHeader(size);
|
|
||||||
packer.packString("");
|
|
||||||
packer.packString(TYPE);
|
|
||||||
packer.packString("subject");
|
|
||||||
packer.packString(subject);
|
|
||||||
packer.packString("body");
|
|
||||||
packer.packString(body);
|
|
||||||
if (!files.isEmpty()) {
|
|
||||||
packer.packString("files");
|
|
||||||
packer.packArrayHeader(files.size());
|
|
||||||
for (Attachment file : files) {
|
for (Attachment file : files) {
|
||||||
packer.packMapHeader(4);
|
MPMap<MPString, MPType<?>> item = new MPMap<>();
|
||||||
packer.packString("name");
|
item.put(mp("name"), mp(file.getName()));
|
||||||
packer.packString(file.getName());
|
item.put(mp("data"), mp(file.getData()));
|
||||||
packer.packString("data");
|
item.put(mp("type"), mp(file.getType()));
|
||||||
packer.packBinaryHeader(file.getData().length);
|
item.put(mp("disposition"), mp(file.getDisposition().name()));
|
||||||
packer.writePayload(file.getData());
|
items.add(item);
|
||||||
packer.packString("type");
|
|
||||||
packer.packString(file.getType());
|
|
||||||
packer.packString("disposition");
|
|
||||||
packer.packString(file.getDisposition().name());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!parents.isEmpty()) {
|
if (!parents.isEmpty()) {
|
||||||
packer.packString("parents");
|
MPArray<MPBinary> items = new MPArray<>();
|
||||||
packer.packArrayHeader(parents.size());
|
result.put(mp("parents"), items);
|
||||||
for (InventoryVector parent : parents) {
|
for (InventoryVector parent : parents) {
|
||||||
packer.packBinaryHeader(parent.getHash().length);
|
items.add(mp(parent.getHash()));
|
||||||
packer.writePayload(parent.getHash());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
@ -185,86 +176,44 @@ public class Message implements ExtendedEncoding.ExtendedType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message unpack(MessageUnpacker unpacker, int size) {
|
public Message unpack(MPMap<MPString, MPType<?>> map) {
|
||||||
Message.Builder builder = new Message.Builder();
|
Message.Builder builder = new Message.Builder();
|
||||||
try {
|
builder.subject(str(map.get(mp("subject"))));
|
||||||
for (int i = 0; i < size; i++) {
|
builder.body(str(map.get(mp("body"))));
|
||||||
String key = unpacker.unpackString();
|
@SuppressWarnings("unchecked")
|
||||||
switch (key) {
|
MPArray<MPBinary> parents = (MPArray<MPBinary>) map.get(mp("parents"));
|
||||||
case "subject":
|
if (parents != null) {
|
||||||
builder.subject(unpacker.unpackString());
|
for (MPBinary parent : parents) {
|
||||||
break;
|
builder.addParent(new InventoryVector(parent.getValue()));
|
||||||
case "body":
|
|
||||||
builder.body(unpacker.unpackString());
|
|
||||||
break;
|
|
||||||
case "parents":
|
|
||||||
builder.parents = unpackParents(unpacker);
|
|
||||||
break;
|
|
||||||
case "files":
|
|
||||||
builder.files = unpackFiles(unpacker);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.error("Unexpected data with key: " + key);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
@SuppressWarnings("unchecked")
|
||||||
LOG.error(e.getMessage(), e);
|
MPArray<MPMap<MPString, MPType<?>>> files = (MPArray<MPMap<MPString, MPType<?>>>) map.get(mp("files"));
|
||||||
|
if (files != null) {
|
||||||
|
for (MPMap<MPString, MPType<?>> item : files) {
|
||||||
|
Attachment.Builder b = new Attachment.Builder();
|
||||||
|
b.name(str(item.get(mp("name"))));
|
||||||
|
b.data(bin(item.get(mp("data"))));
|
||||||
|
b.type(str(item.get(mp("type"))));
|
||||||
|
String disposition = str(item.get(mp("disposition")));
|
||||||
|
if ("inline".equals(disposition)) {
|
||||||
|
b.inline();
|
||||||
|
} else if ("attachment".equals(disposition)) {
|
||||||
|
b.attachment();
|
||||||
}
|
}
|
||||||
|
builder.addFile(b.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new Message(builder);
|
return new Message(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<InventoryVector> unpackParents(MessageUnpacker unpacker) throws IOException {
|
private byte[] bin(MPType data) {
|
||||||
int size = unpacker.unpackArrayHeader();
|
if (data instanceof MPBinary) {
|
||||||
List<InventoryVector> parents = new ArrayList<>(size);
|
return ((MPBinary) data).getValue();
|
||||||
for (int i = 0; i < size; i++) {
|
} else {
|
||||||
int binarySize = unpacker.unpackBinaryHeader();
|
return null;
|
||||||
parents.add(new InventoryVector(unpacker.readPayload(binarySize)));
|
|
||||||
}
|
}
|
||||||
return parents;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Attachment> unpackFiles(MessageUnpacker unpacker) throws IOException {
|
|
||||||
int size = unpacker.unpackArrayHeader();
|
|
||||||
List<Attachment> files = new ArrayList<>(size);
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
Attachment.Builder attachment = new Attachment.Builder();
|
|
||||||
int mapSize = unpacker.unpackMapHeader();
|
|
||||||
for (int j = 0; j < mapSize; j++) {
|
|
||||||
String key = unpacker.unpackString();
|
|
||||||
switch (key) {
|
|
||||||
case "name":
|
|
||||||
attachment.name(unpacker.unpackString());
|
|
||||||
break;
|
|
||||||
case "data":
|
|
||||||
int binarySize = unpacker.unpackBinaryHeader();
|
|
||||||
attachment.data(unpacker.readPayload(binarySize));
|
|
||||||
break;
|
|
||||||
case "type":
|
|
||||||
attachment.type(unpacker.unpackString());
|
|
||||||
break;
|
|
||||||
case "disposition":
|
|
||||||
String disposition = unpacker.unpackString();
|
|
||||||
switch (disposition) {
|
|
||||||
case "inline":
|
|
||||||
attachment.inline();
|
|
||||||
break;
|
|
||||||
case "attachment":
|
|
||||||
attachment.attachment();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.debug("Unknown disposition: " + disposition);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.debug("Unknown file info '" + key + "' with data: " + unpacker.unpackValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
files.add(attachment.build());
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,19 @@ package ch.dissem.bitmessage.entity.valueobject.extended;
|
|||||||
import ch.dissem.bitmessage.entity.Plaintext;
|
import ch.dissem.bitmessage.entity.Plaintext;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.ExtendedEncoding;
|
import ch.dissem.bitmessage.entity.valueobject.ExtendedEncoding;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||||
import org.msgpack.core.MessagePacker;
|
import ch.dissem.msgpack.types.*;
|
||||||
import org.msgpack.core.MessageUnpacker;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static ch.dissem.bitmessage.utils.Strings.str;
|
||||||
|
import static ch.dissem.msgpack.types.Utils.mp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended encoding type 'vote'. Specification still outstanding, so this will need some work.
|
* Extended encoding type 'vote'. Specification still outstanding, so this will need some work.
|
||||||
*/
|
*/
|
||||||
public class Vote implements ExtendedEncoding.ExtendedType {
|
public class Vote implements ExtendedEncoding.ExtendedType {
|
||||||
private static final long serialVersionUID = -8427038604209964837L;
|
private static final long serialVersionUID = -8427038604209964837L;
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Vote.class);
|
|
||||||
|
|
||||||
public static final String TYPE = "vote";
|
public static final String TYPE = "vote";
|
||||||
|
|
||||||
@ -55,15 +54,13 @@ public class Vote implements ExtendedEncoding.ExtendedType {
|
|||||||
return Objects.hash(msgId, vote);
|
return Objects.hash(msgId, vote);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pack(MessagePacker packer) throws IOException {
|
@Override
|
||||||
packer.packMapHeader(3);
|
public MPMap<MPString, MPType<?>> pack() throws IOException {
|
||||||
packer.packString("");
|
MPMap<MPString, MPType<?>> result = new MPMap<>();
|
||||||
packer.packString(TYPE);
|
result.put(mp(""), mp(TYPE));
|
||||||
packer.packString("msgId");
|
result.put(mp("msgId"), mp(msgId.getHash()));
|
||||||
packer.packBinaryHeader(msgId.getHash().length);
|
result.put(mp("vote"), mp(vote));
|
||||||
packer.writePayload(msgId.getHash());
|
return result;
|
||||||
packer.packString("vote");
|
|
||||||
packer.packString(vote);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
@ -104,27 +101,13 @@ public class Vote implements ExtendedEncoding.ExtendedType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vote unpack(MessageUnpacker unpacker, int size) {
|
public Vote unpack(MPMap<MPString, MPType<?>> map) {
|
||||||
Vote.Builder builder = new Vote.Builder();
|
Vote.Builder builder = new Vote.Builder();
|
||||||
try {
|
MPType<?> msgId = map.get(mp("msgId"));
|
||||||
for (int i = 0; i < size; i++) {
|
if (msgId instanceof MPBinary) {
|
||||||
String key = unpacker.unpackString();
|
builder.msgId(new InventoryVector(((MPBinary) msgId).getValue()));
|
||||||
switch (key) {
|
|
||||||
case "msgId":
|
|
||||||
int binarySize = unpacker.unpackBinaryHeader();
|
|
||||||
builder.msgId(new InventoryVector(unpacker.readPayload(binarySize)));
|
|
||||||
break;
|
|
||||||
case "vote":
|
|
||||||
builder.vote(unpacker.unpackString());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.error("Unexpected data with key: " + key);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.error(e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
builder.vote(str(map.get(mp("vote"))));
|
||||||
return new Vote(builder);
|
return new Vote(builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@ import ch.dissem.bitmessage.entity.valueobject.ExtendedEncoding;
|
|||||||
import ch.dissem.bitmessage.entity.valueobject.extended.Message;
|
import ch.dissem.bitmessage.entity.valueobject.extended.Message;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.extended.Vote;
|
import ch.dissem.bitmessage.entity.valueobject.extended.Vote;
|
||||||
import ch.dissem.bitmessage.exception.ApplicationException;
|
import ch.dissem.bitmessage.exception.ApplicationException;
|
||||||
import org.msgpack.core.MessagePack;
|
import ch.dissem.msgpack.Reader;
|
||||||
import org.msgpack.core.MessageUnpacker;
|
import ch.dissem.msgpack.types.MPMap;
|
||||||
|
import ch.dissem.msgpack.types.MPString;
|
||||||
|
import ch.dissem.msgpack.types.MPType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -15,6 +17,8 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.zip.InflaterInputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
|
|
||||||
|
import static ch.dissem.bitmessage.utils.Strings.str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory that creates {@link ExtendedEncoding} objects from byte arrays. You can register your own types by adding a
|
* Factory that creates {@link ExtendedEncoding} objects from byte arrays. You can register your own types by adding a
|
||||||
* {@link ExtendedEncoding.Unpacker} using {@link #registerFactory(ExtendedEncoding.Unpacker)}.
|
* {@link ExtendedEncoding.Unpacker} using {@link #registerFactory(ExtendedEncoding.Unpacker)}.
|
||||||
@ -22,7 +26,7 @@ import java.util.zip.InflaterInputStream;
|
|||||||
public class ExtendedEncodingFactory {
|
public class ExtendedEncodingFactory {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ExtendedEncodingFactory.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ExtendedEncodingFactory.class);
|
||||||
private static final ExtendedEncodingFactory INSTANCE = new ExtendedEncodingFactory();
|
private static final ExtendedEncodingFactory INSTANCE = new ExtendedEncodingFactory();
|
||||||
private static final String KEY_MESSAGE_TYPE = "";
|
private static final MPString KEY_MESSAGE_TYPE = new MPString("");
|
||||||
private Map<String, ExtendedEncoding.Unpacker<?>> factories = new HashMap<>();
|
private Map<String, ExtendedEncoding.Unpacker<?>> factories = new HashMap<>();
|
||||||
|
|
||||||
private ExtendedEncodingFactory() {
|
private ExtendedEncodingFactory() {
|
||||||
@ -37,17 +41,17 @@ public class ExtendedEncodingFactory {
|
|||||||
|
|
||||||
public ExtendedEncoding unzip(byte[] zippedData) {
|
public ExtendedEncoding unzip(byte[] zippedData) {
|
||||||
try (InflaterInputStream unzipper = new InflaterInputStream(new ByteArrayInputStream(zippedData))) {
|
try (InflaterInputStream unzipper = new InflaterInputStream(new ByteArrayInputStream(zippedData))) {
|
||||||
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(unzipper);
|
Reader reader = Reader.getInstance();
|
||||||
int mapSize = unpacker.unpackMapHeader();
|
@SuppressWarnings("unchecked")
|
||||||
String key = unpacker.unpackString();
|
MPMap<MPString, MPType<?>> map = (MPMap<MPString, MPType<?>>) reader.read(unzipper);
|
||||||
if (!KEY_MESSAGE_TYPE.equals(key)) {
|
MPType<?> messageType = map.get(KEY_MESSAGE_TYPE);
|
||||||
LOG.error("Unexpected content: " + key);
|
if (messageType == null) {
|
||||||
|
LOG.error("Missing message type");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String type = unpacker.unpackString();
|
ExtendedEncoding.Unpacker<?> factory = factories.get(str(messageType));
|
||||||
ExtendedEncoding.Unpacker<?> factory = factories.get(type);
|
return new ExtendedEncoding(factory.unpack(map));
|
||||||
return new ExtendedEncoding(factory.unpack(unpacker, mapSize - 1));
|
} catch (ClassCastException | IOException e) {
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ApplicationException(e);
|
throw new ApplicationException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,4 +37,8 @@ public class Strings {
|
|||||||
}
|
}
|
||||||
return hex;
|
return hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String str(Object o) {
|
||||||
|
return o == null ? null : o.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,22 +21,26 @@ import ch.dissem.bitmessage.entity.BitmessageAddress;
|
|||||||
import ch.dissem.bitmessage.entity.Plaintext;
|
import ch.dissem.bitmessage.entity.Plaintext;
|
||||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
||||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||||
|
import ch.dissem.bitmessage.entity.valueobject.extended.Message;
|
||||||
import org.apache.commons.lang3.text.WordUtils;
|
import org.apache.commons.lang3.text.WordUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static ch.dissem.bitmessage.demo.CommandLine.COMMAND_BACK;
|
import static ch.dissem.bitmessage.demo.CommandLine.COMMAND_BACK;
|
||||||
import static ch.dissem.bitmessage.demo.CommandLine.ERROR_UNKNOWN_COMMAND;
|
import static ch.dissem.bitmessage.demo.CommandLine.ERROR_UNKNOWN_COMMAND;
|
||||||
|
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple command line Bitmessage application
|
* A simple command line Bitmessage application
|
||||||
*/
|
*/
|
||||||
public class Application {
|
public class Application {
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(Application.class);
|
private final static Logger LOG = LoggerFactory.getLogger(Application.class);
|
||||||
|
private final static Pattern RESPONSE_PATTERN = Pattern.compile("^RE:.*$", CASE_INSENSITIVE);
|
||||||
private final CommandLine commandLine;
|
private final CommandLine commandLine;
|
||||||
|
|
||||||
private BitmessageContext ctx;
|
private BitmessageContext ctx;
|
||||||
@ -342,7 +346,7 @@ public class Application {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("c) compose message");
|
System.out.println("c) compose message");
|
||||||
System.out.println("s) compose broadcast");
|
System.out.println("s) compose broadcast");
|
||||||
if (label.getType() == Label.Type.TRASH) {
|
if (label != null && label.getType() == Label.Type.TRASH) {
|
||||||
System.out.println("e) empty trash");
|
System.out.println("e) empty trash");
|
||||||
}
|
}
|
||||||
System.out.println(COMMAND_BACK);
|
System.out.println(COMMAND_BACK);
|
||||||
@ -392,7 +396,7 @@ public class Application {
|
|||||||
command = commandLine.nextCommand();
|
command = commandLine.nextCommand();
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "r":
|
case "r":
|
||||||
compose(message.getTo(), message.getFrom(), "RE: " + message.getSubject());
|
compose(message.getTo(), message.getFrom(), message);
|
||||||
break;
|
break;
|
||||||
case "d":
|
case "d":
|
||||||
ctx.labeler().delete(message);
|
ctx.labeler().delete(message);
|
||||||
@ -442,14 +446,20 @@ public class Application {
|
|||||||
return commandLine.selectAddress(addresses, "To:");
|
return commandLine.selectAddress(addresses, "To:");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void compose(BitmessageAddress from, BitmessageAddress to, String subject) {
|
private void compose(BitmessageAddress from, BitmessageAddress to, Plaintext parent) {
|
||||||
boolean broadcast = (to == null);
|
boolean broadcast = (to == null);
|
||||||
|
String subject;
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("From: " + from);
|
System.out.println("From: " + from);
|
||||||
if (!broadcast) {
|
if (!broadcast) {
|
||||||
System.out.println("To: " + to);
|
System.out.println("To: " + to);
|
||||||
}
|
}
|
||||||
if (subject != null) {
|
if (parent != null) {
|
||||||
|
if (RESPONSE_PATTERN.matcher(parent.getSubject()).matches()) {
|
||||||
|
subject = parent.getSubject();
|
||||||
|
} else {
|
||||||
|
subject = "RE: " + parent.getSubject();
|
||||||
|
}
|
||||||
System.out.println("Subject: " + subject);
|
System.out.println("Subject: " + subject);
|
||||||
} else {
|
} else {
|
||||||
System.out.print("Subject: ");
|
System.out.print("Subject: ");
|
||||||
@ -462,10 +472,20 @@ public class Application {
|
|||||||
line = commandLine.nextLine();
|
line = commandLine.nextLine();
|
||||||
message.append(line).append('\n');
|
message.append(line).append('\n');
|
||||||
} while (line.length() > 0 || !commandLine.yesNo("Send message?"));
|
} while (line.length() > 0 || !commandLine.yesNo("Send message?"));
|
||||||
if (broadcast) {
|
Plaintext.Type type = broadcast ? Plaintext.Type.BROADCAST : Plaintext.Type.MSG;
|
||||||
ctx.broadcast(from, subject, message.toString());
|
Plaintext.Builder builder = new Plaintext.Builder(type);
|
||||||
} else {
|
builder.from(from);
|
||||||
ctx.send(from, to, subject, message.toString());
|
builder.to(to);
|
||||||
|
if (commandLine.yesNo("Use extended encoding?")) {
|
||||||
|
Message.Builder extended = new Message.Builder();
|
||||||
|
extended.subject(subject).body(message.toString());
|
||||||
|
if (parent != null) {
|
||||||
|
extended.addParent(parent);
|
||||||
}
|
}
|
||||||
|
builder.message(extended.build());
|
||||||
|
} else {
|
||||||
|
builder.message(subject, message.toString());
|
||||||
|
}
|
||||||
|
ctx.send(builder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user