Wrapped jSSC's SerialPort and SerialPortList classes for testability.

This commit is contained in:
akwizgran
2012-12-15 23:05:41 +00:00
parent b090a12b7f
commit cfb90597bd
8 changed files with 136 additions and 36 deletions

View File

@@ -21,6 +21,6 @@ class ModemFactoryImpl implements ModemFactory {
public Modem createModem(Modem.Callback callback, String portName) {
return new ModemImpl(executor, reliabilityFactory, clock, callback,
portName);
new SerialPortImpl(portName));
}
}

View File

@@ -12,10 +12,8 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.logging.Logger;
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
import net.sf.briar.api.clock.Clock;
import net.sf.briar.api.reliability.ReliabilityLayer;
import net.sf.briar.api.reliability.ReliabilityLayerFactory;
@@ -47,12 +45,12 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
private boolean initialised = false, connected = false; // Locking: this
ModemImpl(Executor executor, ReliabilityLayerFactory reliabilityFactory,
Clock clock, Callback callback, String portName) {
Clock clock, Callback callback, SerialPort port) {
this.executor = executor;
this.reliabilityFactory = reliabilityFactory;
this.clock = clock;
this.callback = callback;
port = new SerialPort(portName);
this.port = port;
stateChange = new Semaphore(1);
line = new byte[MAX_LINE_LENGTH];
}
@@ -67,12 +65,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
}
try {
// Open the serial port
try {
if(!port.openPort())
throw new IOException("Failed to open serial port");
} catch(SerialPortException e) {
throw new IOException(e.toString());
}
port.openPort();
// Find a suitable baud rate and initialise the modem
try {
boolean foundBaudRate = false;
@@ -90,9 +83,9 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
port.addEventListener(this);
port.writeBytes("ATZ\r\n".getBytes("US-ASCII")); // Reset
port.writeBytes("ATE0\r\n".getBytes("US-ASCII")); // Echo off
} catch(SerialPortException e) {
} catch(IOException e) {
tryToClose(port);
throw new IOException(e.toString());
throw e;
}
// Wait for the event thread to receive "OK"
boolean success = false;
@@ -122,7 +115,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
private void tryToClose(SerialPort port) {
try {
port.closePort();
} catch(SerialPortException e) {
} catch(IOException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
}
@@ -145,11 +138,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
}
try {
hangUpInner();
try {
port.closePort();
} catch(SerialPortException e) {
throw new IOException(e.toString());
}
port.closePort();
} finally {
stateChange.release();
}
@@ -179,9 +168,9 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
tryToClose(port);
Thread.currentThread().interrupt();
throw new IOException("Interrupted while hanging up");
} catch(SerialPortException e) {
} catch(IOException e) {
tryToClose(port);
throw new IOException(e.toString());
throw e;
}
}
@@ -212,9 +201,9 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
try {
String dial = "ATDT" + number + "\r\n";
port.writeBytes(dial.getBytes("US-ASCII"));
} catch(SerialPortException e) {
} catch(IOException e) {
tryToClose(port);
throw new IOException(e.toString());
throw e;
}
// Wait for the event thread to receive "CONNECT"
try {
@@ -275,9 +264,9 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
public void handleWrite(byte[] b) throws IOException {
try {
port.writeBytes(b);
} catch(SerialPortException e) {
} catch(IOException e) {
tryToClose(port);
throw new IOException(e.toString());
throw e;
}
}
@@ -297,8 +286,6 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
}
} catch(IOException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch(SerialPortException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
}
@@ -391,9 +378,9 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
if(LOG.isLoggable(INFO)) LOG.info("Answering");
try {
port.writeBytes("ATA\r\n".getBytes("US-ASCII"));
} catch(SerialPortException e) {
} catch(IOException e) {
tryToClose(port);
throw new IOException(e.toString());
throw e;
}
// Wait for the event thread to receive "CONNECT"
boolean success = false;

View File

@@ -17,7 +17,6 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.logging.Logger;
import jssc.SerialPortList;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportProperties;
import net.sf.briar.api.crypto.PseudoRandom;
@@ -41,6 +40,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
private final Executor pluginExecutor;
private final ModemFactory modemFactory;
private final SerialPortList serialPortList;
private final DuplexPluginCallback callback;
private final long pollingInterval;
private final Semaphore polling;
@@ -49,10 +49,11 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
private volatile Modem modem = null;
ModemPlugin(@PluginExecutor Executor pluginExecutor,
ModemFactory modemFactory, DuplexPluginCallback callback,
long pollingInterval) {
ModemFactory modemFactory, SerialPortList serialPortList,
DuplexPluginCallback callback, long pollingInterval) {
this.pluginExecutor = pluginExecutor;
this.modemFactory = modemFactory;
this.serialPortList = serialPortList;
this.callback = callback;
this.pollingInterval = pollingInterval;
polling = new Semaphore(1);
@@ -67,7 +68,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
}
public boolean start() {
for(String portName : SerialPortList.getPortNames()) {
for(String portName : serialPortList.getPortNames()) {
if(LOG.isLoggable(INFO))
LOG.info("Trying to initialise modem on " + portName);
modem = modemFactory.createModem(this, portName);
@@ -97,7 +98,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
private boolean resetModem() {
if(!running) return false;
for(String portName : SerialPortList.getPortNames()) {
for(String portName : serialPortList.getPortNames()) {
modem = modemFactory.createModem(this, portName);
try {
modem.start();

View File

@@ -16,11 +16,13 @@ public class ModemPluginFactory implements DuplexPluginFactory {
private final Executor pluginExecutor;
private final ModemFactory modemFactory;
private final SerialPortList serialPortList;
public ModemPluginFactory(@PluginExecutor Executor pluginExecutor,
ReliabilityLayerFactory reliabilityFactory) {
this.pluginExecutor = pluginExecutor;
modemFactory = new ModemFactoryImpl(pluginExecutor, reliabilityFactory);
serialPortList = new SerialPortListImpl();
}
public TransportId getId() {
@@ -31,7 +33,7 @@ public class ModemPluginFactory implements DuplexPluginFactory {
// This plugin is not enabled by default
String enabled = callback.getConfig().get("enabled");
if(StringUtils.isNullOrEmpty(enabled)) return null;
return new ModemPlugin(pluginExecutor, modemFactory, callback,
POLLING_INTERVAL);
return new ModemPlugin(pluginExecutor, modemFactory, serialPortList,
callback, POLLING_INTERVAL);
}
}

View File

@@ -0,0 +1,23 @@
package net.sf.briar.plugins.modem;
import java.io.IOException;
import jssc.SerialPortEventListener;
interface SerialPort {
void openPort() throws IOException;
void closePort() throws IOException;
boolean setParams(int baudRate, int dataBits, int stopBits, int parityBits)
throws IOException;
void purgePort(int flags) throws IOException;
void addEventListener(SerialPortEventListener l) throws IOException;
byte[] readBytes() throws IOException;
void writeBytes(byte[] b) throws IOException;
}

View File

@@ -0,0 +1,73 @@
package net.sf.briar.plugins.modem;
import java.io.IOException;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
class SerialPortImpl implements SerialPort {
private final jssc.SerialPort port;
SerialPortImpl(String portName) {
port = new jssc.SerialPort(portName);
}
public void openPort() throws IOException {
try {
if(!port.openPort()) throw new IOException("Failed to open port");
} catch(SerialPortException e) {
throw new IOException(e.toString());
}
}
public void closePort() throws IOException {
try {
if(!port.closePort()) throw new IOException("Failed to close port");
} catch(SerialPortException e) {
throw new IOException(e.toString());
}
}
public boolean setParams(int baudRate, int dataBits, int stopBits,
int parityBits) throws IOException {
try {
return port.setParams(baudRate, dataBits, stopBits, parityBits);
} catch(SerialPortException e) {
throw new IOException(e.toString());
}
}
public void purgePort(int flags) throws IOException {
try {
if(!port.purgePort(flags))
throw new IOException("Failed to purge port");
} catch(SerialPortException e) {
throw new IOException(e.toString());
}
}
public void addEventListener(SerialPortEventListener l) throws IOException {
try {
port.addEventListener(l);
} catch(SerialPortException e) {
throw new IOException(e.toString());
}
}
public byte[] readBytes() throws IOException {
try {
return port.readBytes();
} catch(SerialPortException e) {
throw new IOException(e.toString());
}
}
public void writeBytes(byte[] b) throws IOException {
try {
if(!port.writeBytes(b)) throw new IOException("Failed to write");
} catch(SerialPortException e) {
throw new IOException(e.toString());
}
}
}

View File

@@ -0,0 +1,6 @@
package net.sf.briar.plugins.modem;
interface SerialPortList {
String[] getPortNames();
}

View File

@@ -0,0 +1,8 @@
package net.sf.briar.plugins.modem;
class SerialPortListImpl implements SerialPortList {
public String[] getPortNames() {
return jssc.SerialPortList.getPortNames();
}
}