Use an Executor to decouple the callback from the caller.

This commit is contained in:
akwizgran
2011-10-05 17:22:21 +01:00
parent 8940dc83cb
commit af41e42c6c
3 changed files with 81 additions and 47 deletions

View File

@@ -6,6 +6,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.DbException;
@@ -23,6 +24,7 @@ import org.apache.commons.io.FileSystemUtils;
abstract class FilePlugin implements BatchTransportPlugin { abstract class FilePlugin implements BatchTransportPlugin {
private final ConnectionRecogniser recogniser; private final ConnectionRecogniser recogniser;
private final Executor executor;
protected Map<String, String> localProperties = null; protected Map<String, String> localProperties = null;
protected Map<ContactId, Map<String, String>> remoteProperties = null; protected Map<ContactId, Map<String, String>> remoteProperties = null;
@@ -34,8 +36,9 @@ abstract class FilePlugin implements BatchTransportPlugin {
protected abstract File chooseOutputDirectory(); protected abstract File chooseOutputDirectory();
protected abstract void writerFinished(File f); protected abstract void writerFinished(File f);
FilePlugin(ConnectionRecogniser recogniser) { FilePlugin(ConnectionRecogniser recogniser, Executor executor) {
this.recogniser = recogniser; this.recogniser = recogniser;
this.executor = executor;
} }
public synchronized void start(Map<String, String> localProperties, public synchronized void start(Map<String, String> localProperties,
@@ -117,42 +120,55 @@ abstract class FilePlugin implements BatchTransportPlugin {
return FileSystemUtils.freeSpaceKb(path) * 1024L; return FileSystemUtils.freeSpaceKb(path) * 1024L;
} }
protected void createReaderFromFile(File f) { protected void createReaderFromFile(final File f) {
if(!started) throw new IllegalStateException(); if(!started) throw new IllegalStateException();
if(!isPossibleConnectionFilename(f.getName())) return; executor.execute(new ReaderCreator(f));
if(f.length() < TransportConstants.MIN_CONNECTION_LENGTH) return;
try {
FileInputStream in = new FileInputStream(f);
byte[] iv = new byte[TransportConstants.IV_LENGTH];
int offset = 0;
while(offset < iv.length) {
int read = in.read(iv, offset, iv.length - offset);
if(read == -1) break;
offset += read;
}
if(offset < iv.length) {
// The file was truncated
in.close();
return;
}
ContactId c = recogniser.acceptConnection(iv);
if(c == null) {
// Nobody there
in.close();
return;
}
FileTransportReader reader = new FileTransportReader(f, in);
callback.readerCreated(c, iv, reader);
} catch(DbException e) {
// FIXME: At least log it
return;
} catch(IOException e) {
// FIXME: At least log it
return;
}
} }
protected boolean isPossibleConnectionFilename(String filename) { protected boolean isPossibleConnectionFilename(String filename) {
return filename.toLowerCase().matches("[a-z]{8}\\.dat"); return filename.toLowerCase().matches("[a-z]{8}\\.dat");
} }
private class ReaderCreator implements Runnable {
private final File f;
private ReaderCreator(File f) {
this.f = f;
}
public void run() {
if(!isPossibleConnectionFilename(f.getName())) return;
if(f.length() < TransportConstants.MIN_CONNECTION_LENGTH) return;
try {
FileInputStream in = new FileInputStream(f);
byte[] iv = new byte[TransportConstants.IV_LENGTH];
int offset = 0;
while(offset < iv.length) {
int read = in.read(iv, offset, iv.length - offset);
if(read == -1) break;
offset += read;
}
if(offset < iv.length) {
// The file was truncated
in.close();
return;
}
ContactId c = recogniser.acceptConnection(iv);
if(c == null) {
// Nobody there
in.close();
return;
}
FileTransportReader reader = new FileTransportReader(f, in);
callback.readerCreated(c, iv, reader);
} catch(DbException e) {
// FIXME: At least log it
return;
} catch(IOException e) {
// FIXME: At least log it
return;
}
}
}
} }

View File

@@ -4,6 +4,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor;
import net.sf.briar.api.ContactId; import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportId; import net.sf.briar.api.TransportId;
@@ -22,9 +23,9 @@ implements RemovableDriveMonitor.Callback {
private final RemovableDriveFinder finder; private final RemovableDriveFinder finder;
private final RemovableDriveMonitor monitor; private final RemovableDriveMonitor monitor;
RemovableDrivePlugin(ConnectionRecogniser recogniser, RemovableDrivePlugin(ConnectionRecogniser recogniser, Executor executor,
RemovableDriveFinder finder, RemovableDriveMonitor monitor) { RemovableDriveFinder finder, RemovableDriveMonitor monitor) {
super(recogniser); super(recogniser, executor);
this.finder = finder; this.finder = finder;
this.monitor = monitor; this.monitor = monitor;
} }

View File

@@ -6,6 +6,7 @@ import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.TestUtils; import net.sf.briar.TestUtils;
@@ -36,6 +37,7 @@ public class RemovableDrivePluginTest extends TestCase {
@Test @Test
public void testGetId() { public void testGetId() {
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final ConnectionRecogniser recogniser = final ConnectionRecogniser recogniser =
context.mock(ConnectionRecogniser.class); context.mock(ConnectionRecogniser.class);
final RemovableDriveFinder finder = final RemovableDriveFinder finder =
@@ -44,7 +46,7 @@ public class RemovableDrivePluginTest extends TestCase {
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); executor, finder, monitor);
assertEquals(RemovableDrivePlugin.TRANSPORT_ID, assertEquals(RemovableDrivePlugin.TRANSPORT_ID,
plugin.getId().getInt()); plugin.getId().getInt());
@@ -57,6 +59,7 @@ public class RemovableDrivePluginTest extends TestCase {
final List<File> drives = Collections.emptyList(); final List<File> drives = Collections.emptyList();
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final ConnectionRecogniser recogniser = final ConnectionRecogniser recogniser =
context.mock(ConnectionRecogniser.class); context.mock(ConnectionRecogniser.class);
final RemovableDriveFinder finder = final RemovableDriveFinder finder =
@@ -73,7 +76,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); executor, finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
assertNull(plugin.createWriter(contactId)); assertNull(plugin.createWriter(contactId));
@@ -90,6 +93,7 @@ public class RemovableDrivePluginTest extends TestCase {
drives.add(drive2); drives.add(drive2);
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final ConnectionRecogniser recogniser = final ConnectionRecogniser recogniser =
context.mock(ConnectionRecogniser.class); context.mock(ConnectionRecogniser.class);
final RemovableDriveFinder finder = final RemovableDriveFinder finder =
@@ -109,7 +113,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); executor, finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
assertNull(plugin.createWriter(contactId)); assertNull(plugin.createWriter(contactId));
@@ -128,6 +132,7 @@ public class RemovableDrivePluginTest extends TestCase {
drives.add(drive2); drives.add(drive2);
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final ConnectionRecogniser recogniser = final ConnectionRecogniser recogniser =
context.mock(ConnectionRecogniser.class); context.mock(ConnectionRecogniser.class);
final RemovableDriveFinder finder = final RemovableDriveFinder finder =
@@ -147,7 +152,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); executor, finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
assertNull(plugin.createWriter(contactId)); assertNull(plugin.createWriter(contactId));
@@ -168,6 +173,7 @@ public class RemovableDrivePluginTest extends TestCase {
assertTrue(drive1.createNewFile()); assertTrue(drive1.createNewFile());
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final ConnectionRecogniser recogniser = final ConnectionRecogniser recogniser =
context.mock(ConnectionRecogniser.class); context.mock(ConnectionRecogniser.class);
final RemovableDriveFinder finder = final RemovableDriveFinder finder =
@@ -187,7 +193,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); executor, finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
assertNull(plugin.createWriter(contactId)); assertNull(plugin.createWriter(contactId));
@@ -208,6 +214,7 @@ public class RemovableDrivePluginTest extends TestCase {
assertTrue(drive1.mkdir()); assertTrue(drive1.mkdir());
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final ConnectionRecogniser recogniser = final ConnectionRecogniser recogniser =
context.mock(ConnectionRecogniser.class); context.mock(ConnectionRecogniser.class);
final RemovableDriveFinder finder = final RemovableDriveFinder finder =
@@ -227,7 +234,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); executor, finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
assertNotNull(plugin.createWriter(contactId)); assertNotNull(plugin.createWriter(contactId));
@@ -251,6 +258,7 @@ public class RemovableDrivePluginTest extends TestCase {
assertTrue(drive1.mkdir()); assertTrue(drive1.mkdir());
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final ConnectionRecogniser recogniser = final ConnectionRecogniser recogniser =
context.mock(ConnectionRecogniser.class); context.mock(ConnectionRecogniser.class);
final RemovableDriveFinder finder = final RemovableDriveFinder finder =
@@ -271,7 +279,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); executor, finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
BatchTransportWriter writer = plugin.createWriter(contactId); BatchTransportWriter writer = plugin.createWriter(contactId);
@@ -299,6 +307,7 @@ public class RemovableDrivePluginTest extends TestCase {
@Test @Test
public void testEmptyDriveIsIgnored() throws Exception { public void testEmptyDriveIsIgnored() throws Exception {
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final ConnectionRecogniser recogniser = final ConnectionRecogniser recogniser =
context.mock(ConnectionRecogniser.class); context.mock(ConnectionRecogniser.class);
final RemovableDriveFinder finder = final RemovableDriveFinder finder =
@@ -313,7 +322,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); executor, finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
plugin.driveInserted(testDir); plugin.driveInserted(testDir);
@@ -324,6 +333,7 @@ public class RemovableDrivePluginTest extends TestCase {
@Test @Test
public void testFilenames() { public void testFilenames() {
Mockery context = new Mockery(); Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final ConnectionRecogniser recogniser = final ConnectionRecogniser recogniser =
context.mock(ConnectionRecogniser.class); context.mock(ConnectionRecogniser.class);
final RemovableDriveFinder finder = final RemovableDriveFinder finder =
@@ -332,7 +342,7 @@ public class RemovableDrivePluginTest extends TestCase {
context.mock(RemovableDriveMonitor.class); context.mock(RemovableDriveMonitor.class);
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); executor, finder, monitor);
assertFalse(plugin.isPossibleConnectionFilename("abcdefg.dat")); assertFalse(plugin.isPossibleConnectionFilename("abcdefg.dat"));
assertFalse(plugin.isPossibleConnectionFilename("abcdefghi.dat")); assertFalse(plugin.isPossibleConnectionFilename("abcdefghi.dat"));
@@ -361,7 +371,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); new ImmediateExecutor(), finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
File f = new File(testDir, "abcdefgh.dat"); File f = new File(testDir, "abcdefgh.dat");
@@ -394,7 +404,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); new ImmediateExecutor(), finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
File f = new File(testDir, "abcdefgh.dat"); File f = new File(testDir, "abcdefgh.dat");
@@ -430,7 +440,7 @@ public class RemovableDrivePluginTest extends TestCase {
}}); }});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser, RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
finder, monitor); new ImmediateExecutor(), finder, monitor);
plugin.start(null, null, null, callback); plugin.start(null, null, null, callback);
File f = new File(testDir, "abcdefgh.dat"); File f = new File(testDir, "abcdefgh.dat");
@@ -448,4 +458,11 @@ public class RemovableDrivePluginTest extends TestCase {
public void tearDown() { public void tearDown() {
TestUtils.deleteTestDirectory(testDir); TestUtils.deleteTestDirectory(testDir);
} }
private static class ImmediateExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
} }