1. ScannedData now has a Channel and a SignedEncryptedBallot attributes,
rather than just 'data' attribute 2. Implemented a NetworkVirtualPrinter output device, and now both this class and the previous SystemConsoleOutputDevice extend the same new abstract class AsyncRunnableOutputDevice which supplies default implementations for the interface methods.vbdev2
parent
3a5908ac49
commit
14fac728b3
|
@ -2,11 +2,16 @@ syntax = "proto3";
|
||||||
|
|
||||||
package meerkat;
|
package meerkat;
|
||||||
|
|
||||||
|
import "meerkat/voting.proto";
|
||||||
|
|
||||||
option java_package = "meerkat.protobuf";
|
option java_package = "meerkat.protobuf";
|
||||||
|
|
||||||
// Container for scanned data
|
// Container for scanned data
|
||||||
message ScannedData {
|
message ScannedData {
|
||||||
bytes data = 1;
|
bytes channel = 1;
|
||||||
|
|
||||||
|
SignedEncryptedBallot signed_encrypted_ballot = 2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container for error messages
|
// Container for error messages
|
||||||
|
|
|
@ -2,7 +2,9 @@ package meerkat.pollingstation;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
import meerkat.protobuf.Crypto.Signature;
|
||||||
import meerkat.protobuf.PollingStation.*;
|
import meerkat.protobuf.PollingStation.*;
|
||||||
|
import meerkat.protobuf.Voting.SignedEncryptedBallot;
|
||||||
import meerkat.rest.Constants;
|
import meerkat.rest.Constants;
|
||||||
|
|
||||||
import meerkat.rest.*;
|
import meerkat.rest.*;
|
||||||
|
@ -46,7 +48,7 @@ public class PollingStationWebScannerTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(ScannedData result) {
|
public void onSuccess(ScannedData result) {
|
||||||
dataIsAsExpected = result.getData().equals(expectedData.getData());
|
dataIsAsExpected = result.getChannel().equals(expectedData.getChannel());
|
||||||
semaphore.release();
|
semaphore.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +111,7 @@ public class PollingStationWebScannerTest {
|
||||||
byte[] data = {(byte) 1, (byte) 2};
|
byte[] data = {(byte) 1, (byte) 2};
|
||||||
|
|
||||||
ScannedData scannedData = ScannedData.newBuilder()
|
ScannedData scannedData = ScannedData.newBuilder()
|
||||||
.setData(ByteString.copyFrom(data))
|
.setChannel(ByteString.copyFrom(data))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
scanner.subscribe(new ScanHandler(scannedData));
|
scanner.subscribe(new ScanHandler(scannedData));
|
||||||
|
|
|
@ -1,46 +1,30 @@
|
||||||
package meerkat.voting.output;
|
package meerkat.voting.output;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.protobuf.BoolValue;
|
import meerkat.protobuf.Voting.BallotSecrets;
|
||||||
import meerkat.protobuf.PollingStation.ScannedData;
|
import meerkat.protobuf.Voting.PlaintextBallot;
|
||||||
import meerkat.protobuf.Voting.*;
|
import meerkat.protobuf.Voting.SignedEncryptedBallot;
|
||||||
import meerkat.rest.*;
|
|
||||||
import meerkat.voting.controller.callbacks.ControllerCallback;
|
import meerkat.voting.controller.callbacks.ControllerCallback;
|
||||||
import meerkat.voting.output.outputcommands.*;
|
import meerkat.voting.output.outputcommands.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.ws.rs.client.*;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
import static meerkat.pollingstation.PollingStationConstants.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by hai on 27/06/16.
|
* Created by hai on 27/06/16.
|
||||||
*/
|
*/
|
||||||
public class AsyncRunnableOutputDevice implements BallotOutputDevice, Runnable {
|
public abstract class AsyncRunnableOutputDevice implements BallotOutputDevice, Runnable {
|
||||||
|
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
private LinkedBlockingQueue<OutputCommand> queue;
|
private LinkedBlockingQueue<OutputCommand> queue;
|
||||||
private volatile boolean shutDownHasBeenCalled;
|
private volatile boolean shutDownHasBeenCalled;
|
||||||
|
|
||||||
private SignedEncryptedBallot signedEncryptedBallot;
|
public AsyncRunnableOutputDevice() {
|
||||||
|
|
||||||
private final WebTarget successfulPrintTarget;
|
|
||||||
|
|
||||||
public AsyncRunnableOutputDevice(String address) {
|
|
||||||
logger = LoggerFactory.getLogger(AsyncRunnableOutputDevice.class);
|
logger = LoggerFactory.getLogger(AsyncRunnableOutputDevice.class);
|
||||||
logger.info("A NetworkVirtualPrinter is constructed");
|
logger.info("AsyncRunnableOutputDevice is constructed");
|
||||||
queue = new LinkedBlockingQueue<>();
|
queue = new LinkedBlockingQueue<>();
|
||||||
shutDownHasBeenCalled = false;
|
shutDownHasBeenCalled = false;
|
||||||
|
|
||||||
Client client = ClientBuilder.newClient();
|
|
||||||
client.register(ProtobufMessageBodyReader.class);
|
|
||||||
client.register(ProtobufMessageBodyWriter.class);
|
|
||||||
successfulPrintTarget = client.target(address).path(POLLING_STATION_WEB_SCANNER_SCAN_PATH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -69,6 +53,15 @@ public class AsyncRunnableOutputDevice implements BallotOutputDevice, Runnable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
abstract void doCommitToBallot(CommitOutputCommand command);
|
||||||
|
|
||||||
|
abstract void doAudit(AuditOutputCommand command);
|
||||||
|
|
||||||
|
abstract void doCastBallot(CastOutputCommand command);
|
||||||
|
|
||||||
|
abstract void doCancel(CancelOutputCommand command);
|
||||||
|
|
||||||
|
|
||||||
private void handleSingleCommand(OutputCommand command) {
|
private void handleSingleCommand(OutputCommand command) {
|
||||||
if (command instanceof CommitOutputCommand) {
|
if (command instanceof CommitOutputCommand) {
|
||||||
doCommitToBallot((CommitOutputCommand)command);
|
doCommitToBallot((CommitOutputCommand)command);
|
||||||
|
@ -118,44 +111,4 @@ public class AsyncRunnableOutputDevice implements BallotOutputDevice, Runnable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void doCommitToBallot(CommitOutputCommand command) {
|
|
||||||
logger.debug("entered method doCommitToBallot");
|
|
||||||
signedEncryptedBallot = command.getSignedEncryptedBallot();
|
|
||||||
command.getCallback().onSuccess(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void doAudit(AuditOutputCommand command) {
|
|
||||||
logger.debug("entered method doAudit");
|
|
||||||
signedEncryptedBallot = null;
|
|
||||||
command.getCallback().onSuccess(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void doCastBallot(CastOutputCommand command) {
|
|
||||||
logger.debug("entered method doCastBallot");
|
|
||||||
ScannedData scannedData = ScannedData.newBuilder()
|
|
||||||
.setChannel(null) //TODO: fill the details for the channel to be able to send here
|
|
||||||
.setSignedEncryptedBallot(this.signedEncryptedBallot)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
Response response = successfulPrintTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(scannedData, Constants.MEDIATYPE_PROTOBUF));
|
|
||||||
BoolValue b = response.readEntity(BoolValue.class);
|
|
||||||
response.close();
|
|
||||||
|
|
||||||
if (b.getValue()) {
|
|
||||||
command.getCallback().onSuccess(null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
command.getCallback().onFailure(new IOException());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void doCancel(CancelOutputCommand command) {
|
|
||||||
logger.debug("entered method doCancel");
|
|
||||||
signedEncryptedBallot = null;
|
|
||||||
command.getCallback().onSuccess(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,84 @@
|
||||||
package meerkat.voting.output;
|
package meerkat.voting.output;
|
||||||
|
|
||||||
import com.google.protobuf.BoolValue;
|
import com.google.protobuf.BoolValue;
|
||||||
import meerkat.pollingstation.PollingStationScanner;
|
import meerkat.protobuf.PollingStation.ScannedData;
|
||||||
import meerkat.protobuf.PollingStation.*;
|
import meerkat.protobuf.Voting.SignedEncryptedBallot;
|
||||||
import meerkat.rest.*;
|
import meerkat.rest.Constants;
|
||||||
|
import meerkat.rest.ProtobufMessageBodyReader;
|
||||||
|
import meerkat.rest.ProtobufMessageBodyWriter;
|
||||||
|
import meerkat.voting.output.outputcommands.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.ws.rs.client.*;
|
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 static meerkat.pollingstation.PollingStationConstants.*;
|
import static meerkat.pollingstation.PollingStationConstants.POLLING_STATION_WEB_SCANNER_SCAN_PATH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by hai on 27/06/16.
|
* Created by hai on 27/06/16.
|
||||||
*/
|
*/
|
||||||
public class NetworkVirtualPrinter implements PollingStationScanner.Producer {
|
public class NetworkVirtualPrinter extends AsyncRunnableOutputDevice {
|
||||||
|
|
||||||
WebTarget successfulScanPath;
|
private Logger logger;
|
||||||
WebTarget errorPath;
|
private SignedEncryptedBallot signedEncryptedBallot;
|
||||||
|
private final WebTarget successfulPrintTarget;
|
||||||
|
|
||||||
public NetworkVirtualPrinter(String address) {
|
public NetworkVirtualPrinter(String address) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
logger = LoggerFactory.getLogger(NetworkVirtualPrinter.class);
|
||||||
|
logger.info("A NetworkVirtualPrinter is constructed");
|
||||||
|
|
||||||
Client client = ClientBuilder.newClient();
|
Client client = ClientBuilder.newClient();
|
||||||
client.register(ProtobufMessageBodyReader.class);
|
client.register(ProtobufMessageBodyReader.class);
|
||||||
client.register(ProtobufMessageBodyWriter.class);
|
client.register(ProtobufMessageBodyWriter.class);
|
||||||
successfulScanPath = client.target(address).path(POLLING_STATION_WEB_SCANNER_SCAN_PATH);
|
successfulPrintTarget = client.target(address).path(POLLING_STATION_WEB_SCANNER_SCAN_PATH);
|
||||||
errorPath = client.target(address).path(POLLING_STATION_WEB_SCANNER_ERROR_PATH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BoolValue newScan(ScannedData scannedData) {
|
public void doCommitToBallot(CommitOutputCommand command) {
|
||||||
return null;
|
logger.debug("entered method doCommitToBallot");
|
||||||
|
signedEncryptedBallot = command.getSignedEncryptedBallot();
|
||||||
|
command.getCallback().onSuccess(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BoolValue reportScanError(ErrorMsg errorMsg) {
|
public void doAudit(AuditOutputCommand command) {
|
||||||
return null;
|
logger.debug("entered method doAudit");
|
||||||
|
signedEncryptedBallot = null;
|
||||||
|
command.getCallback().onSuccess(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void doCastBallot(CastOutputCommand command) {
|
||||||
|
logger.debug("entered method doCastBallot");
|
||||||
|
ScannedData scannedData = ScannedData.newBuilder()
|
||||||
|
.setChannel(null) //TODO: fill the details for the channel to be able to send here
|
||||||
|
.setSignedEncryptedBallot(this.signedEncryptedBallot)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Response response = successfulPrintTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(scannedData, Constants.MEDIATYPE_PROTOBUF));
|
||||||
|
BoolValue b = response.readEntity(BoolValue.class);
|
||||||
|
response.close();
|
||||||
|
|
||||||
|
if (b.getValue()) {
|
||||||
|
command.getCallback().onSuccess(null);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
command.getCallback().onFailure(new IOException());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void doCancel(CancelOutputCommand command) {
|
||||||
|
logger.debug("entered method doCancel");
|
||||||
|
signedEncryptedBallot = null;
|
||||||
|
command.getCallback().onSuccess(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,96 +1,28 @@
|
||||||
package meerkat.voting.output;
|
package meerkat.voting.output;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import meerkat.protobuf.Crypto.*;
|
import meerkat.protobuf.Crypto.*;
|
||||||
import meerkat.protobuf.Voting.*;
|
import meerkat.protobuf.Voting.*;
|
||||||
import meerkat.voting.controller.callbacks.ControllerCallback;
|
|
||||||
import meerkat.voting.output.outputcommands.*;
|
import meerkat.voting.output.outputcommands.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A toy OutputDevice class
|
* A toy OutputDevice class
|
||||||
* outputs everything simply to the System console
|
* outputs everything simply to the System console
|
||||||
*/
|
*/
|
||||||
public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
|
public class SystemConsoleOutputDevice extends AsyncRunnableOutputDevice {
|
||||||
|
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
private LinkedBlockingQueue<OutputCommand> queue;
|
|
||||||
private volatile boolean shutDownHasBeenCalled;
|
|
||||||
|
|
||||||
public SystemConsoleOutputDevice () {
|
public SystemConsoleOutputDevice () {
|
||||||
|
super();
|
||||||
logger = LoggerFactory.getLogger(SystemConsoleOutputDevice.class);
|
logger = LoggerFactory.getLogger(SystemConsoleOutputDevice.class);
|
||||||
logger.info("A SystemConsoleOutputDevice is constructed");
|
logger.info("A SystemConsoleOutputDevice is constructed");
|
||||||
queue = new LinkedBlockingQueue<>();
|
|
||||||
shutDownHasBeenCalled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the UTF8 decoding of byte-string data
|
|
||||||
*/
|
|
||||||
private static String bytesToString(ByteString data) {
|
|
||||||
return data.toStringUtf8();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run () {
|
|
||||||
logger.info("UI starts running");
|
|
||||||
while (! wasShutDownCalled()) {
|
|
||||||
try {
|
|
||||||
OutputCommand command = queue.take();
|
|
||||||
handleSingleCommand(command);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {
|
|
||||||
logger.warn ("Interrupted while reading from command queue " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean wasShutDownCalled () {
|
|
||||||
return shutDownHasBeenCalled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void callShutDown() {
|
|
||||||
logger.info("callShutDown command has been called");
|
|
||||||
shutDownHasBeenCalled = true;
|
|
||||||
queue.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void handleSingleCommand(OutputCommand command) {
|
|
||||||
if (command instanceof CommitOutputCommand) {
|
|
||||||
doCommitToBallot((CommitOutputCommand)command);
|
|
||||||
}
|
|
||||||
else if (command instanceof AuditOutputCommand) {
|
|
||||||
doAudit((AuditOutputCommand)command);
|
|
||||||
}
|
|
||||||
else if (command instanceof CastOutputCommand) {
|
|
||||||
doCastBallot((CastOutputCommand)command);
|
|
||||||
}
|
|
||||||
else if (command instanceof CancelOutputCommand) {
|
|
||||||
doCancel((CancelOutputCommand)command);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String errorMessage = "handleSingleCommand: unknown type of OutputCommand received: " +
|
|
||||||
command.getClass().getName();
|
|
||||||
logger.error(errorMessage);
|
|
||||||
throw new RuntimeException(errorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void commitToBallot(PlaintextBallot plaintextBallot,
|
|
||||||
SignedEncryptedBallot signedEncryptedBallot,
|
|
||||||
FutureCallback<Void> callback) {
|
|
||||||
logger.debug("Output interface call to commit to ballot");
|
|
||||||
queue.add(new CommitOutputCommand(plaintextBallot, signedEncryptedBallot, (ControllerCallback)callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doCommitToBallot(CommitOutputCommand command) {
|
public void doCommitToBallot(CommitOutputCommand command) {
|
||||||
logger.debug("entered method doCommitToBallot");
|
logger.debug("entered method doCommitToBallot");
|
||||||
|
@ -111,12 +43,6 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void audit(BallotSecrets ballotSecrets, FutureCallback<Void> callback) {
|
|
||||||
logger.debug("an interface call to audit");
|
|
||||||
queue.add(new AuditOutputCommand(ballotSecrets, (ControllerCallback)callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doAudit(AuditOutputCommand command) {
|
public void doAudit(AuditOutputCommand command) {
|
||||||
logger.debug("entered method doAudit");
|
logger.debug("entered method doAudit");
|
||||||
System.out.println("Auditing");
|
System.out.println("Auditing");
|
||||||
|
@ -127,12 +53,6 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void castBallot(FutureCallback<Void> callback) {
|
|
||||||
logger.debug("an interface call to cast ballot");
|
|
||||||
queue.add(new CastOutputCommand((ControllerCallback)callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doCastBallot(CastOutputCommand command) {
|
public void doCastBallot(CastOutputCommand command) {
|
||||||
logger.debug("entered method doCastBallot");
|
logger.debug("entered method doCastBallot");
|
||||||
System.out.println("Ballot finalized for casting!");
|
System.out.println("Ballot finalized for casting!");
|
||||||
|
@ -140,12 +60,6 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelBallot(FutureCallback<Void> callback) {
|
|
||||||
logger.debug("an interface call to cancel the output");
|
|
||||||
queue.add(new CancelOutputCommand((ControllerCallback)callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doCancel(CancelOutputCommand command) {
|
public void doCancel(CancelOutputCommand command) {
|
||||||
logger.debug("entered method doCancel");
|
logger.debug("entered method doCancel");
|
||||||
System.out.println("Ballot cancelled!");
|
System.out.println("Ballot cancelled!");
|
||||||
|
@ -165,4 +79,12 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
|
||||||
System.out.println(bytesToString(data));
|
System.out.println(bytesToString(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the UTF8 decoding of byte-string data
|
||||||
|
*/
|
||||||
|
private static String bytesToString(ByteString data) {
|
||||||
|
return data.toStringUtf8();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue