From 879deaa6437bcd6dc8a659e4f2c513b7b08a241a Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Sat, 24 Nov 2012 00:00:03 +0000 Subject: [PATCH] +++ Support GVFS URIs as valid DnD files by translating the URI to the .gvfs mountpoint filepath --- .../sourceforge/filebot/gio/GIOLibrary.java | 31 +++++++ source/net/sourceforge/filebot/gio/GVFS.java | 41 +++++++++ .../filebot/ui/transfer/FileTransferable.java | 89 ++++++++++--------- 3 files changed, 119 insertions(+), 42 deletions(-) create mode 100644 source/net/sourceforge/filebot/gio/GIOLibrary.java create mode 100644 source/net/sourceforge/filebot/gio/GVFS.java diff --git a/source/net/sourceforge/filebot/gio/GIOLibrary.java b/source/net/sourceforge/filebot/gio/GIOLibrary.java new file mode 100644 index 00000000..98afb4f0 --- /dev/null +++ b/source/net/sourceforge/filebot/gio/GIOLibrary.java @@ -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); + +} diff --git a/source/net/sourceforge/filebot/gio/GVFS.java b/source/net/sourceforge/filebot/gio/GVFS.java new file mode 100644 index 00000000..3a51515f --- /dev/null +++ b/source/net/sourceforge/filebot/gio/GVFS.java @@ -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(); + } + +} diff --git a/source/net/sourceforge/filebot/ui/transfer/FileTransferable.java b/source/net/sourceforge/filebot/ui/transfer/FileTransferable.java index a0941c1f..9613097e 100644 --- a/source/net/sourceforge/filebot/ui/transfer/FileTransferable.java +++ b/source/net/sourceforge/filebot/ui/transfer/FileTransferable.java @@ -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 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 getFilesFromTransferable(Transferable tr) throws IOException, UnsupportedFlavorException { - if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { - // file list flavor - return (List) tr.getTransferData(DataFlavor.javaFileListFlavor); - } else if (tr.isDataFlavorSupported(FileTransferable.uriListFlavor)) { - // file URI list flavor - Readable transferData = (Readable) tr.getTransferData(FileTransferable.uriListFlavor); - + public static List 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 files = new ArrayList(); - + 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) tr + .getTransferData(DataFlavor.javaFileListFlavor); } - + // cannot get files from transferable throw new UnsupportedFlavorException(null); }