diff --git a/bulletin-board-client/src/main/java/meerkat/bulletinboard/SimpleBulletinBoardClient.java b/bulletin-board-client/src/main/java/meerkat/bulletinboard/SimpleBulletinBoardClient.java index 80451b8..26b1e4e 100644 --- a/bulletin-board-client/src/main/java/meerkat/bulletinboard/SimpleBulletinBoardClient.java +++ b/bulletin-board-client/src/main/java/meerkat/bulletinboard/SimpleBulletinBoardClient.java @@ -1,21 +1,14 @@ package meerkat.bulletinboard; import com.google.protobuf.ByteString; -import com.google.protobuf.Timestamp; import meerkat.comm.CommunicationException; -import meerkat.comm.MessageInputStream; import meerkat.crypto.Digest; import meerkat.crypto.concrete.SHA256Digest; -import meerkat.protobuf.BulletinBoardAPI; import meerkat.protobuf.BulletinBoardAPI.*; +import meerkat.protobuf.Comm.*; import meerkat.protobuf.Voting.*; import meerkat.rest.*; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.util.Collection; -import java.util.Iterator; import java.util.List; import javax.ws.rs.client.Client; diff --git a/bulletin-board-client/src/main/java/meerkat/bulletinboard/workers/singleserver/SingleServerCloseBatchWorker.java b/bulletin-board-client/src/main/java/meerkat/bulletinboard/workers/singleserver/SingleServerCloseBatchWorker.java index ab298a5..83e27c2 100644 --- a/bulletin-board-client/src/main/java/meerkat/bulletinboard/workers/singleserver/SingleServerCloseBatchWorker.java +++ b/bulletin-board-client/src/main/java/meerkat/bulletinboard/workers/singleserver/SingleServerCloseBatchWorker.java @@ -6,7 +6,7 @@ import static meerkat.bulletinboard.BulletinBoardConstants.CLOSE_BATCH_PATH; /** * Created by Arbel Deutsch Peled on 27-Dec-15. - * Tries to contact server once and perform a close batch operation + * Tries to contact server once and perform a stop batch operation */ public class SingleServerCloseBatchWorker extends SingleServerGenericPostWorker { diff --git a/bulletin-board-client/src/main/java/meerkat/bulletinboard/workers/singleserver/SingleServerGenericPostWorker.java b/bulletin-board-client/src/main/java/meerkat/bulletinboard/workers/singleserver/SingleServerGenericPostWorker.java index 621a828..2148801 100644 --- a/bulletin-board-client/src/main/java/meerkat/bulletinboard/workers/singleserver/SingleServerGenericPostWorker.java +++ b/bulletin-board-client/src/main/java/meerkat/bulletinboard/workers/singleserver/SingleServerGenericPostWorker.java @@ -2,7 +2,7 @@ package meerkat.bulletinboard.workers.singleserver; import meerkat.bulletinboard.SingleServerWorker; import meerkat.comm.CommunicationException; -import meerkat.protobuf.BulletinBoardAPI.BoolMsg; +import meerkat.protobuf.Comm.*; import meerkat.rest.Constants; import javax.ws.rs.ProcessingException; diff --git a/bulletin-board-client/src/test/java/meerkat/bulletinboard/GenericBulletinBoardClientTester.java b/bulletin-board-client/src/test/java/meerkat/bulletinboard/GenericBulletinBoardClientTester.java index 88fb22c..d4bd3ec 100644 --- a/bulletin-board-client/src/test/java/meerkat/bulletinboard/GenericBulletinBoardClientTester.java +++ b/bulletin-board-client/src/test/java/meerkat/bulletinboard/GenericBulletinBoardClientTester.java @@ -508,7 +508,7 @@ public class GenericBulletinBoardClientTester { .build()) .build(); - // Try to close the (unopened) batch; + // Try to stop the (unopened) batch; bulletinBoardClient.closeBatch(closeBatchMessage, failPostCallback); diff --git a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/BulletinBoardSQLServer.java b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/BulletinBoardSQLServer.java index b652b1a..dd68daf 100644 --- a/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/BulletinBoardSQLServer.java +++ b/bulletin-board-server/src/main/java/meerkat/bulletinboard/sqlserver/BulletinBoardSQLServer.java @@ -17,6 +17,7 @@ import meerkat.crypto.concrete.ECDSASignature; import meerkat.crypto.concrete.SHA256Digest; import meerkat.protobuf.BulletinBoardAPI.*; +import meerkat.protobuf.Comm.*; import meerkat.protobuf.Crypto.Signature; import meerkat.protobuf.Crypto.SignatureVerificationKey; @@ -27,7 +28,6 @@ import javax.sql.DataSource; import meerkat.util.BulletinBoardUtils; import meerkat.util.TimestampComparator; -import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; diff --git a/bulletin-board-server/src/main/java/meerkat/bulletinboard/webapp/BulletinBoardWebApp.java b/bulletin-board-server/src/main/java/meerkat/bulletinboard/webapp/BulletinBoardWebApp.java index 5f98ff6..f88d31f 100644 --- a/bulletin-board-server/src/main/java/meerkat/bulletinboard/webapp/BulletinBoardWebApp.java +++ b/bulletin-board-server/src/main/java/meerkat/bulletinboard/webapp/BulletinBoardWebApp.java @@ -15,8 +15,8 @@ import meerkat.bulletinboard.sqlserver.MySQLQueryProvider; import meerkat.bulletinboard.sqlserver.SQLiteQueryProvider; import meerkat.comm.CommunicationException; import meerkat.comm.MessageOutputStream; -import meerkat.protobuf.BulletinBoardAPI; import meerkat.protobuf.BulletinBoardAPI.*; +import meerkat.protobuf.Comm.*; import static meerkat.bulletinboard.BulletinBoardConstants.*; import static meerkat.rest.Constants.*; diff --git a/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardSQLServerIntegrationTest.java b/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardSQLServerIntegrationTest.java index 8debb83..a9be646 100644 --- a/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardSQLServerIntegrationTest.java +++ b/bulletin-board-server/src/test/java/meerkat/bulletinboard/BulletinBoardSQLServerIntegrationTest.java @@ -8,6 +8,7 @@ import com.google.protobuf.Timestamp; import meerkat.comm.MessageInputStream; import meerkat.protobuf.Crypto.*; import meerkat.protobuf.BulletinBoardAPI.*; +import meerkat.protobuf.Comm.*; import static meerkat.bulletinboard.BulletinBoardConstants.*; import meerkat.rest.Constants; import meerkat.rest.ProtobufMessageBodyReader; @@ -20,7 +21,6 @@ import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.io.InputStream; import java.util.List; diff --git a/bulletin-board-server/src/test/java/meerkat/bulletinboard/GenericBulletinBoardServerTest.java b/bulletin-board-server/src/test/java/meerkat/bulletinboard/GenericBulletinBoardServerTest.java index 131aee8..e09f051 100644 --- a/bulletin-board-server/src/test/java/meerkat/bulletinboard/GenericBulletinBoardServerTest.java +++ b/bulletin-board-server/src/test/java/meerkat/bulletinboard/GenericBulletinBoardServerTest.java @@ -28,8 +28,8 @@ import meerkat.crypto.Digest; import meerkat.crypto.concrete.ECDSASignature; import meerkat.crypto.concrete.SHA256Digest; import meerkat.protobuf.BulletinBoardAPI.*; +import meerkat.protobuf.Comm.*; import meerkat.util.BulletinBoardMessageGenerator; -import org.h2.util.DateTimeUtils; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; diff --git a/meerkat-common/src/main/java/meerkat/bulletinboard/BulletinBoardServer.java b/meerkat-common/src/main/java/meerkat/bulletinboard/BulletinBoardServer.java index f6ca1ab..abe4335 100644 --- a/meerkat-common/src/main/java/meerkat/bulletinboard/BulletinBoardServer.java +++ b/meerkat-common/src/main/java/meerkat/bulletinboard/BulletinBoardServer.java @@ -3,6 +3,7 @@ package meerkat.bulletinboard; import meerkat.comm.CommunicationException; import meerkat.comm.MessageOutputStream; import meerkat.protobuf.BulletinBoardAPI.*; +import meerkat.protobuf.Comm.*; import java.util.Collection; @@ -62,8 +63,8 @@ public interface BulletinBoardServer{ public BoolMsg postBatchMessage(BatchMessage batchMessage) throws CommunicationException; /** - * Attempts to close and finalize a batch message - * @param message contains the data necessary to close the batch; in particular: the signature for the batch + * Attempts to stop and finalize a batch message + * @param message contains the data necessary to stop the batch; in particular: the signature for the batch * @return TRUE if the batch was successfully closed, FALSE otherwise * Specifically, if the signature is invalid or if some of the batch parts have not yet been submitted: the value returned will be FALSE * @throws CommunicationException on DB connection error diff --git a/meerkat-common/src/main/java/meerkat/pollingstation/PollingStationConstants.java b/meerkat-common/src/main/java/meerkat/pollingstation/PollingStationConstants.java index 643a73c..1bc6d3c 100644 --- a/meerkat-common/src/main/java/meerkat/pollingstation/PollingStationConstants.java +++ b/meerkat-common/src/main/java/meerkat/pollingstation/PollingStationConstants.java @@ -7,9 +7,7 @@ public interface PollingStationConstants { // Relative addresses for Scanner operations - public static final String POLLING_STATION_WEB_SCANNER_PATH = "/scanner"; public static final String POLLING_STATION_WEB_SCANNER_SCAN_PATH = "/scan"; public static final String POLLING_STATION_WEB_SCANNER_ERROR_PATH = "/error"; - } diff --git a/meerkat-common/src/main/java/meerkat/pollingstation/PollingStationScanner.java b/meerkat-common/src/main/java/meerkat/pollingstation/PollingStationScanner.java index 9bea5b5..9adc616 100644 --- a/meerkat-common/src/main/java/meerkat/pollingstation/PollingStationScanner.java +++ b/meerkat-common/src/main/java/meerkat/pollingstation/PollingStationScanner.java @@ -1,29 +1,61 @@ package meerkat.pollingstation; import com.google.common.util.concurrent.FutureCallback; +import meerkat.protobuf.Comm.BoolMsg; import meerkat.protobuf.PollingStation.*; /** * Created by Arbel on 05/05/2016. * An interface for the scanner used by the Polling Station Committee + * The scanner works as a producer, while the polling station is the consumer + * That is to say: scans are pushed from the scanner rather than requested by the polling station */ public interface PollingStationScanner { /** - * Subscribes to new scans - * @param scanCallback is the handler for scanned data + * An interface for processing scans (Polling Station side) */ - public void subscribe(FutureCallback scanCallback); + public interface Consumer { + + /** + * Sets up the connection to the scanner and begins receiving scans + * @throws Exception when the operation fails + */ + public void start() throws Exception; + + /** + * Closes the connection to the scanner + * @throws Exception when the operation fails + */ + public void stop() throws Exception; + + /** + * Subscribes to new scans + * + * @param scanCallback is the handler for scanned data + */ + public void subscribe(FutureCallback scanCallback); + + } /** - * Sends a scan to all subscribers - * @param scannedData contains the scanned data + * An interface for submitting scanned data (scanner side) */ - public void newScan(ScannedData scannedData); + public interface Producer { - /** - * Notifies subscribers about an error that occurred during scan - * @param errorMsg is the error that occurred - */ - public void reportScanError(ErrorMsg errorMsg); + /** + * Sends a scan to all subscribers + * @param scannedData contains the scanned data + * @return a BoolMsg containing TRUE iff the scanned data has been sent to at least one subscriber + */ + public BoolMsg newScan(ScannedData scannedData); + /** + * Notifies subscribers about an error that occurred during scan + * @param errorMsg is the error that occurred + * @return a BoolMsg containing TRUE iff the error has been sent to at least one subscriber + */ + public BoolMsg reportScanError(ErrorMsg errorMsg); + + } + } \ No newline at end of file diff --git a/meerkat-common/src/main/proto/meerkat/BulletinBoardAPI.proto b/meerkat-common/src/main/proto/meerkat/BulletinBoardAPI.proto index 0edb03b..27ad512 100644 --- a/meerkat-common/src/main/proto/meerkat/BulletinBoardAPI.proto +++ b/meerkat-common/src/main/proto/meerkat/BulletinBoardAPI.proto @@ -7,14 +7,6 @@ option java_package = "meerkat.protobuf"; import 'meerkat/crypto.proto'; import 'google/protobuf/timestamp.proto'; -message BoolMsg { - bool value = 1; -} - -message IntMsg { - int32 value = 1; -} - message MessageID { // The ID of a message for unique retrieval. // Note that it is assumed that this ID is a function of the message itself. diff --git a/meerkat-common/src/main/proto/meerkat/PollingStation.proto b/meerkat-common/src/main/proto/meerkat/PollingStation.proto index 0cdc658..35dbd12 100644 --- a/meerkat-common/src/main/proto/meerkat/PollingStation.proto +++ b/meerkat-common/src/main/proto/meerkat/PollingStation.proto @@ -12,4 +12,11 @@ message ScannedData { // Container for error messages message ErrorMsg { string msg = 1; +} + +// Container for HTTP address +message HTTPAddress { + string hostname = 1; + int32 port = 2; + string address = 3; } \ No newline at end of file diff --git a/meerkat-common/src/main/proto/meerkat/comm.proto b/meerkat-common/src/main/proto/meerkat/comm.proto index c509165..2f23678 100644 --- a/meerkat-common/src/main/proto/meerkat/comm.proto +++ b/meerkat-common/src/main/proto/meerkat/comm.proto @@ -11,3 +11,11 @@ message BroadcastMessage { bytes payload = 5; } + +message BoolMsg { + bool value = 1; +} + +message IntMsg { + int32 value = 1; +} diff --git a/polling-station/build.gradle b/polling-station/build.gradle index 036d2e8..4635668 100644 --- a/polling-station/build.gradle +++ b/polling-station/build.gradle @@ -2,10 +2,8 @@ plugins { id "us.kirchmeier.capsule" version "1.0.1" id 'com.google.protobuf' version '0.7.0' - id 'org.akhikhl.gretty' version "1.2.4" } -apply plugin: 'org.akhikhl.gretty' apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' @@ -46,10 +44,11 @@ dependencies { compile project(':restful-api-common') // Jersey for RESTful API - compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.22.+' + compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.5.+' // Servlets - compile 'javax.servlet:javax.servlet-api:3.0.+' + compile 'org.eclipse.jetty:jetty-server:9.3.+' + compile 'org.eclipse.jetty:jetty-servlet:9.3.+' // Logging compile 'org.slf4j:slf4j-api:1.7.7' diff --git a/polling-station/src/main/java/meerkat/pollingstation/PollingStationScannerWebApp.java b/polling-station/src/main/java/meerkat/pollingstation/PollingStationScannerWebApp.java new file mode 100644 index 0000000..edebe33 --- /dev/null +++ b/polling-station/src/main/java/meerkat/pollingstation/PollingStationScannerWebApp.java @@ -0,0 +1,89 @@ +package meerkat.pollingstation; + +/** + * Created by Arbel on 5/31/2016. + */ + +import com.google.common.util.concurrent.FutureCallback; +import meerkat.protobuf.Comm; +import meerkat.protobuf.PollingStation; + +import javax.annotation.PostConstruct; +import javax.servlet.ServletContext; +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import java.io.IOException; +import java.util.Iterator; + +import static meerkat.pollingstation.PollingStationConstants.POLLING_STATION_WEB_SCANNER_ERROR_PATH; +import static meerkat.pollingstation.PollingStationConstants.POLLING_STATION_WEB_SCANNER_SCAN_PATH; +import static meerkat.rest.Constants.MEDIATYPE_PROTOBUF; + +/** + * Implements a Web-App interface for {@link meerkat.pollingstation.PollingStationScanner.Producer} + * This class depends on {@link meerkat.pollingstation.PollingStationWebScanner} and works in conjunction with it + */ +@Path("/") +public class PollingStationScannerWebApp implements PollingStationScanner.Producer { + + @Context + ServletContext servletContext; + + Iterator> callbacks; + + /** + * This method is called by the Jetty engine when instantiating the servlet + */ + @PostConstruct + public void init() throws Exception{ + callbacks = ((PollingStationWebScanner.CallbackAccessor) servletContext.getAttribute(PollingStationWebScanner.CALLBACKS_ATTRIBUTE_NAME)).getCallbackIterator(); + } + + @POST + @Path(POLLING_STATION_WEB_SCANNER_SCAN_PATH) + @Consumes(MEDIATYPE_PROTOBUF) + @Produces(MEDIATYPE_PROTOBUF) + @Override + public Comm.BoolMsg newScan(PollingStation.ScannedData scannedData) { + + boolean handled = false; + + while (callbacks.hasNext()){ + + callbacks.next().onSuccess(scannedData); + handled = true; + + } + + return Comm.BoolMsg.newBuilder() + .setValue(handled) + .build(); + + } + + @POST + @Path(POLLING_STATION_WEB_SCANNER_ERROR_PATH) + @Consumes(MEDIATYPE_PROTOBUF) + @Produces(MEDIATYPE_PROTOBUF) + @Override + public Comm.BoolMsg reportScanError(PollingStation.ErrorMsg errorMsg) { + + boolean handled = false; + + while (callbacks.hasNext()){ + + callbacks.next().onFailure(new IOException(errorMsg.getMsg())); + handled = true; + + } + + return Comm.BoolMsg.newBuilder() + .setValue(handled) + .build(); + + } + +} diff --git a/polling-station/src/main/java/meerkat/pollingstation/PollingStationWebScanner.java b/polling-station/src/main/java/meerkat/pollingstation/PollingStationWebScanner.java index a3aefdd..d7fc6a4 100644 --- a/polling-station/src/main/java/meerkat/pollingstation/PollingStationWebScanner.java +++ b/polling-station/src/main/java/meerkat/pollingstation/PollingStationWebScanner.java @@ -1,27 +1,57 @@ package meerkat.pollingstation; -import com.google.common.util.concurrent.FutureCallback; -import meerkat.protobuf.PollingStation; -import static meerkat.rest.Constants.*; - -import javax.ws.rs.*; -import java.io.IOException; -import java.util.LinkedList; +import java.util.Iterator; import java.util.List; +import java.util.LinkedList; + +import com.google.common.util.concurrent.FutureCallback; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.*; -import static meerkat.pollingstation.PollingStationConstants.*; import meerkat.protobuf.PollingStation.*; +import org.glassfish.jersey.servlet.ServletContainer; +import org.glassfish.jersey.server.ResourceConfig; + +import meerkat.protobuf.PollingStation.ScannedData; +import meerkat.rest.*; /** * Created by Arbel on 05/05/2016. */ -@Path(POLLING_STATION_WEB_SCANNER_PATH) -public class PollingStationWebScanner implements PollingStationScanner{ +public class PollingStationWebScanner implements PollingStationScanner.Consumer{ + + public final static String CALLBACKS_ATTRIBUTE_NAME = "callbacks"; + + private final Server server; private final List> callbacks; - public PollingStationWebScanner() { + public PollingStationWebScanner(HTTPAddress address) { + callbacks = new LinkedList<>(); + + server = new Server(address.getPort()); + + ServletContextHandler servletContextHandler = new ServletContextHandler(server, address.getAddress()); + servletContextHandler.setAttribute(CALLBACKS_ATTRIBUTE_NAME, new CallbackAccessor()); + + ResourceConfig resourceConfig = new ResourceConfig(PollingStationScannerWebApp.class); + resourceConfig.register(ProtobufMessageBodyReader.class); + resourceConfig.register(ProtobufMessageBodyWriter.class); + + ServletHolder servletHolder = new ServletHolder(new ServletContainer(resourceConfig)); + + servletContextHandler.addServlet(servletHolder, "/*"); + } + + @Override + public void start() throws Exception { + server.start(); + } + + @Override + public void stop() throws Exception { + server.stop(); } @Override @@ -29,43 +59,10 @@ public class PollingStationWebScanner implements PollingStationScanner{ callbacks.add(scanCallback); } - @Path(POLLING_STATION_WEB_SCANNER_SCAN_PATH) - @POST - @Consumes(MEDIATYPE_PROTOBUF) - @Produces(MEDIATYPE_PROTOBUF) - @Override - public void newScan(ScannedData scannedData) { - - if (callbacks.size() <= 0) - throw new RuntimeException("No subscribers to forward scan to!"); - - for (FutureCallback callback : callbacks){ - callback.onSuccess(scannedData); + public class CallbackAccessor { + public Iterator> getCallbackIterator() { + return callbacks.iterator(); } - } - @Path(POLLING_STATION_WEB_SCANNER_ERROR_PATH) - @POST - @Consumes(MEDIATYPE_PROTOBUF) - @Produces(MEDIATYPE_PROTOBUF) - @Override - public void reportScanError(PollingStation.ErrorMsg errorMsg) { - - if (callbacks.size() <= 0) - throw new RuntimeException("No subscribers to forward error to!"); - - for (FutureCallback callback : callbacks){ - callback.onFailure(new IOException(errorMsg.getMsg())); - } - - } - - @Path("/test") - @GET - public String test(){ - return "test"; - } - - } diff --git a/polling-station/src/main/webapp/META-INF/jetty-env.xml b/polling-station/src/main/webapp/META-INF/jetty-env.xml deleted file mode 100644 index c4d368f..0000000 --- a/polling-station/src/main/webapp/META-INF/jetty-env.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern - none - - - org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern - none - - \ No newline at end of file diff --git a/polling-station/src/main/webapp/WEB-INF/web.xml b/polling-station/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 0632b0d..0000000 --- a/polling-station/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - Jersey Hello World - - org.glassfish.jersey.servlet.ServletContainer - - - jersey.config.server.provider.packages - meerkat - - 1 - - - Jersey Hello World - /* - - - meerkat.pollingstation.PollingStationWebScanner - - diff --git a/polling-station/src/test/java/meerkat/pollingstation/PollingStationWebScannerTest.java b/polling-station/src/test/java/meerkat/pollingstation/PollingStationWebScannerTest.java new file mode 100644 index 0000000..63cd8dd --- /dev/null +++ b/polling-station/src/test/java/meerkat/pollingstation/PollingStationWebScannerTest.java @@ -0,0 +1,169 @@ +package meerkat.pollingstation; + +import com.google.common.util.concurrent.FutureCallback; +import com.google.protobuf.ByteString; +import com.sun.org.apache.regexp.internal.RE; +import meerkat.protobuf.PollingStation; +import meerkat.protobuf.PollingStation.*; +import meerkat.rest.Constants; + +import meerkat.rest.*; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; + +import java.io.IOException; +import java.util.concurrent.Semaphore; + +import static meerkat.pollingstation.PollingStationConstants.*; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * Created by Arbel on 25/05/2016. + */ +public class PollingStationWebScannerTest { + + private PollingStationScanner.Consumer scanner; + private HTTPAddress httpAddress; + + private Semaphore semaphore; + private Throwable thrown; + private boolean dataIsAsExpected; + + private class ScanHandler implements FutureCallback { + + private final ScannedData expectedData; + + public ScanHandler(ScannedData expectedData) { + this.expectedData = expectedData; + } + + @Override + public void onSuccess(ScannedData result) { + dataIsAsExpected = result.getData().equals(expectedData.getData()); + semaphore.release(); + } + + @Override + public void onFailure(Throwable t) { + dataIsAsExpected = false; + thrown = t; + semaphore.release(); + } + } + + private class ErrorHandler implements FutureCallback { + + private final String expectedErrorMessage; + + public ErrorHandler(String expectedErrorMessage) { + this.expectedErrorMessage = expectedErrorMessage; + } + + @Override + public void onSuccess(ScannedData result) { + dataIsAsExpected = false; + semaphore.release(); + } + + @Override + public void onFailure(Throwable t) { + dataIsAsExpected = t.getMessage().equals(expectedErrorMessage); + semaphore.release(); + } + } + + @Before + public void init() { + + System.err.println("Setting up Scanner WebApp!"); + + httpAddress = HTTPAddress.newBuilder() + .setPort(8080) + .setHostname("http://localhost") + .build(); + + scanner = new PollingStationWebScanner(httpAddress); + + semaphore = new Semaphore(0); + thrown = null; + + try { + scanner.start(); + } catch (Exception e) { + assertThat("Could not start server: " + e.getMessage(), false); + } + + } + + @Test + public void testSuccessfulScan() throws InterruptedException { + + Client client = ClientBuilder.newClient(); + client.register(ProtobufMessageBodyReader.class); + client.register(ProtobufMessageBodyWriter.class); + WebTarget webTarget = client.target(httpAddress.getHostname() + ":" + httpAddress.getPort()) + .path(httpAddress.getAddress()).path(POLLING_STATION_WEB_SCANNER_SCAN_PATH); + + byte[] data = {(byte) 1, (byte) 2}; + + ScannedData scannedData = ScannedData.newBuilder() + .setData(ByteString.copyFrom(data)) + .build(); + + scanner.subscribe(new ScanHandler(scannedData)); + + Response response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(scannedData, Constants.MEDIATYPE_PROTOBUF)); + response.close(); + + semaphore.acquire(); + assertThat("Scanner has thrown an error", thrown == null); + assertThat("Scanned data received was incorrect", dataIsAsExpected); + + } + + @Test + public void testErroneousScan() throws InterruptedException { + + Client client = ClientBuilder.newClient(); + client.register(ProtobufMessageBodyReader.class); + client.register(ProtobufMessageBodyWriter.class); + WebTarget webTarget = client.target(httpAddress.getHostname() + ":" + httpAddress.getPort()) + .path(httpAddress.getAddress()).path(POLLING_STATION_WEB_SCANNER_ERROR_PATH); + + ErrorMsg errorMsg = ErrorMsg.newBuilder() + .setMsg("!Error Message!") + .build(); + + scanner.subscribe(new ErrorHandler(errorMsg.getMsg())); + + Response response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(errorMsg, Constants.MEDIATYPE_PROTOBUF)); + response.close(); + + semaphore.acquire(); + assertThat("Scanner error received was incorrect", dataIsAsExpected); + + } + + @After + public void close() { + + System.err.println("Scanner WebApp shutting down..."); + + try { + scanner.stop(); + } catch (Exception e) { + assertThat("Could not stop server: " + e.getMessage(), false); + } + + } + +} \ No newline at end of file