mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Removable drive finders for Windows, Mac and Linux (untested).
This commit is contained in:
121
components/net/sf/briar/plugins/file/FilePlugin.java
Normal file
121
components/net/sf/briar/plugins/file/FilePlugin.java
Normal file
@@ -0,0 +1,121 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.FileSystemUtils;
|
||||
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.TransportId;
|
||||
import net.sf.briar.api.transport.InvalidConfigException;
|
||||
import net.sf.briar.api.transport.InvalidTransportException;
|
||||
import net.sf.briar.api.transport.TransportConstants;
|
||||
import net.sf.briar.api.transport.batch.BatchTransportCallback;
|
||||
import net.sf.briar.api.transport.batch.BatchTransportPlugin;
|
||||
import net.sf.briar.api.transport.batch.BatchTransportReader;
|
||||
import net.sf.briar.api.transport.batch.BatchTransportWriter;
|
||||
|
||||
abstract class FilePlugin implements BatchTransportPlugin {
|
||||
|
||||
public static final int TRANSPORT_ID = 0;
|
||||
|
||||
private static final TransportId id = new TransportId(TRANSPORT_ID);
|
||||
|
||||
private boolean started = false;
|
||||
protected Map<String, String> localProperties = null;
|
||||
protected Map<ContactId, Map<String, String>> remoteProperties = null;
|
||||
protected Map<String, String> config = null;
|
||||
protected BatchTransportCallback callback = null;
|
||||
|
||||
protected abstract File chooseOutputDirectory();
|
||||
protected abstract void writerFinished(File f);
|
||||
|
||||
public TransportId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public synchronized void start(Map<String, String> localProperties,
|
||||
Map<ContactId, Map<String, String>> remoteProperties,
|
||||
Map<String, String> config, BatchTransportCallback callback)
|
||||
throws InvalidTransportException, InvalidConfigException {
|
||||
if(started) throw new IllegalStateException();
|
||||
started = true;
|
||||
this.localProperties = localProperties;
|
||||
this.remoteProperties = remoteProperties;
|
||||
this.config = config;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
if(!started) throw new IllegalStateException();
|
||||
started = false;
|
||||
}
|
||||
|
||||
public synchronized void setLocalProperties(Map<String, String> properties)
|
||||
throws InvalidTransportException {
|
||||
if(!started) throw new IllegalStateException();
|
||||
localProperties = properties;
|
||||
}
|
||||
|
||||
public synchronized void setRemoteProperties(ContactId c,
|
||||
Map<String, String> properties)
|
||||
throws InvalidTransportException {
|
||||
if(!started) throw new IllegalStateException();
|
||||
remoteProperties.put(c, properties);
|
||||
}
|
||||
|
||||
public synchronized void setConfig(Map<String, String> config)
|
||||
throws InvalidConfigException {
|
||||
if(!started) throw new IllegalStateException();
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public boolean shouldPoll() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getPollingInterval() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void poll() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public BatchTransportReader createReader(ContactId c) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public BatchTransportWriter createWriter(ContactId c) {
|
||||
if(!started) throw new IllegalStateException();
|
||||
File dir = chooseOutputDirectory();
|
||||
if(dir == null) return null;
|
||||
if(!dir.exists()) return null;
|
||||
if(!dir.isDirectory()) return null;
|
||||
File f = new File(dir, createFilename());
|
||||
try {
|
||||
long capacity = getCapacity(f.getAbsolutePath());
|
||||
if(capacity < TransportConstants.MIN_CONNECTION_LENGTH) return null;
|
||||
OutputStream out = new FileOutputStream(f);
|
||||
return new FileTransportWriter(f, out, capacity, this);
|
||||
} catch(IOException e) {
|
||||
f.delete();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected String createFilename() {
|
||||
StringBuilder s = new StringBuilder(12);
|
||||
for(int i = 0; i < 8; i++) s.append((char) ('a' + Math.random() * 26));
|
||||
s.append(".dat");
|
||||
System.out.println(s);
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
protected long getCapacity(String path) throws IOException {
|
||||
return FileSystemUtils.freeSpaceKb(path) * 1024L;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import net.sf.briar.api.transport.batch.BatchTransportWriter;
|
||||
|
||||
class FileTransportWriter implements BatchTransportWriter {
|
||||
|
||||
private final File file;
|
||||
private final OutputStream out;
|
||||
private final long capacity;
|
||||
private final FilePlugin plugin;
|
||||
|
||||
private boolean streamInUse = false;
|
||||
|
||||
FileTransportWriter(File file, OutputStream out, long capacity,
|
||||
FilePlugin plugin) {
|
||||
this.file = file;
|
||||
this.out = out;
|
||||
this.capacity = capacity;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public long getCapacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
streamInUse = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
streamInUse = false;
|
||||
plugin.writerFinished(file);
|
||||
}
|
||||
|
||||
public void dispose() throws IOException {
|
||||
if(streamInUse) out.close();
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
class LinuxRemovableDriveFinder extends UnixRemovableDriveFinder {
|
||||
|
||||
@Override
|
||||
protected String getMountCommand() {
|
||||
return "/bin/mount";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String parseMountPoint(String line) {
|
||||
// The format is "/dev/foo on /bar/baz type bam (opt1,opt2)"
|
||||
line = line.replaceFirst("^/dev/[^ ]+ on ", "");
|
||||
return line.replaceFirst(" type [^ ]+ \\([^)]+\\)$", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRemovableDriveMountPoint(String path) {
|
||||
return path.startsWith("/mnt/") || path.startsWith("/media/");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
class MacRemovableDriveFinder extends UnixRemovableDriveFinder {
|
||||
|
||||
@Override
|
||||
protected String getMountCommand() {
|
||||
return "/sbin/mount";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String parseMountPoint(String line) {
|
||||
// The format is "/dev/foo on /bar/baz (opt1, opt2)"
|
||||
line = line.replaceFirst("^/dev/[^ ]+ on ", "");
|
||||
return line.replaceFirst(" \\([^)]+\\)$", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isRemovableDriveMountPoint(String path) {
|
||||
return path.startsWith("/Volumes/");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
interface RemovableDriveFinder {
|
||||
|
||||
List<File> findRemovableDrives() throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.briar.util.OsUtils;
|
||||
|
||||
class RemovableDriveFinderImpl implements RemovableDriveFinder {
|
||||
|
||||
private final LinuxRemovableDriveFinder linux =
|
||||
new LinuxRemovableDriveFinder();
|
||||
private final MacRemovableDriveFinder mac =
|
||||
new MacRemovableDriveFinder();
|
||||
private final WindowsRemovableDriveFinder windows =
|
||||
new WindowsRemovableDriveFinder();
|
||||
|
||||
public List<File> findRemovableDrives() throws IOException {
|
||||
if(OsUtils.isLinux()) return linux.findRemovableDrives();
|
||||
else if(OsUtils.isMac()) return mac.findRemovableDrives();
|
||||
else if(OsUtils.isWindows()) return windows.findRemovableDrives();
|
||||
else return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
class RemovableDrivePlugin extends FilePlugin {
|
||||
|
||||
private final RemovableDriveFinder finder;
|
||||
|
||||
RemovableDrivePlugin(RemovableDriveFinder finder) {
|
||||
this.finder = finder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File chooseOutputDirectory() {
|
||||
try {
|
||||
List<File> drives = finder.findRemovableDrives();
|
||||
if(drives.isEmpty()) return null;
|
||||
String[] paths = new String[drives.size()];
|
||||
for(int i = 0; i < paths.length; i++) {
|
||||
paths[i] = drives.get(i).getAbsolutePath();
|
||||
}
|
||||
int i = callback.showChoice("REMOVABLE_DRIVE_CHOOSE_DRIVE", paths);
|
||||
if(i == -1) return null;
|
||||
return drives.get(i);
|
||||
} catch(IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writerFinished(File f) {
|
||||
callback.showMessage("REMOVABLE_DRIVE_WRITE_FINISHED");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
abstract class UnixRemovableDriveFinder implements RemovableDriveFinder {
|
||||
|
||||
protected abstract String getMountCommand();
|
||||
|
||||
protected abstract String parseMountPoint(String line);
|
||||
|
||||
protected abstract boolean isRemovableDriveMountPoint(String path);
|
||||
|
||||
public List<File> findRemovableDrives() throws IOException {
|
||||
List<File> drives = new ArrayList<File>();
|
||||
Process p = new ProcessBuilder(getMountCommand()).start();
|
||||
Scanner s = new Scanner(p.getInputStream(), "UTF-8");
|
||||
try {
|
||||
while(s.hasNextLine()) {
|
||||
String line = s.nextLine();
|
||||
String[] tokens = line.split(" ");
|
||||
if(tokens.length < 3) continue;
|
||||
// The general format is "/dev/foo on /bar/baz ..."
|
||||
if(tokens[0].startsWith("/dev/") && tokens[1].equals("on")) {
|
||||
// The path may contain spaces so we can't use tokens[2]
|
||||
String path = parseMountPoint(line);
|
||||
if(isRemovableDriveMountPoint(path)) {
|
||||
File f = new File(path);
|
||||
if(f.exists() && f.isDirectory()) drives.add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
s.close();
|
||||
}
|
||||
return drives;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.jna.platform.win32.Kernel32;
|
||||
|
||||
class WindowsRemovableDriveFinder implements RemovableDriveFinder {
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364939.aspx
|
||||
private static final int DRIVE_REMOVABLE = 2;
|
||||
|
||||
public List<File> findRemovableDrives() throws IOException {
|
||||
File[] roots = File.listRoots();
|
||||
if(roots == null) throw new IOException();
|
||||
List<File> drives = new ArrayList<File>();
|
||||
for(File root : roots) {
|
||||
try {
|
||||
int type = Kernel32.INSTANCE.GetDriveType(root.getPath());
|
||||
if(type == DRIVE_REMOVABLE) drives.add(root);
|
||||
} catch(RuntimeException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return drives;
|
||||
}
|
||||
|
||||
}
|
||||
29
test/net/sf/briar/plugins/file/TestFilePlugin.java
Normal file
29
test/net/sf/briar/plugins/file/TestFilePlugin.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package net.sf.briar.plugins.file;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class TestFilePlugin extends FilePlugin {
|
||||
|
||||
private final File outputDir;
|
||||
private final long capacity;
|
||||
|
||||
public TestFilePlugin(File outputDir, long capacity) {
|
||||
this.outputDir = outputDir;
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File chooseOutputDirectory() {
|
||||
return outputDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writerFinished(File f) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getCapacity(String path) {
|
||||
return capacity;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user