summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Clayton <alex.clayton@isode.com>2016-03-16 13:48:37 (GMT)
committerAlex Clayton <alex.clayton@isode.com>2016-03-16 14:05:38 (GMT)
commit8b9891afc85d114ff1e9c9a0291a4aaee8baeb09 (patch)
tree5027dc69d6ca785e0ed94aebc7232b3790b51464
parent892af8539f2b46e840d7344489529259d1df03b9 (diff)
downloadstroke-8b9891afc85d114ff1e9c9a0291a4aaee8baeb09.zip
stroke-8b9891afc85d114ff1e9c9a0291a4aaee8baeb09.tar.bz2
Add FileWriteBytestream class and test.
Adds a FileWriteBytestream class plus a test for it. These had been missed out previously. Also as per patch 'Fix crash when saving a received file to non-writable location' changed WriteBytestream.write() method to return a boolean indicating success or failure. Test-information: Tests pass ok. Change-Id: I0c3676db8b67573142e8628f439cecf54f3f8f1a
-rw-r--r--src/com/isode/stroke/filetransfer/ByteArrayWriteBytestream.java6
-rw-r--r--src/com/isode/stroke/filetransfer/FileTransferError.java3
-rw-r--r--src/com/isode/stroke/filetransfer/FileWriteBytestream.java73
-rw-r--r--src/com/isode/stroke/filetransfer/SOCKS5BytestreamClientSession.java1
-rw-r--r--src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerSession.java27
-rw-r--r--src/com/isode/stroke/filetransfer/WriteBytestream.java11
-rw-r--r--test/com/isode/stroke/filetransfer/FileWriteBytestreamTest.java83
7 files changed, 185 insertions, 19 deletions
diff --git a/src/com/isode/stroke/filetransfer/ByteArrayWriteBytestream.java b/src/com/isode/stroke/filetransfer/ByteArrayWriteBytestream.java
index eb3a30f..d983e89 100644
--- a/src/com/isode/stroke/filetransfer/ByteArrayWriteBytestream.java
+++ b/src/com/isode/stroke/filetransfer/ByteArrayWriteBytestream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2015 Isode Limited.
+ * Copyright (c) 2010-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -20,9 +20,11 @@ public class ByteArrayWriteBytestream extends WriteBytestream {
public ByteArrayWriteBytestream() {
}
- public void write(final ByteArray bytes) {
+ @Override
+ public boolean write(final ByteArray bytes) {
data.append(bytes);
onWrite.emit(bytes);
+ return true;
}
public ByteArray getData() {
diff --git a/src/com/isode/stroke/filetransfer/FileTransferError.java b/src/com/isode/stroke/filetransfer/FileTransferError.java
index ac135d6..fbb5ec6 100644
--- a/src/com/isode/stroke/filetransfer/FileTransferError.java
+++ b/src/com/isode/stroke/filetransfer/FileTransferError.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2015 Isode Limited.
+ * Copyright (c) 2010-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -19,6 +19,7 @@ public class FileTransferError {
UnknownError,
PeerError,
ReadError,
+ WriteError,
ClosedError
};
diff --git a/src/com/isode/stroke/filetransfer/FileWriteBytestream.java b/src/com/isode/stroke/filetransfer/FileWriteBytestream.java
new file mode 100644
index 0000000..7fa068d
--- /dev/null
+++ b/src/com/isode/stroke/filetransfer/FileWriteBytestream.java
@@ -0,0 +1,73 @@
+/* Copyright (c) 2016, Isode Limited, London, England.
+ * All rights reserved.
+ *
+ * Acquisition and use of this software and related materials for any
+ * purpose requires a written license agreement from Isode Limited,
+ * or a written license from an organisation licensed by Isode Limited
+ * to grant such a license.
+ *
+ */
+package com.isode.stroke.filetransfer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import com.isode.stroke.base.ByteArray;
+
+public class FileWriteBytestream extends WriteBytestream {
+
+ private final String filePath_;
+
+ private FileOutputStream stream_ = null;
+
+ public FileWriteBytestream(String filePath) {
+ filePath_ = filePath;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ }
+ finally {
+ super.finalize();
+ }
+ }
+
+ @Override
+ public boolean write(ByteArray data) {
+ if (data.isEmpty()) {
+ return true;
+ }
+ if (stream_ == null) {
+ try {
+ stream_ = new FileOutputStream(filePath_);
+ } catch (FileNotFoundException e) {
+ return false;
+ }
+ }
+ try {
+ stream_.write(data.getData());
+ stream_.flush();
+ } catch (IOException e) {
+ return false;
+ }
+ onWrite.emit(data);
+ return true;
+ }
+
+ public void close() {
+ if (stream_ != null) {
+ try {
+ stream_.close();
+ } catch (IOException e) {
+ // Ignore exception
+ }
+ stream_ = null;
+ }
+ }
+
+
+}
diff --git a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamClientSession.java b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamClientSession.java
index 18e4484..982e3e9 100644
--- a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamClientSession.java
+++ b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamClientSession.java
@@ -116,7 +116,6 @@ public class SOCKS5BytestreamClientSession extends SOCKS5AbstractBytestreamSessi
state = State.Reading;
writeBytestream = writeStream;
writeBytestream.write(unprocessedData);
- //onBytesReceived(unprocessedData.size());
unprocessedData.clear();
} else {
logger_.fine("Session isn't ready for transfer yet!\n");
diff --git a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerSession.java b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerSession.java
index 8facca0..f9c1f95 100644
--- a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerSession.java
+++ b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerSession.java
@@ -82,7 +82,7 @@ public class SOCKS5BytestreamServerSession extends SOCKS5AbstractBytestreamSess
}
public void stop() {
- finish(false);
+ finish();
}
public void startSending(ReadBytestream stream) {
@@ -124,8 +124,12 @@ public class SOCKS5BytestreamServerSession extends SOCKS5AbstractBytestreamSess
return streamID;
}
- private void finish(boolean error) {
- logger_.fine(error + " " + state + "\n");
+ private void finish() {
+ finish(null);
+ }
+
+ private void finish(FileTransferError error) {
+ logger_.fine("state: " + state + "\n");
if (State.Finished.equals(state)) {
return;
}
@@ -140,11 +144,7 @@ public class SOCKS5BytestreamServerSession extends SOCKS5AbstractBytestreamSess
}
readBytestream = null;
state = State.Finished;
- if (error) {
- onFinished.emit(new FileTransferError(FileTransferError.Type.PeerError));
- } else {
- onFinished.emit(null);
- }
+ onFinished.emit(error);
}
private void process() {
@@ -193,7 +193,7 @@ public class SOCKS5BytestreamServerSession extends SOCKS5AbstractBytestreamSess
if (!hasBytestream) {
logger_.fine("Readstream or Wrtiestream with ID " + streamID + " not found!\n");
connection.write(result);
- finish(true);
+ finish(new FileTransferError(FileTransferError.Type.PeerError));
}
else {
logger_.fine("Found stream. Sent OK.\n");
@@ -210,14 +210,15 @@ public class SOCKS5BytestreamServerSession extends SOCKS5AbstractBytestreamSess
unprocessedData.append(data);
process();
} else {
- writeBytestream.write(new ByteArray(data));
- // onBytesReceived(data.size());
+ if (!writeBytestream.write(new ByteArray(data))) {
+ finish(new FileTransferError(FileTransferError.Type.WriteError));
+ }
}
}
private void handleDisconnected(final Connection.Error error) {
logger_.fine((error != null ? (error.equals(Connection.Error.ReadError) ? "Read Error" : "Write Error") : "No Error") + "\n");
- finish(error != null ? true : false);
+ finish(error != null ? new FileTransferError(FileTransferError.Type.PeerError) : null);
}
private void handleDataAvailable() {
@@ -244,7 +245,7 @@ public class SOCKS5BytestreamServerSession extends SOCKS5AbstractBytestreamSess
//}
}
else {
- finish(false);
+ finish();
}
}
} \ No newline at end of file
diff --git a/src/com/isode/stroke/filetransfer/WriteBytestream.java b/src/com/isode/stroke/filetransfer/WriteBytestream.java
index c243bdc..81d2093 100644
--- a/src/com/isode/stroke/filetransfer/WriteBytestream.java
+++ b/src/com/isode/stroke/filetransfer/WriteBytestream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -16,7 +16,14 @@ import com.isode.stroke.signals.Signal1;
public abstract class WriteBytestream {
- public abstract void write(final ByteArray b);
+ /**
+ * Write data from a {@link ByteArray} to the bytestream. On
+ * success {@code true} is returned and {@link #onWrite} is called.
+ * On failure {@code false} is returned.
+ * @param b The {@link ByteArray} to write.
+ * @return {@code true} on success, {@code false} on failure.
+ */
+ public abstract boolean write(final ByteArray b);
public final Signal1<ByteArray> onWrite = new Signal1<ByteArray>();
} \ No newline at end of file
diff --git a/test/com/isode/stroke/filetransfer/FileWriteBytestreamTest.java b/test/com/isode/stroke/filetransfer/FileWriteBytestreamTest.java
new file mode 100644
index 0000000..3e06646
--- /dev/null
+++ b/test/com/isode/stroke/filetransfer/FileWriteBytestreamTest.java
@@ -0,0 +1,83 @@
+/* Copyright (c) 2016, Isode Limited, London, England.
+ * All rights reserved.
+ *
+ * Acquisition and use of this software and related materials for any
+ * purpose requires a written license agreement from Isode Limited,
+ * or a written license from an organisation licensed by Isode Limited
+ * to grant such a license.
+ *
+ */
+package com.isode.stroke.filetransfer;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.isode.stroke.base.ByteArray;
+import com.isode.stroke.signals.Slot1;
+
+/**
+ * Tests for {@link FileWriteBytestream}
+ *
+ */
+public class FileWriteBytestreamTest {
+
+ private boolean onWriteWasCalled = false;
+
+ @Test
+ public void testSuccessfulWrite() {
+ File tempfile = null;
+ String filename = null;
+ try {
+ try {
+ tempfile = File.createTempFile("write_file_bytestream_test_", ".tmp");
+ filename = tempfile.getAbsolutePath();
+ } catch (IOException e) {
+ // Unable to create file exit test
+ return;
+ }
+ WriteBytestream writeBytestream = new FileWriteBytestream(filename);
+ writeBytestream.onWrite.connect(new Slot1<ByteArray>() {
+
+ @Override
+ public void call(ByteArray data) {
+ handleOnWrite(data);
+ }
+
+ });
+
+ assertTrue(writeBytestream.write(new ByteArray("Some data.")));
+ assertTrue(onWriteWasCalled);
+ }
+ finally {
+ if (tempfile != null && tempfile.exists()) {
+ tempfile.delete();
+ }
+ }
+ }
+
+ @Test
+ public void testFailingWrite() {
+ WriteBytestream writeBytestream = new FileWriteBytestream("");
+ writeBytestream.onWrite.connect(new Slot1<ByteArray>() {
+
+ @Override
+ public void call(ByteArray data) {
+ handleOnWrite(data);
+ }
+
+ });
+
+ assertFalse(writeBytestream.write(new ByteArray("Some data.")));
+ assertFalse(onWriteWasCalled);
+ }
+
+ private void handleOnWrite(ByteArray data) {
+ onWriteWasCalled = true;
+ }
+
+}