diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 22aa80cae..642d980d4 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -36,6 +36,9 @@
+
+
+
@@ -258,14 +261,10 @@
-
-
-
-
-
+
-
+
\ No newline at end of file
diff --git a/briar-headless/build.gradle b/briar-headless/build.gradle
index c6fbc5e6c..b615fb419 100644
--- a/briar-headless/build.gradle
+++ b/briar-headless/build.gradle
@@ -14,11 +14,12 @@ dependencies {
implementation project(path: ':briar-core', configuration: 'default')
implementation project(path: ':bramble-java', configuration: 'default')
- implementation 'io.javalin:javalin:1.7.0'
+ implementation 'io.javalin:javalin:2.1.0'
implementation 'org.slf4j:slf4j-simple:1.7.25'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.6'
apt 'com.google.dagger:dagger-compiler:2.0.2'
+ kapt 'com.google.dagger:dagger-compiler:2.0.2'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
diff --git a/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.java b/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.java
deleted file mode 100644
index d093398b9..000000000
--- a/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.briarproject.bramble.identity;
-
-import org.briarproject.bramble.api.identity.Author;
-import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-@NotNullByDefault
-@SuppressWarnings("WeakerAccess")
-public class OutputAuthor {
-
- public final byte[] id;
- public final String name;
- public final byte[] publicKey;
-
- public OutputAuthor(Author author) {
- this.id = author.getId().getBytes();
- this.name = author.getName();
- this.publicKey = author.getPublicKey();
- }
-
-}
diff --git a/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.kt b/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.kt
new file mode 100644
index 000000000..020de0fdd
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.kt
@@ -0,0 +1,14 @@
+package org.briarproject.bramble.identity
+
+import org.briarproject.bramble.api.identity.Author
+import javax.annotation.concurrent.Immutable
+
+@Immutable
+@Suppress("unused")
+class OutputAuthor(author: Author) {
+
+ val id: ByteArray = author.id.bytes
+ val name: String = author.name
+ val publicKey: ByteArray = author.publicKey
+
+}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/Extensions.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/Extensions.kt
new file mode 100644
index 000000000..9aa992271
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Extensions.kt
@@ -0,0 +1,12 @@
+package org.briarproject.briar.headless
+
+import org.briarproject.bramble.api.identity.Author
+import org.briarproject.bramble.identity.OutputAuthor
+import org.briarproject.briar.api.blog.MessageType
+
+fun Author.output() = OutputAuthor(this)
+
+fun Author.Status.output() = name.toLowerCase()
+
+fun MessageType.output() = name.toLowerCase()
+
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java
deleted file mode 100644
index ff65063f1..000000000
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.briarproject.briar.headless;
-
-import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.briar.headless.blogs.BlogController;
-import org.briarproject.briar.headless.contact.ContactController;
-import org.briarproject.briar.headless.forums.ForumController;
-import org.briarproject.briar.headless.messaging.MessagingController;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import io.javalin.Javalin;
-
-import static io.javalin.ApiBuilder.get;
-import static io.javalin.ApiBuilder.path;
-import static io.javalin.ApiBuilder.post;
-import static io.javalin.event.EventType.SERVER_START_FAILED;
-import static io.javalin.event.EventType.SERVER_STOPPED;
-import static java.lang.Runtime.getRuntime;
-
-@Immutable
-@Singleton
-@MethodsNotNullByDefault
-@ParametersAreNonnullByDefault
-public class Router {
-
- private final BriarService briarService;
- private final ContactController contactController;
- private final MessagingController messagingController;
- private final ForumController forumController;
- private final BlogController blogController;
-
- @Inject
- public Router(BriarService briarService,
- ContactController contactController,
- MessagingController messagingController,
- ForumController forumController,
- BlogController blogController) {
- this.briarService = briarService;
- this.contactController = contactController;
- this.messagingController = messagingController;
- this.forumController = forumController;
- this.blogController = blogController;
- }
-
- public void start() {
- briarService.start();
- getRuntime().addShutdownHook(new Thread(briarService::stop));
-
- Javalin app = Javalin.create()
- .port(7000)
- .disableStartupBanner()
- .enableStandardRequestLogging()
- .enableRouteOverview("/")
- .enableDynamicGzip()
- .event(SERVER_START_FAILED, event -> briarService.stop())
- .event(SERVER_STOPPED, event -> briarService.stop())
- .start();
-
- app.routes(() -> {
- path("/contacts", () -> get(contactController::list));
- path("/messages/:contactId", () -> {
- get(messagingController::list);
- post(messagingController::write);
- });
- path("/forums", () -> {
- get(forumController::list);
- post(forumController::create);
- });
- path("/blogs", () -> path("/posts", () -> {
- get(blogController::listPosts);
- post(blogController::createPost);
- }));
- });
- }
-
-}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt
new file mode 100644
index 000000000..de23453c2
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt
@@ -0,0 +1,68 @@
+package org.briarproject.briar.headless
+
+import io.javalin.Javalin
+import io.javalin.JavalinEvent.SERVER_START_FAILED
+import io.javalin.JavalinEvent.SERVER_STOPPED
+import io.javalin.apibuilder.ApiBuilder.*
+import org.briarproject.briar.headless.blogs.BlogController
+import org.briarproject.briar.headless.contact.ContactController
+import org.briarproject.briar.headless.forums.ForumController
+import org.briarproject.briar.headless.messaging.MessagingController
+import java.lang.Runtime.getRuntime
+import javax.annotation.concurrent.Immutable
+import javax.inject.Inject
+import javax.inject.Singleton
+import kotlin.system.exitProcess
+
+@Immutable
+@Singleton
+class Router @Inject
+constructor(
+ private val briarService: BriarService,
+ private val contactController: ContactController,
+ private val messagingController: MessagingController,
+ private val forumController: ForumController,
+ private val blogController: BlogController
+) {
+
+ fun start() {
+ briarService.start()
+ getRuntime().addShutdownHook(Thread(Runnable { briarService.stop() }))
+
+ val app = Javalin.create()
+ .port(7000)
+ .disableStartupBanner()
+ .enableDebugLogging()
+ .enableCaseSensitiveUrls()
+ .enableRouteOverview("/")
+ .event(SERVER_START_FAILED) { stop() }
+ .event(SERVER_STOPPED) { stop() }
+ .start()
+
+ app.routes {
+ path("/contacts") {
+ get { ctx -> contactController.list(ctx) }
+ }
+ path("/messages/:contactId") {
+ get { ctx -> messagingController.list(ctx) }
+ post { ctx -> messagingController.write(ctx) }
+ }
+ path("/forums") {
+ get { ctx -> forumController.list(ctx) }
+ post { ctx -> forumController.create(ctx) }
+ }
+ path("/blogs") {
+ path("/posts") {
+ get { ctx -> blogController.listPosts(ctx) }
+ post { ctx -> blogController.createPost(ctx) }
+ }
+ }
+ }
+ }
+
+ private fun stop() {
+ briarService.stop()
+ exitProcess(1)
+ }
+
+}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.java b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.java
deleted file mode 100644
index 358e0f6b1..000000000
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.briarproject.briar.headless.blogs;
-
-import org.briarproject.bramble.api.FormatException;
-import org.briarproject.bramble.api.db.DbException;
-import org.briarproject.bramble.api.identity.IdentityManager;
-import org.briarproject.bramble.api.identity.LocalAuthor;
-import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.bramble.api.system.Clock;
-import org.briarproject.briar.api.blog.Blog;
-import org.briarproject.briar.api.blog.BlogManager;
-import org.briarproject.briar.api.blog.BlogPost;
-import org.briarproject.briar.api.blog.BlogPostFactory;
-import org.briarproject.briar.api.blog.BlogPostHeader;
-
-import java.security.GeneralSecurityException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import io.javalin.Context;
-
-@Immutable
-@Singleton
-@MethodsNotNullByDefault
-@ParametersAreNonnullByDefault
-public class BlogController {
-
- private final BlogManager blogManager;
- private final BlogPostFactory blogPostFactory;
- private final IdentityManager identityManager;
- private final Clock clock;
-
- @Inject
- public BlogController(BlogManager blogManager,
- BlogPostFactory blogPostFactory, IdentityManager identityManager,
- Clock clock) {
- this.blogManager = blogManager;
- this.blogPostFactory = blogPostFactory;
- this.identityManager = identityManager;
- this.clock = clock;
- }
-
- public Context listPosts(Context ctx) throws DbException {
- List posts = new ArrayList<>();
- for (Blog b : blogManager.getBlogs()) {
- Collection headers =
- blogManager.getPostHeaders(b.getId());
- for (BlogPostHeader header : headers) {
- String body = blogManager.getPostBody(header.getId());
- OutputBlogPost post = new OutputBlogPost(header, body);
- posts.add(post);
- }
- }
- return ctx.json(posts);
- }
-
- public Context createPost(Context ctx)
- throws DbException, GeneralSecurityException, FormatException {
- String text = ctx.formParam("text");
- if (text == null || text.length() < 1) {
- return ctx.status(500).result("Expecting Blog text");
- } else {
- LocalAuthor author = identityManager.getLocalAuthor();
- Blog blog = blogManager.getPersonalBlog(author);
- long now = clock.currentTimeMillis();
- BlogPost post = blogPostFactory
- .createBlogPost(blog.getId(), now, null, author, text);
- blogManager.addLocalPost(post);
- BlogPostHeader header = blogManager
- .getPostHeader(blog.getId(), post.getMessage().getId());
- OutputBlogPost outputPost = new OutputBlogPost(header, text);
- return ctx.json(outputPost);
- }
- }
-
-}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.kt
new file mode 100644
index 000000000..4b8ccb144
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.kt
@@ -0,0 +1,47 @@
+package org.briarproject.briar.headless.blogs
+
+import io.javalin.BadRequestResponse
+import io.javalin.Context
+import org.briarproject.bramble.api.identity.IdentityManager
+import org.briarproject.bramble.api.system.Clock
+import org.briarproject.briar.api.blog.BlogManager
+import org.briarproject.briar.api.blog.BlogPostFactory
+import javax.annotation.concurrent.Immutable
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Immutable
+@Singleton
+class BlogController @Inject
+constructor(
+ private val blogManager: BlogManager,
+ private val blogPostFactory: BlogPostFactory,
+ private val identityManager: IdentityManager,
+ private val clock: Clock
+) {
+
+ fun listPosts(ctx: Context): Context {
+ val posts = blogManager.blogs.flatMap { blog ->
+ blogManager.getPostHeaders(blog.id).map { header ->
+ val body = blogManager.getPostBody(header.id)
+ header.output(body)
+ }
+ }
+ return ctx.json(posts)
+ }
+
+ fun createPost(ctx: Context): Context {
+ val text = ctx.formParam("text")
+ if (text == null || text.isEmpty())
+ throw BadRequestResponse("Expecting Blog text")
+
+ val author = identityManager.localAuthor
+ val blog = blogManager.getPersonalBlog(author)
+ val now = clock.currentTimeMillis()
+ val post = blogPostFactory.createBlogPost(blog.id, now, null, author, text)
+ blogManager.addLocalPost(post)
+ val header = blogManager.getPostHeader(blog.id, post.message.id)
+ return ctx.json(header.output(text))
+ }
+
+}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/Extensions.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/Extensions.kt
new file mode 100644
index 000000000..eccf60201
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/Extensions.kt
@@ -0,0 +1,5 @@
+package org.briarproject.briar.headless.blogs
+
+import org.briarproject.briar.api.blog.BlogPostHeader
+
+internal fun BlogPostHeader.output(body: String) = OutputBlogPost(this, body)
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.java b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.java
deleted file mode 100644
index f1dd2a8a9..000000000
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.briarproject.briar.headless.blogs;
-
-import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.identity.OutputAuthor;
-import org.briarproject.briar.api.blog.BlogPostHeader;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-@NotNullByDefault
-@SuppressWarnings("WeakerAccess")
-class OutputBlogPost {
-
- public final String body;
- public final OutputAuthor author;
- public final String authorStatus, type;
- public final byte[] id;
- @Nullable
- public final byte[] parentId;
- public final boolean read, rssFeed;
- public final long timestamp, timestampReceived;
-
- OutputBlogPost(BlogPostHeader header, String body) {
- this.body = body;
- this.author = new OutputAuthor(header.getAuthor());
- this.authorStatus = header.getAuthorStatus().name().toLowerCase();
- this.type = header.getType().name().toLowerCase();
- this.id = header.getId().getBytes();
- this.parentId = header.getParentId() == null ? null :
- header.getParentId().getBytes();
- this.read = header.isRead();
- this.rssFeed = header.isRssFeed();
- this.timestamp = header.getTimestamp();
- this.timestampReceived = header.getTimeReceived();
- }
-
-}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.kt
new file mode 100644
index 000000000..433e52128
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.kt
@@ -0,0 +1,22 @@
+package org.briarproject.briar.headless.blogs
+
+import org.briarproject.bramble.identity.OutputAuthor
+import org.briarproject.briar.api.blog.BlogPostHeader
+import org.briarproject.briar.headless.output
+import javax.annotation.concurrent.Immutable
+
+@Immutable
+@Suppress("unused")
+internal class OutputBlogPost(header: BlogPostHeader, val body: String) {
+
+ val author: OutputAuthor = OutputAuthor(header.author)
+ val authorStatus: String = header.authorStatus.output()
+ val type = header.type.output()
+ val id: ByteArray = header.id.bytes
+ val parentId = header.parentId?.bytes
+ val read = header.isRead
+ val rssFeed = header.isRssFeed
+ val timestamp = header.timestamp
+ val timestampReceived = header.timeReceived
+
+}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.java b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.java
deleted file mode 100644
index 8c2be33ea..000000000
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.briarproject.briar.headless.contact;
-
-import org.briarproject.bramble.api.contact.Contact;
-import org.briarproject.bramble.api.contact.ContactManager;
-import org.briarproject.bramble.api.db.DbException;
-import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import io.javalin.Context;
-
-@Immutable
-@Singleton
-@NotNullByDefault
-public class ContactController {
-
- private final ContactManager contactManager;
-
- @Inject
- public ContactController(ContactManager contactManager) {
- this.contactManager = contactManager;
- }
-
- public Context list(Context ctx) throws DbException {
- Collection contacts = contactManager.getActiveContacts();
- List outputContacts = new ArrayList<>(contacts.size());
- for (Contact c : contacts) {
- outputContacts.add(new OutputContact(c));
- }
- return ctx.json(outputContacts);
- }
-
-}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.kt
new file mode 100644
index 000000000..1de72d5c9
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.kt
@@ -0,0 +1,21 @@
+package org.briarproject.briar.headless.contact
+
+import io.javalin.Context
+import org.briarproject.bramble.api.contact.ContactManager
+import javax.annotation.concurrent.Immutable
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Immutable
+@Singleton
+class ContactController @Inject
+constructor(private val contactManager: ContactManager) {
+
+ fun list(ctx: Context): Context {
+ val contacts = contactManager.activeContacts.map { contact ->
+ contact.output()
+ }
+ return ctx.json(contacts)
+ }
+
+}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/Extensions.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/Extensions.kt
new file mode 100644
index 000000000..ed90d3c04
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/Extensions.kt
@@ -0,0 +1,5 @@
+package org.briarproject.briar.headless.contact
+
+import org.briarproject.bramble.api.contact.Contact
+
+internal fun Contact.output() = OutputContact(this)
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.java b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.java
deleted file mode 100644
index b5a026a0f..000000000
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.briarproject.briar.headless.contact;
-
-import org.briarproject.bramble.api.contact.Contact;
-import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.identity.OutputAuthor;
-
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-@NotNullByDefault
-@SuppressWarnings("WeakerAccess")
-public class OutputContact {
-
- public final int id;
- public final OutputAuthor author;
- public final boolean verified;
-
- public OutputContact(Contact c) {
- this.id = c.getId().getInt();
- this.author = new OutputAuthor(c.getAuthor());
- this.verified = c.isVerified();
- }
-
-}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.kt
new file mode 100644
index 000000000..6c3662297
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.kt
@@ -0,0 +1,15 @@
+package org.briarproject.briar.headless.contact
+
+import org.briarproject.bramble.api.contact.Contact
+import org.briarproject.briar.headless.output
+import javax.annotation.concurrent.Immutable
+
+@Immutable
+@Suppress("unused")
+internal class OutputContact(c: Contact) {
+
+ val id = c.id.int
+ val author = c.author.output()
+ val verified = c.isVerified
+
+}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/Extensions.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/Extensions.kt
new file mode 100644
index 000000000..6c1d38cfa
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/Extensions.kt
@@ -0,0 +1,7 @@
+package org.briarproject.briar.headless.forums
+
+import org.briarproject.briar.api.forum.Forum
+
+internal fun Forum.output() = OutputForum(this)
+
+internal fun Collection.output() = map { it.output() }
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.java b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.java
deleted file mode 100644
index 483b98d02..000000000
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.briarproject.briar.headless.forums;
-
-import org.briarproject.bramble.api.db.DbException;
-import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
-import org.briarproject.briar.api.forum.Forum;
-import org.briarproject.briar.api.forum.ForumManager;
-
-import java.util.Collection;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import io.javalin.Context;
-
-import static io.javalin.translator.json.JavalinJsonPlugin.getObjectToJsonMapper;
-
-@Immutable
-@Singleton
-@MethodsNotNullByDefault
-@ParametersAreNonnullByDefault
-public class ForumController {
-
- private final ForumManager forumManager;
-
- @Inject
- public ForumController(ForumManager forumManager) {
- this.forumManager = forumManager;
- }
-
- public Context list(Context ctx) throws DbException {
- Collection forums = forumManager.getForums();
- return ctx.result(getObjectToJsonMapper().map(forums));
- }
-
- public Context create(Context ctx) throws DbException {
- String name = ctx.formParam("name");
- if (name == null || name.length() < 1) {
- return ctx.status(500).result("Expecting Forum Name");
- } else {
- Forum forum = forumManager.addForum(name);
- return ctx.result(getObjectToJsonMapper().map(forum));
- }
- }
-
-}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.kt
new file mode 100644
index 000000000..52d6a06c7
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.kt
@@ -0,0 +1,26 @@
+package org.briarproject.briar.headless.forums
+
+import io.javalin.BadRequestResponse
+import io.javalin.Context
+import org.briarproject.briar.api.forum.ForumManager
+import javax.annotation.concurrent.Immutable
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Immutable
+@Singleton
+class ForumController @Inject
+constructor(private val forumManager: ForumManager) {
+
+ fun list(ctx: Context): Context {
+ return ctx.json(forumManager.forums.output())
+ }
+
+ fun create(ctx: Context): Context {
+ val name = ctx.formParam("name")
+ if (name == null || name.isEmpty())
+ throw BadRequestResponse("Expecting Forum Name")
+ return ctx.json(forumManager.addForum(name).output())
+ }
+
+}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/forums/OutputForum.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/OutputForum.kt
new file mode 100644
index 000000000..0066ab5cf
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/OutputForum.kt
@@ -0,0 +1,13 @@
+package org.briarproject.briar.headless.forums
+
+import org.briarproject.briar.api.forum.Forum
+import javax.annotation.concurrent.Immutable
+
+@Immutable
+@Suppress("unused")
+internal class OutputForum(forum: Forum) {
+
+ val name: String = forum.name
+ val id: ByteArray = forum.id.bytes
+
+}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/Extensions.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/Extensions.kt
new file mode 100644
index 000000000..f2d5bc248
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/Extensions.kt
@@ -0,0 +1,8 @@
+package org.briarproject.briar.headless.messaging
+
+import org.briarproject.briar.api.messaging.PrivateMessage
+import org.briarproject.briar.api.messaging.PrivateMessageHeader
+
+internal fun PrivateMessageHeader.output(body: String) = OutputPrivateMessage(this, body)
+
+internal fun PrivateMessage.output(body: String) = OutputPrivateMessage(this, body)
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.java b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.java
deleted file mode 100644
index 7146bc8ce..000000000
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.briarproject.briar.headless.messaging;
-
-import org.briarproject.bramble.api.FormatException;
-import org.briarproject.bramble.api.contact.Contact;
-import org.briarproject.bramble.api.contact.ContactId;
-import org.briarproject.bramble.api.contact.ContactManager;
-import org.briarproject.bramble.api.db.DbException;
-import org.briarproject.bramble.api.db.NoSuchContactException;
-import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.bramble.api.sync.Group;
-import org.briarproject.bramble.api.system.Clock;
-import org.briarproject.briar.api.messaging.MessagingManager;
-import org.briarproject.briar.api.messaging.PrivateMessage;
-import org.briarproject.briar.api.messaging.PrivateMessageFactory;
-import org.briarproject.briar.api.messaging.PrivateMessageHeader;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import io.javalin.Context;
-
-import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
-
-@Immutable
-@Singleton
-@NotNullByDefault
-public class MessagingController {
-
- private final MessagingManager messagingManager;
- private final PrivateMessageFactory privateMessageFactory;
- private final ContactManager contactManager;
- private final Clock clock;
-
- @Inject
- public MessagingController(MessagingManager messagingManager,
- PrivateMessageFactory privateMessageFactory,
- ContactManager contactManager,
- Clock clock) {
- this.messagingManager = messagingManager;
- this.privateMessageFactory = privateMessageFactory;
- this.contactManager = contactManager;
- this.clock = clock;
- }
-
- public Context list(Context ctx) throws DbException {
- Contact contact = getContact(ctx);
- if (contact == null) return ctx.status(404);
-
- Collection headers =
- messagingManager.getMessageHeaders(contact.getId());
- List messages = new ArrayList<>(headers.size());
- for (PrivateMessageHeader header : headers) {
- String body = messagingManager.getMessageBody(header.getId());
- messages.add(new OutputPrivateMessage(header, body));
- }
- return ctx.json(messages);
- }
-
- public Context write(Context ctx) throws DbException, FormatException {
- Contact contact = getContact(ctx);
- if (contact == null) return ctx.status(404);
-
- String message = ctx.formParam("message");
- if (message == null || message.length() < 1)
- return ctx.status(500).result("Expecting Message text");
- if (message.length() > MAX_PRIVATE_MESSAGE_BODY_LENGTH)
- return ctx.status(500).result("Message text too large");
-
- Group group = messagingManager.getContactGroup(contact);
- long now = clock.currentTimeMillis();
- PrivateMessage m = privateMessageFactory
- .createPrivateMessage(group.getId(), now, message);
-
- messagingManager.addLocalMessage(m);
- return ctx.json(new OutputPrivateMessage(m, message));
- }
-
- @Nullable
- private Contact getContact(Context ctx) throws DbException {
- String contactString = ctx.param("contactId");
- if (contactString == null) return null;
- int contactInt = Integer.parseInt(contactString);
- ContactId contactId = new ContactId(contactInt);
- try {
- return contactManager.getContact(contactId);
- } catch (NoSuchContactException e) {
- return null;
- }
- }
-
-}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.kt
new file mode 100644
index 000000000..d9fca98fb
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.kt
@@ -0,0 +1,66 @@
+package org.briarproject.briar.headless.messaging
+
+import io.javalin.BadRequestResponse
+import io.javalin.Context
+import io.javalin.NotFoundResponse
+import org.briarproject.bramble.api.contact.Contact
+import org.briarproject.bramble.api.contact.ContactId
+import org.briarproject.bramble.api.contact.ContactManager
+import org.briarproject.bramble.api.db.NoSuchContactException
+import org.briarproject.bramble.api.system.Clock
+import org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH
+import org.briarproject.briar.api.messaging.MessagingManager
+import org.briarproject.briar.api.messaging.PrivateMessageFactory
+import javax.annotation.concurrent.Immutable
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Immutable
+@Singleton
+class MessagingController @Inject
+constructor(
+ private val messagingManager: MessagingManager,
+ private val privateMessageFactory: PrivateMessageFactory,
+ private val contactManager: ContactManager,
+ private val clock: Clock
+) {
+
+ fun list(ctx: Context): Context {
+ val contact = getContact(ctx)
+
+ val messages = messagingManager.getMessageHeaders(contact.id).map { header ->
+ val body = messagingManager.getMessageBody(header.id)
+ header.output(body)
+ }
+ return ctx.json(messages)
+ }
+
+ fun write(ctx: Context): Context {
+ val contact = getContact(ctx)
+
+ val message = ctx.formParam("message")
+ if (message == null || message.isEmpty())
+ throw BadRequestResponse("Expecting Message text")
+ if (message.length > MAX_PRIVATE_MESSAGE_BODY_LENGTH)
+ throw BadRequestResponse("Message text too large")
+
+ val group = messagingManager.getContactGroup(contact)
+ val now = clock.currentTimeMillis()
+ val m = privateMessageFactory.createPrivateMessage(group.id, now, message)
+
+ messagingManager.addLocalMessage(m)
+ return ctx.json(m.output(message))
+ }
+
+ private fun getContact(ctx: Context): Contact {
+ val contactString = ctx.pathParam("contactId")
+ val contactInt = Integer.parseInt(contactString)
+ val contactId = ContactId(contactInt)
+ return try {
+ contactManager.getContact(contactId)
+ } catch (e: NoSuchContactException) {
+ throw NotFoundResponse()
+ }
+ }
+
+}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.java b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.java
deleted file mode 100644
index 6cf491d0e..000000000
--- a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.briarproject.briar.headless.messaging;
-
-import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
-import org.briarproject.briar.api.messaging.PrivateMessage;
-import org.briarproject.briar.api.messaging.PrivateMessageHeader;
-
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-@NotNullByDefault
-@SuppressWarnings("WeakerAccess")
-public class OutputPrivateMessage {
-
- public final String body;
- public final long timestamp;
- public final boolean read, seen, sent, local;
- public final byte[] id, groupId;
-
- OutputPrivateMessage(PrivateMessageHeader header, String body) {
- this.body = body;
- this.timestamp = header.getTimestamp();
- this.read = header.isRead();
- this.seen = header.isSeen();
- this.sent = header.isSent();
- this.local = header.isLocal();
- this.id = header.getId().getBytes();
- this.groupId = header.getGroupId().getBytes();
- }
-
- /**
- * Only meant for own {@link PrivateMessage}s directly after creation.
- */
- OutputPrivateMessage(PrivateMessage m, String body) {
- this.body = body;
- this.timestamp = m.getMessage().getTimestamp();
- this.read = true;
- this.seen = true;
- this.sent = false;
- this.local = true;
- this.id = m.getMessage().getId().getBytes();
- this.groupId = m.getMessage().getGroupId().getBytes();
- }
-}
diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt
new file mode 100644
index 000000000..1b93256ee
--- /dev/null
+++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt
@@ -0,0 +1,44 @@
+package org.briarproject.briar.headless.messaging
+
+import org.briarproject.briar.api.messaging.PrivateMessage
+import org.briarproject.briar.api.messaging.PrivateMessageHeader
+import javax.annotation.concurrent.Immutable
+
+@Immutable
+@Suppress("unused", "MemberVisibilityCanBePrivate")
+internal class OutputPrivateMessage {
+
+ val body: String
+ val timestamp: Long
+ val read: Boolean
+ val seen: Boolean
+ val sent: Boolean
+ val local: Boolean
+ val id: ByteArray
+ val groupId: ByteArray
+
+ internal constructor(header: PrivateMessageHeader, body: String) {
+ this.body = body
+ this.timestamp = header.timestamp
+ this.read = header.isRead
+ this.seen = header.isSeen
+ this.sent = header.isSent
+ this.local = header.isLocal
+ this.id = header.id.bytes
+ this.groupId = header.groupId.bytes
+ }
+
+ /**
+ * Only meant for own [PrivateMessage]s directly after creation.
+ */
+ internal constructor(m: PrivateMessage, body: String) {
+ this.body = body
+ this.timestamp = m.message.timestamp
+ this.read = true
+ this.seen = true
+ this.sent = false
+ this.local = true
+ this.id = m.message.id.bytes
+ this.groupId = m.message.groupId.bytes
+ }
+}
diff --git a/briar-headless/witness.gradle b/briar-headless/witness.gradle
index 0f51803bd..fc741e429 100644
--- a/briar-headless/witness.gradle
+++ b/briar-headless/witness.gradle
@@ -7,7 +7,7 @@ dependencyVerification {
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
- 'io.javalin:javalin:1.7.0:javalin-1.7.0.jar:d97d2044a7b050a3b6564c9a99a0a94a4c6d8c57818033cf0d8236bc90a8069b',
+ 'io.javalin:javalin:2.1.0:javalin-2.1.0.jar:d52264afbecddd1a8926a6d3b6f84ca534afa4d3997176c99e96ca2e0874577a',
'io.mockk:mockk-agent-api:1.8.6:mockk-agent-api-1.8.6.jar:613512c66538e6349e03df641a868f4ee324f13e2e1dbd67a0ed388aa664a444',
'io.mockk:mockk-agent-common:1.8.6:mockk-agent-common-1.8.6.jar:cb7cb26fae5bfd3c89090858548990f311b27f673b9efa9d0c94f97c463b2863',
'io.mockk:mockk-agent-jvm:1.8.6:mockk-agent-jvm-1.8.6.jar:3f30b98d23ada8b5a44d75b43cd58fc03252fcb96939ff31e7ad659818af1e5d',
@@ -20,29 +20,28 @@ dependencyVerification {
'net.bytebuddy:byte-buddy-agent:1.8.8:byte-buddy-agent-1.8.8.jar:dc1a2dcefe72731fa89ae84e32231c74d545ccf8216c79865096e546f20c57e8',
'net.bytebuddy:byte-buddy:1.8.8:byte-buddy-1.8.8.jar:30aed1ae2ee5261b1d2f0e98ec3fcb40755c3f61b378089fb65d56098df1f16b',
'org.apiguardian:apiguardian-api:1.0.0:apiguardian-api-1.0.0.jar:1f58b77470d8d147a0538d515347dd322f49a83b9e884b8970051160464b65b3',
- 'org.eclipse.jetty.websocket:websocket-api:9.4.9.v20180320:websocket-api-9.4.9.v20180320.jar:985b737f5c0928d48fc9890b261cbed096625350b9c0e321f44bde8a803c85ec',
- 'org.eclipse.jetty.websocket:websocket-client:9.4.9.v20180320:websocket-client-9.4.9.v20180320.jar:2f5c6a64987ac27a21862a6349bd2b1d25545cba9aa68084e50ef77af7adcd7d',
- 'org.eclipse.jetty.websocket:websocket-common:9.4.9.v20180320:websocket-common-9.4.9.v20180320.jar:26fc6bba6ad8e6522b27d5f397429c349264bcea076bd186ad885ef0cd0a73c8',
- 'org.eclipse.jetty.websocket:websocket-server:9.4.9.v20180320:websocket-server-9.4.9.v20180320.jar:93ebcfa8e8af9876491d1524b4e8d273be8a7576e18b75ef699bad9564f76de2',
- 'org.eclipse.jetty.websocket:websocket-servlet:9.4.9.v20180320:websocket-servlet-9.4.9.v20180320.jar:cac3f46db4917722b860e194907c36c251d2765ca1ce8323085c47cefafec52b',
- 'org.eclipse.jetty:jetty-client:9.4.9.v20180320:jetty-client-9.4.9.v20180320.jar:d6d8eca17806261a96137f64ad14c33feed26ba031c92180162961589141072d',
- 'org.eclipse.jetty:jetty-http:9.4.9.v20180320:jetty-http-9.4.9.v20180320.jar:823e76a9565f8a98c96542745f34560e2a6a9dfa6fbe320614061ad9b17b950b',
- 'org.eclipse.jetty:jetty-io:9.4.9.v20180320:jetty-io-9.4.9.v20180320.jar:fffa35ca529d3267ad80d87f83ad4f6796b0981ae21d3ff621151bbe0a8f4155',
- 'org.eclipse.jetty:jetty-security:9.4.9.v20180320:jetty-security-9.4.9.v20180320.jar:5cbaeb9837aa331a8ee918724786655c6f60f8cc65ab84e03ff587bc212a2327',
- 'org.eclipse.jetty:jetty-server:9.4.9.v20180320:jetty-server-9.4.9.v20180320.jar:b45869789b8f8081c1c75c059b4fd262d2fd440fa676c54bc753365fdd1f82d6',
- 'org.eclipse.jetty:jetty-servlet:9.4.9.v20180320:jetty-servlet-9.4.9.v20180320.jar:a96f8711d4f9d5d4c3fcafa046fb5caefec17eefcbfcd35b6c2e1d5a0549edfc',
- 'org.eclipse.jetty:jetty-util:9.4.9.v20180320:jetty-util-9.4.9.v20180320.jar:86ccb5e178e7001f26a12ec4bf56c522911424a0edf60424f15add8601355fc5',
- 'org.eclipse.jetty:jetty-webapp:9.4.9.v20180320:jetty-webapp-9.4.9.v20180320.jar:7d6c6af12f10a47524e8eabc607226b038100680612ea569f92c030158bd5566',
- 'org.eclipse.jetty:jetty-xml:9.4.9.v20180320:jetty-xml-9.4.9.v20180320.jar:2a0c8e64364cb8d0f483e5e050db6fbd26f0ad9e5098367f8af7928887fa5ece',
+ 'org.eclipse.jetty.websocket:websocket-api:9.4.11.v20180605:websocket-api-9.4.11.v20180605.jar:924edcf7fb17f2ff2e541afce7fd692305235e51b5a16f7223d7e8b4de77559d',
+ 'org.eclipse.jetty.websocket:websocket-client:9.4.11.v20180605:websocket-client-9.4.11.v20180605.jar:d3c812f80ac18d7031ffe2a324f2f83d8b260a99863be81b81668184ad5f2cca',
+ 'org.eclipse.jetty.websocket:websocket-common:9.4.11.v20180605:websocket-common-9.4.11.v20180605.jar:f00731b8f9d2f2155bd87a2040cdef991fbcd24ff843ff4ba1ab1829bf62c04c',
+ 'org.eclipse.jetty.websocket:websocket-server:9.4.11.v20180605:websocket-server-9.4.11.v20180605.jar:0cfa90029d46618116f986cc6aea1c4f2e7408f3c97ad3eb2f92f74aff37279b',
+ 'org.eclipse.jetty.websocket:websocket-servlet:9.4.11.v20180605:websocket-servlet-9.4.11.v20180605.jar:76f52b482ad174944e07f552cbfaaa2ccf498063e0a3837bb930eee8a06373aa',
+ 'org.eclipse.jetty:jetty-client:9.4.11.v20180605:jetty-client-9.4.11.v20180605.jar:b096ea6ee2607886323791930a470b2e04fb3327459b287ef99647226bd7a09c',
+ 'org.eclipse.jetty:jetty-http:9.4.11.v20180605:jetty-http-9.4.11.v20180605.jar:963b75730aa92b0dfbe65fe8a2e413edc88aeb53e8686ba6b1617d7caeb14067',
+ 'org.eclipse.jetty:jetty-io:9.4.11.v20180605:jetty-io-9.4.11.v20180605.jar:75c82d6e542a3518e2517c4084c83d8216ec2d2458f8747b8b5c944355ebd732',
+ 'org.eclipse.jetty:jetty-security:9.4.11.v20180605:jetty-security-9.4.11.v20180605.jar:5a12b1c69264466004baff33b14fc1555007c86fb2fece2a420c480aa7f8ef56',
+ 'org.eclipse.jetty:jetty-server:9.4.11.v20180605:jetty-server-9.4.11.v20180605.jar:b74af5ac482b05c242ed231e00b7c08a0b6649f76f2e039a0885de0cf1376ef8',
+ 'org.eclipse.jetty:jetty-servlet:9.4.11.v20180605:jetty-servlet-9.4.11.v20180605.jar:e24f145a6d95c7653ad2fe0c34cf8ce7311effb7eb8ed9399fae63d8af63eaf4',
+ 'org.eclipse.jetty:jetty-util:9.4.11.v20180605:jetty-util-9.4.11.v20180605.jar:936e5ed74275c16164cc1eccaeae55900eb00edd9f1b1d3b83d70782dd25f505',
+ 'org.eclipse.jetty:jetty-webapp:9.4.11.v20180605:jetty-webapp-9.4.11.v20180605.jar:858f3f16cecb0891f07a4e8d82554201c513bf058c0f65969b366936155b6a36',
+ 'org.eclipse.jetty:jetty-xml:9.4.11.v20180605:jetty-xml-9.4.11.v20180605.jar:1780bdaee2b1908e032fbc286bb856d730c4d0c9de39d5e14a1b9c48028c295e',
'org.jetbrains.kotlin:kotlin-compiler-embeddable:1.2.61:kotlin-compiler-embeddable-1.2.61.jar:f8165810c61f440a2de6003ed9857d28a1dfc990bacbecee1436610c8ebe565b',
'org.jetbrains.kotlin:kotlin-reflect:1.2.41:kotlin-reflect-1.2.41.jar:1bab75771dfa2bb5949cd383ceaedf6f8d354fa0d677804fc5a39e320bab70d3',
'org.jetbrains.kotlin:kotlin-reflect:1.2.61:kotlin-reflect-1.2.61.jar:a4f1ed542390f9bf967fb9aff2c232b90988f7ce138a4b7bcc70b754821a8943',
'org.jetbrains.kotlin:kotlin-script-runtime:1.2.61:kotlin-script-runtime-1.2.61.jar:793e4c54a8d59cf1f1cda68a7bc6be1ad54c41d771a08d308aa28c2cd304f1b1',
'org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.2.61:kotlin-scripting-compiler-embeddable-1.2.61.jar:99e0ee865f9c7c8ddcc0975185c69392182311067fe2a6faa72e942185631c1c',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.2.61:kotlin-stdlib-common-1.2.61.jar:54a6fab7dae0cd7528208e95868fe1869b01b613c3018f2e53dbbad2604f6595',
- 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.41:kotlin-stdlib-jdk7-1.2.41.jar:169ee5879cba8444499243ceea5e6a2cb6ecea5424211cc819f0704501154b35',
- 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.41:kotlin-stdlib-jdk8-1.2.41.jar:b306e0e6735841e31e320bf3260c71d60fc35057cfa87895f23251ee260a64a8',
- 'org.jetbrains.kotlin:kotlin-stdlib:1.2.41:kotlin-stdlib-1.2.41.jar:f0595b9ed88ddc6fd66bddf68c56c6f2f6c4b17faa51e43e478acad32b05303e',
+ 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.61:kotlin-stdlib-jdk7-1.2.61.jar:f02ed7a640323b162c798a7834b35c10590880151e104eeb83acd84b364ef030',
+ 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.61:kotlin-stdlib-jdk8-1.2.61.jar:1fdeec7f74c2bae97a2205bb4aff0c6fe9d133bd619d069a0928156098d1b927',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.61:kotlin-stdlib-1.2.61.jar:62eaf9cc6e746cef4593abe7cdb4dd48694ef5f817c852e0d9fbbd11fcfc564e',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.junit.jupiter:junit-jupiter-api:5.2.0:junit-jupiter-api-5.2.0.jar:47f7d71b35dc331210b9ab219bbb00d54332981aa12eb5effe817de17e1ae7b3',