diff --git a/components/net/sf/briar/plugins/file/FilePlugin.java b/components/net/sf/briar/plugins/file/FilePlugin.java
index ea8c9200fe1f97ae5052e2443c8597f5ec843819..f16796ace793ad65d571e00f42aed272c3fc34e3 100644
--- a/components/net/sf/briar/plugins/file/FilePlugin.java
+++ b/components/net/sf/briar/plugins/file/FilePlugin.java
@@ -5,7 +5,10 @@ import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.ContactId;
@@ -44,9 +47,18 @@ abstract class FilePlugin implements BatchTransportPlugin {
 	throws InvalidPropertiesException, InvalidConfigException, IOException {
 		if(started) throw new IllegalStateException();
 		started = true;
-		this.localProperties = localProperties;
-		this.remoteProperties = remoteProperties;
-		this.config = config;
+		this.localProperties = Collections.unmodifiableMap(localProperties);
+		// Copy the remoteProperties map to make its values unmodifiable
+		// Copy the remoteProperties map to make its values unmodifiable
+		int size = remoteProperties.size();
+		Map<ContactId, Map<String, String>> m =
+			new HashMap<ContactId, Map<String, String>>(size);
+		for(Entry<ContactId, Map<String, String>> e
+				: remoteProperties.entrySet()) {
+			m.put(e.getKey(), Collections.unmodifiableMap(e.getValue()));
+		}
+		this.remoteProperties = m;
+		this.config = Collections.unmodifiableMap(config);
 		this.callback = callback;
 	}
 
@@ -58,20 +70,20 @@ abstract class FilePlugin implements BatchTransportPlugin {
 	public synchronized void setLocalProperties(Map<String, String> properties)
 	throws InvalidPropertiesException {
 		if(!started) throw new IllegalStateException();
-		localProperties = properties;
+		localProperties = Collections.unmodifiableMap(properties);
 	}
 
 	public synchronized void setRemoteProperties(ContactId c,
 			Map<String, String> properties)
 	throws InvalidPropertiesException {
 		if(!started) throw new IllegalStateException();
-		remoteProperties.put(c, properties);
+		remoteProperties.put(c, Collections.unmodifiableMap(properties));
 	}
 
 	public synchronized void setConfig(Map<String, String> config)
 	throws InvalidConfigException {
 		if(!started) throw new IllegalStateException();
-		this.config = config;
+		this.config = Collections.unmodifiableMap(config);
 	}
 
 	public BatchTransportReader createReader(ContactId c) {
@@ -105,8 +117,7 @@ abstract class FilePlugin implements BatchTransportPlugin {
 		return FileSystemUtils.freeSpaceKb(path) * 1024L;
 	}
 
-	// Package access for testing
-	void createReaderFromFile(final File f) {
+	protected void createReaderFromFile(final File f) {
 		if(!started) return;
 		executor.execute(new ReaderCreator(f));
 	}
diff --git a/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java b/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java
index 91035d63d22aa016a5b1261d024d4528863e01bd..9233c006b9de78383ddbd09f68374d9b92debad6 100644
--- a/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java
+++ b/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java
@@ -6,6 +6,7 @@ import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketAddress;
 import java.util.Map;
+import java.util.TreeMap;
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.ContactId;
@@ -59,9 +60,10 @@ public class SimpleSocketPlugin extends SocketPlugin {
 		String host = i.getAddress().getHostAddress();
 		String port = String.valueOf(i.getPort());
 		// FIXME: Special handling for private IP addresses?
-		localProperties.put("host", host);
-		localProperties.put("port", port);
-		callback.setLocalProperties(localProperties);
+		Map<String, String> m = new TreeMap<String, String>(localProperties);
+		m.put("host", host);
+		m.put("port", port);
+		callback.setLocalProperties(m);
 	}
 
 	private SocketAddress createSocketAddress(Map<String, String> properties) {
diff --git a/components/net/sf/briar/plugins/socket/SocketPlugin.java b/components/net/sf/briar/plugins/socket/SocketPlugin.java
index 700f63734eb932004817a4a9feb959630fd173c0..fadd7c41cf2ab00d0da1e38fba017309ae2c240a 100644
--- a/components/net/sf/briar/plugins/socket/SocketPlugin.java
+++ b/components/net/sf/briar/plugins/socket/SocketPlugin.java
@@ -4,7 +4,10 @@ import java.io.IOException;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketAddress;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.concurrent.Executor;
 
 import net.sf.briar.api.ContactId;
@@ -43,9 +46,17 @@ abstract class SocketPlugin implements StreamTransportPlugin {
 	throws InvalidPropertiesException, InvalidConfigException {
 		if(started) throw new IllegalStateException();
 		started = true;
-		this.localProperties = localProperties;
-		this.remoteProperties = remoteProperties;
-		this.config = config;
+		this.localProperties = Collections.unmodifiableMap(localProperties);
+		// Copy the remoteProperties map to make its values unmodifiable
+		int size = remoteProperties.size();
+		Map<ContactId, Map<String, String>> m =
+			new HashMap<ContactId, Map<String, String>>(size);
+		for(Entry<ContactId, Map<String, String>> e
+				: remoteProperties.entrySet()) {
+			m.put(e.getKey(), Collections.unmodifiableMap(e.getValue()));
+		}
+		this.remoteProperties = m;
+		this.config = Collections.unmodifiableMap(config);
 		this.callback = callback;
 		executor.execute(createBinder());
 	}
@@ -129,7 +140,7 @@ abstract class SocketPlugin implements StreamTransportPlugin {
 	public synchronized void setLocalProperties(Map<String, String> properties)
 	throws InvalidPropertiesException {
 		if(!started) throw new IllegalStateException();
-		localProperties = properties;
+		localProperties = Collections.unmodifiableMap(properties);
 		// Close and reopen the socket if its address has changed
 		if(socket != null) {
 			SocketAddress addr = socket.getLocalSocketAddress();
@@ -148,13 +159,13 @@ abstract class SocketPlugin implements StreamTransportPlugin {
 			Map<String, String> properties)
 	throws InvalidPropertiesException {
 		if(!started) throw new IllegalStateException();
-		remoteProperties.put(c, properties);
+		remoteProperties.put(c, Collections.unmodifiableMap(properties));
 	}
 
 	public synchronized void setConfig(Map<String, String> config)
 	throws InvalidConfigException {
 		if(!started) throw new IllegalStateException();
-		this.config = config;
+		this.config = Collections.unmodifiableMap(config);
 	}
 
 	public synchronized void poll() {
diff --git a/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java b/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
index fa8a93046ebf8e413d0b278c3f064e08ecb4bea5..4c942a4a1be0705ba4584302671c30669f3fb220 100644
--- a/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
+++ b/test/net/sf/briar/plugins/file/RemovableDrivePluginTest.java
@@ -5,7 +5,10 @@ import java.io.FileOutputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
 import java.util.concurrent.Executor;
 
 import junit.framework.TestCase;
@@ -27,8 +30,16 @@ public class RemovableDrivePluginTest extends TestCase {
 	private final File testDir = TestUtils.getTestDirectory();
 	private final ContactId contactId = new ContactId(0);
 
+	private Map<String, String> localProperties = null;
+	private Map<ContactId, Map<String, String>> remoteProperties = null;
+	private Map<String, String> config = null;
+
 	@Before
 	public void setUp() {
+		localProperties = new TreeMap<String, String>();
+		remoteProperties = new HashMap<ContactId, Map<String, String>>();
+		remoteProperties.put(contactId, new TreeMap<String, String>());
+		config = new TreeMap<String, String>();
 		testDir.mkdirs();
 	}
 
@@ -71,7 +82,7 @@ public class RemovableDrivePluginTest extends TestCase {
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
 				finder, monitor);
-		plugin.start(null, null, null, callback);
+		plugin.start(localProperties, remoteProperties, config, callback);
 
 		assertNull(plugin.createWriter(contactId));
 
@@ -106,7 +117,7 @@ public class RemovableDrivePluginTest extends TestCase {
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
 				finder, monitor);
-		plugin.start(null, null, null, callback);
+		plugin.start(localProperties, remoteProperties, config, callback);
 
 		assertNull(plugin.createWriter(contactId));
 		File[] files = drive1.listFiles();
@@ -143,7 +154,7 @@ public class RemovableDrivePluginTest extends TestCase {
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
 				finder, monitor);
-		plugin.start(null, null, null, callback);
+		plugin.start(localProperties, remoteProperties, config, callback);
 
 		assertNull(plugin.createWriter(contactId));
 		File[] files = drive1.listFiles();
@@ -182,7 +193,7 @@ public class RemovableDrivePluginTest extends TestCase {
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
 				finder, monitor);
-		plugin.start(null, null, null, callback);
+		plugin.start(localProperties, remoteProperties, config, callback);
 
 		assertNull(plugin.createWriter(contactId));
 		File[] files = drive1.listFiles();
@@ -221,7 +232,7 @@ public class RemovableDrivePluginTest extends TestCase {
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
 				finder, monitor);
-		plugin.start(null, null, null, callback);
+		plugin.start(localProperties, remoteProperties, config, callback);
 
 		assertNotNull(plugin.createWriter(contactId));
 		// The output file should exist and should be empty
@@ -264,7 +275,7 @@ public class RemovableDrivePluginTest extends TestCase {
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
 				finder, monitor);
-		plugin.start(null, null, null, callback);
+		plugin.start(localProperties, remoteProperties, config, callback);
 
 		BatchTransportWriter writer = plugin.createWriter(contactId);
 		assertNotNull(writer);
@@ -305,7 +316,7 @@ public class RemovableDrivePluginTest extends TestCase {
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
 				finder, monitor);
-		plugin.start(null, null, null, callback);
+		plugin.start(localProperties, remoteProperties, config, callback);
 
 		plugin.driveInserted(testDir);
 
@@ -350,7 +361,7 @@ public class RemovableDrivePluginTest extends TestCase {
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(
 				new ImmediateExecutor(), finder, monitor);
-		plugin.start(null, null, null, callback);
+		plugin.start(localProperties, remoteProperties, config, callback);
 
 		File f = new File(testDir, "abcdefgh.dat");
 		OutputStream out = new FileOutputStream(f);
@@ -380,7 +391,7 @@ public class RemovableDrivePluginTest extends TestCase {
 
 		RemovableDrivePlugin plugin = new RemovableDrivePlugin(
 				new ImmediateExecutor(), finder, monitor);
-		plugin.start(null, null, null, callback);
+		plugin.start(localProperties, remoteProperties, config, callback);
 
 		File f = new File(testDir, "abcdefgh.dat");
 		OutputStream out = new FileOutputStream(f);