+++ Support GVFS URIs as valid DnD files by translating the URI to the .gvfs mountpoint filepath

This commit is contained in:
Reinhard Pointner 2012-11-24 00:00:03 +00:00
parent 42c6a3703f
commit 879deaa643
3 changed files with 119 additions and 42 deletions

View File

@ -0,0 +1,31 @@
package net.sourceforge.filebot.gio;
import static java.util.Collections.*;
import java.lang.reflect.Method;
import com.sun.jna.FunctionMapper;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
interface GIOLibrary extends Library {
GIOLibrary INSTANCE = (GIOLibrary) Native.loadLibrary("gio-2.0",
GIOLibrary.class);
void g_type_init();
Pointer g_vfs_get_default();
Pointer g_vfs_get_file_for_uri(Pointer gvfs, String uri);
Pointer g_file_get_path(Pointer gfile);
void g_free(Pointer gpointer);
void g_object_unref(Pointer gobject);
}

View File

@ -0,0 +1,41 @@
package net.sourceforge.filebot.gio;
import java.io.File;
import java.net.URI;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public class GVFS {
private static Pointer gvfs;
private synchronized static Pointer getDefaultVFS() {
if (gvfs == null) {
GIOLibrary.INSTANCE.g_type_init();
gvfs = GIOLibrary.INSTANCE.g_vfs_get_default();
}
return gvfs;
}
public static File getPathForURI(URI uri) {
Pointer gfile = GIOLibrary.INSTANCE.g_vfs_get_file_for_uri(
getDefaultVFS(), uri.toString());
Pointer chars = GIOLibrary.INSTANCE.g_file_get_path(gfile);
try {
if (chars != null)
return new File(chars.getString(0));
else
return null;
} finally {
GIOLibrary.INSTANCE.g_object_unref(gfile);
GIOLibrary.INSTANCE.g_free(chars);
}
}
public static boolean isSupported() {
return Platform.isLinux() || Platform.isFreeBSD();
}
}

View File

@ -1,7 +1,5 @@
package net.sourceforge.filebot.ui.transfer;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
@ -18,11 +16,11 @@ import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.filebot.gio.GVFS;
public class FileTransferable implements Transferable {
public static final DataFlavor uriListFlavor = createUriListFlavor();
private static DataFlavor createUriListFlavor() {
try {
@ -32,23 +30,20 @@ public class FileTransferable implements Transferable {
throw new RuntimeException(e);
}
}
private final File[] files;
public FileTransferable(File... files) {
this.files = files;
}
public FileTransferable(Collection<File> files) {
this.files = files.toArray(new File[0]);
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException {
if (flavor.isFlavorJavaFileListType())
return Arrays.asList(files);
else if (flavor.equals(uriListFlavor))
@ -56,83 +51,93 @@ public class FileTransferable implements Transferable {
else
throw new UnsupportedFlavorException(flavor);
}
/**
* @return line separated list of file URIs
*/
private String getUriList() {
StringBuilder sb = new StringBuilder(80 * files.length);
for (File file : files) {
// use URI encoded path
sb.append("file://").append(file.toURI().getRawPath());
sb.append("\r\n");
}
return sb.toString();
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] { DataFlavor.javaFileListFlavor, uriListFlavor };
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return isFileListFlavor(flavor);
}
public static boolean isFileListFlavor(DataFlavor flavor) {
return flavor.isFlavorJavaFileListType() || flavor.equals(uriListFlavor);
return flavor.isFlavorJavaFileListType()
|| flavor.equals(uriListFlavor);
}
public static boolean hasFileListFlavor(Transferable tr) {
return tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor) || tr.isDataFlavorSupported(FileTransferable.uriListFlavor);
return tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
|| tr.isDataFlavorSupported(FileTransferable.uriListFlavor);
}
@SuppressWarnings("unchecked")
public static List<File> getFilesFromTransferable(Transferable tr) throws IOException, UnsupportedFlavorException {
if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
// file list flavor
return (List<File>) tr.getTransferData(DataFlavor.javaFileListFlavor);
} else if (tr.isDataFlavorSupported(FileTransferable.uriListFlavor)) {
// file URI list flavor
Readable transferData = (Readable) tr.getTransferData(FileTransferable.uriListFlavor);
public static List<File> getFilesFromTransferable(Transferable tr)
throws IOException, UnsupportedFlavorException {
if (tr.isDataFlavorSupported(FileTransferable.uriListFlavor)) {
// file URI list flavor (Linux)
Readable transferData = (Readable) tr
.getTransferData(FileTransferable.uriListFlavor);
Scanner scanner = new Scanner(transferData);
List<File> files = new ArrayList<File>();
while (scanner.hasNextLine()) {
String uri = scanner.nextLine();
if (uri.startsWith("#")) {
String line = scanner.nextLine();
if (line.startsWith("#")) {
// the line is a comment (as per RFC 2483)
continue;
}
try {
File file = new File(new URI(uri));
if (!file.exists())
URI uri = new URI(line);
File file = null;
try {
// file URIs
file = new File(uri);
} catch (IllegalArgumentException e) {
// try handle other GVFS URI schemes
if (GVFS.isSupported()) {
file = GVFS.getPathForURI(uri);
}
}
if (!file.exists()) {
throw new FileNotFoundException(file.toString());
}
files.add(file);
} catch (Exception e) {
// URISyntaxException, IllegalArgumentException, FileNotFoundException
Logger.getLogger(FileTransferable.class.getName()).log(Level.WARNING, "Invalid file uri: " + uri);
// URISyntaxException, IllegalArgumentException,
// FileNotFoundException
Logger.getLogger(FileTransferable.class.getName()).log(
Level.WARNING, "Invalid file uri: " + line);
}
return files;
}
return files;
} else if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
// file list flavor
return (List<File>) tr
.getTransferData(DataFlavor.javaFileListFlavor);
}
// cannot get files from transferable
throw new UnsupportedFlavorException(null);
}