diff --git a/README.md b/README.md index c7f8883..f7d3d59 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,68 @@ -# bw2Android -Android bindings for Bosswave +# bw2Android - Android Bindings for Bosswave + +## Obtaining a JAR File +This project uses Gradle for compilation and dependency management. After +cloning the project, run the following from the top level directory: +``` +$ ./gradlew shadowJar +``` + +After Gradle has finished, a fat JAR file will be available under `build/libs`. + +## Basic Usage +Here's a rough example of how to initialize the client, publish, and subscribe. +```java +// Many client methods throw IOExceptions +BosswaveClient client; +try { + // Connect to a Bosswave agent running locally + client = new BosswaveClient("localhost", BosswaveClient.DEFAULT_PORT); + + // Set the Bosswave entity to be used for subsequent operations + client.setEntityFromFile("myKey.ent"); + + // Enable auto chain by default + client.overrideAutoChainTo(true); + + // Define a callback to handle Bosswave errors + private class ResponseErrorHandler implements ResponseHandler { + @Override + public void onResponseReceived(BosswaveResponse resp) { + if (!resp.getStatus().equals("okay")) { + throw new RuntimeException(resp.getReason())); + } + } + } + + // Publish a simple text message + PublishRequest.Builder builder = new PublishRequest.Builder(BW_URI); + PayloadObject.Type poType = new PayloadObject.Type(POAllocations.PODFText); + String message = "Hello, World!"; + byte[] poContents = message.getBytes(StandardCharsets.UTF_8); + PayloadObject po = new PayloadObject(poType, poContents); + builder.addPayloadObject(po); + PublishRequest request = builder.build(); + client.publish(request, new ResponseErrorHandler()); + + // Define a callback to handle incoming text messages + private class TextResultHandler implements ResultHandler { + @Override + public void onResultReceived(BosswaveResult rslt) { + byte[] messageContent = rslt.getPayloadObjects().get(0).getContent(); + String msg = new String(messageContent, StandardCharsets.UTF_8); + System.out.println(msg); + } + } + + // Subscribe to a Bosswave URI + SubscribeRequest.Builder builder = new SubscribeRequest.Builder("scratch.ns/foo/bar"); + SubscribeRequest request = builder.build(); + client.subscribe(request, new ResponseErrorHandler(), new TextResultHandler()); + + // Additional application logic... +} finally { + if (client != null) { + client.close(); + } +} +``` diff --git a/src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveClient.java b/src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveClient.java index c867b7b..0f18b56 100644 --- a/src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveClient.java +++ b/src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveClient.java @@ -25,7 +25,7 @@ public class BosswaveClient implements Closeable { private final Map responseHandlers; private final Object responseHandlerLock; - private final Map messageHandlers; + private final Map resultHandlers; private final Object messageHandlersLock; private final Map listResultHandlers; private final Object listResultHandlersLock; @@ -42,7 +42,7 @@ public BosswaveClient(String hostName, int port) throws IOException { responseHandlers = new HashMap(); responseHandlerLock = new Object(); - messageHandlers = new HashMap(); + resultHandlers = new HashMap(); messageHandlersLock = new Object(); listResultHandlers = new HashMap(); listResultHandlersLock = new Object(); @@ -173,7 +173,7 @@ public void publish(PublishRequest request, ResponseHandler handler) throws IOEx installResponseHandler(seqNo, handler); } - public void subscribe(SubscribeRequest request, ResponseHandler rh, MessageHandler mh) throws IOException { + public void subscribe(SubscribeRequest request, ResponseHandler rspH, ResultHandler rsltH) throws IOException { int seqNo = Frame.generateSequenceNumber(); Frame.Builder builder = new Frame.Builder(Command.SUBSCRIBE, seqNo); @@ -220,11 +220,11 @@ public void subscribe(SubscribeRequest request, ResponseHandler rh, MessageHandl f.writeToStream(outStream); outStream.flush(); - if (rh != null) { - installResponseHandler(seqNo, rh); + if (rspH != null) { + installResponseHandler(seqNo, rspH); } - if (mh != null) { - installMessageHandler(seqNo, mh); + if (rsltH != null) { + installResultHandler(seqNo, rsltH); } } @@ -274,7 +274,7 @@ public void list(ListRequest request, ResponseHandler rh, ListResultHandler lrh) } } - public void query(QueryRequest request, ResponseHandler rh, MessageHandler mh) throws IOException { + public void query(QueryRequest request, ResponseHandler respH, ResultHandler rsltH) throws IOException { int seqNo = Frame.generateSequenceNumber(); Frame.Builder builder = new Frame.Builder(Command.QUERY, seqNo); @@ -316,11 +316,11 @@ public void query(QueryRequest request, ResponseHandler rh, MessageHandler mh) t Frame f = builder.build(); f.writeToStream(outStream); outStream.flush(); - if (rh != null) { - installResponseHandler(seqNo, rh); + if (respH != null) { + installResponseHandler(seqNo, respH); } - if (mh != null) { - installMessageHandler(seqNo, mh); + if (rsltH != null) { + installResultHandler(seqNo, rsltH); } } @@ -444,9 +444,9 @@ private void installResponseHandler(int seqNo, ResponseHandler rh) { } } - private void installMessageHandler(int seqNo, MessageHandler mh) { + private void installResultHandler(int seqNo, ResultHandler rh) { synchronized (messageHandlersLock) { - messageHandlers.put(seqNo, mh); + resultHandlers.put(seqNo, rh); } } @@ -485,13 +485,13 @@ public void run() { reason = new String(frame.getFirstValue("reason"), CharEncoding.UTF_8); // Upon error, we also need to clean up any result handlers synchronized (messageHandlersLock) { - messageHandlers.remove(seqNo); + resultHandlers.remove(seqNo); } synchronized (listResultHandlersLock) { listResultHandlers.remove(seqNo); } } - responseHandler.onResponseReceived(new Response(status, reason)); + responseHandler.onResponseReceived(new BosswaveResponse(status, reason)); } break; } @@ -499,12 +499,12 @@ public void run() { case RESULT: { String finishedStr = new String(frame.getFirstValue("finished"), CharEncoding.UTF_8); boolean finished = Boolean.parseBoolean(finishedStr); - MessageHandler messageHandler; + ResultHandler resultHandler; synchronized (messageHandlersLock) { if (finished) { - messageHandler = messageHandlers.remove(seqNo); + resultHandler = resultHandlers.remove(seqNo); } else { - messageHandler = messageHandlers.get(seqNo); + resultHandler = resultHandlers.get(seqNo); } } ListResultHandler listResultHandler; @@ -516,7 +516,7 @@ public void run() { } } - if (messageHandler != null) { + if (resultHandler != null) { String uri = new String(frame.getFirstValue("uri"), CharEncoding.UTF_8); String from = new String(frame.getFirstValue("from"), CharEncoding.UTF_8); @@ -526,13 +526,13 @@ public void run() { unpack = Boolean.parseBoolean(new String(unpackBytes, CharEncoding.UTF_8)); } - Message msg; + BosswaveResult result; if (unpack) { - msg = new Message(from, uri, frame.getRoutingObjects(), frame.getPayloadObjects()); + result = new BosswaveResult(from, uri, frame.getRoutingObjects(), frame.getPayloadObjects()); } else { - msg = new Message(from, uri, null, null); + result = new BosswaveResult(from, uri, null, null); } - messageHandler.onResultReceived(msg); + resultHandler.onResultReceived(result); } else if (listResultHandler != null) { if (finished) { listResultHandler.finish(); diff --git a/src/main/java/edu/berkeley/cs/sdb/bosswave/Response.java b/src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveResponse.java similarity index 76% rename from src/main/java/edu/berkeley/cs/sdb/bosswave/Response.java rename to src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveResponse.java index add2354..3b80262 100644 --- a/src/main/java/edu/berkeley/cs/sdb/bosswave/Response.java +++ b/src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveResponse.java @@ -1,10 +1,10 @@ package edu.berkeley.cs.sdb.bosswave; -public class Response { +public class BosswaveResponse { private final String status; private final String reason; - public Response(String status, String reason) { + public BosswaveResponse(String status, String reason) { this.status = status; this.reason = reason; } diff --git a/src/main/java/edu/berkeley/cs/sdb/bosswave/Message.java b/src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveResult.java similarity index 84% rename from src/main/java/edu/berkeley/cs/sdb/bosswave/Message.java rename to src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveResult.java index 54667e7..90cbb1a 100644 --- a/src/main/java/edu/berkeley/cs/sdb/bosswave/Message.java +++ b/src/main/java/edu/berkeley/cs/sdb/bosswave/BosswaveResult.java @@ -3,13 +3,13 @@ import java.util.Collections; import java.util.List; -public class Message { +public class BosswaveResult { private final String from; private final String uri; private final List routingObjects; private final List payloadObjects; - public Message(String from, String uri, List ros, List pos) { + public BosswaveResult(String from, String uri, List ros, List pos) { this.from = from; this.uri = uri; routingObjects = Collections.unmodifiableList(ros); diff --git a/src/main/java/edu/berkeley/cs/sdb/bosswave/MessageHandler.java b/src/main/java/edu/berkeley/cs/sdb/bosswave/MessageHandler.java deleted file mode 100644 index 7fe41a7..0000000 --- a/src/main/java/edu/berkeley/cs/sdb/bosswave/MessageHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package edu.berkeley.cs.sdb.bosswave; - -public interface MessageHandler { - void onResultReceived(Message message); -} diff --git a/src/main/java/edu/berkeley/cs/sdb/bosswave/ResponseHandler.java b/src/main/java/edu/berkeley/cs/sdb/bosswave/ResponseHandler.java index 05a8b33..0a18726 100644 --- a/src/main/java/edu/berkeley/cs/sdb/bosswave/ResponseHandler.java +++ b/src/main/java/edu/berkeley/cs/sdb/bosswave/ResponseHandler.java @@ -1,5 +1,5 @@ package edu.berkeley.cs.sdb.bosswave; public interface ResponseHandler { - void onResponseReceived(Response result); + void onResponseReceived(BosswaveResponse result); } diff --git a/src/main/java/edu/berkeley/cs/sdb/bosswave/ResultHandler.java b/src/main/java/edu/berkeley/cs/sdb/bosswave/ResultHandler.java new file mode 100644 index 0000000..5944e74 --- /dev/null +++ b/src/main/java/edu/berkeley/cs/sdb/bosswave/ResultHandler.java @@ -0,0 +1,5 @@ +package edu.berkeley.cs.sdb.bosswave; + +public interface ResultHandler { + void onResultReceived(BosswaveResult result); +} diff --git a/src/test/java/edu/berkeley/cs/sdb/bosswave/BosswaveClientTest.java b/src/test/java/edu/berkeley/cs/sdb/bosswave/BosswaveClientTest.java index aa3874f..6cce7f8 100644 --- a/src/test/java/edu/berkeley/cs/sdb/bosswave/BosswaveClientTest.java +++ b/src/test/java/edu/berkeley/cs/sdb/bosswave/BosswaveClientTest.java @@ -29,7 +29,7 @@ public class BosswaveClientTest { private final Semaphore sem = new Semaphore(0); private BosswaveClient client; private final TestResponseHandler responseHandler = new TestResponseHandler(); - private final TestMessageHandler messageHandler = new TestMessageHandler(); + private final TestResultHandler resultHandler = new TestResultHandler(); @Before public void setUp() throws IOException { @@ -42,14 +42,14 @@ public void setUp() throws IOException { SubscribeRequest request = builder.build(); client.subscribe(request, new ResponseHandler() { @Override - public void onResponseReceived(Response result) { - if (result.getStatus().equals("okay")) { + public void onResponseReceived(BosswaveResponse response) { + if (response.getStatus().equals("okay")) { sem.release(); } else { - throw new RuntimeException("Failed to subscribe: " + result.getReason()); + throw new RuntimeException("Failed to subscribe: " + response.getReason()); } } - }, messageHandler); + }, resultHandler); } @After @@ -79,25 +79,25 @@ public void testPublish() throws IOException, InterruptedException { private static class TestResponseHandler implements ResponseHandler { @Override - public void onResponseReceived(Response result) { - if (!result.getStatus().equals("okay")) { - throw new RuntimeException("Bosswave operation failed: " + result.getReason()); + public void onResponseReceived(BosswaveResponse response) { + if (!response.getStatus().equals("okay")) { + throw new RuntimeException("Bosswave operation failed: " + response.getReason()); } } } - private class TestMessageHandler implements MessageHandler { + private class TestResultHandler implements ResultHandler { private int counter; - public TestMessageHandler() { + public TestResultHandler() { counter = 0; } @Override - public void onResultReceived(Message message) { - assertEquals(message.getPayloadObjects().size(), 1); - byte[] messageContent = message.getPayloadObjects().get(0).getContent(); + public void onResultReceived(BosswaveResult result) { + assertEquals(result.getPayloadObjects().size(), 1); + byte[] messageContent = result.getPayloadObjects().get(0).getContent(); String messageText; try { messageText = new String(messageContent, CharEncoding.UTF_8);