Hi I attach a testcase for the bug. It's a simple application that open a window and writes de data droppped from a file-manager. With nautilus it works ok, but if you drop files from pcmanfm it throws a exception at the console.
I also attach a patch to openjdk, to ignore lines with only "null" character, and a isolated test of the fail point. the function called to parse the "drop data": List<File> fileList = (List<File>) tr.getTransferData(DataFlavor.javaFileListFlavor); Then, after some work, it goes to sun.awt.X11.XDataTransferer line ~287 while ((line = reader.readLine()) != null) { try { uri = new URI(line); // <-- fails here } catch (URISyntaxException uriSyntaxException) { throw new IOException(uriSyntaxException); } uriList.add(uri); } and fails because it tries to make a URI from '\0', I've send the patch upstream, but their bug tracking system it's not public by default. I'll update this bug when I've notice.
import java.awt.BorderLayout; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.io.File; import java.io.IOException; import java.util.List; import java.util.TooManyListenersException; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; public class FileDropTestCase extends JFrame implements DropTargetListener { private static final long serialVersionUID = 1L; private JTextArea text = null; public static void main(String[] args) throws TooManyListenersException { JFrame frame = new FileDropTestCase(); frame.setVisible(true); } public FileDropTestCase() throws TooManyListenersException { super(FileDropTestCase.class.getName()); text = new JTextArea(); this.getContentPane().add(new JScrollPane(text), BorderLayout.CENTER); this.setBounds(100, 100, 300, 400); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setUpDnd(); this.setVisible(true); } private void setUpDnd() throws TooManyListenersException { final java.awt.dnd.DropTarget dt = new java.awt.dnd.DropTarget(); dt.addDropTargetListener(this); new java.awt.dnd.DropTarget(text, this); } @Override public void dragEnter(DropTargetDragEvent dtde) {} @Override public void dragOver(DropTargetDragEvent dtde) {} @Override public void dropActionChanged(DropTargetDragEvent dtde) {} @Override public void dragExit(DropTargetEvent dte) {} @Override public void drop(DropTargetDropEvent evt) { java.awt.datatransfer.Transferable tr = evt.getTransferable(); if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { evt.acceptDrop(java.awt.dnd.DnDConstants.ACTION_COPY); try { // This call fails dropping files from pcmanfm. // it works fine with nautilus, and windows explorer. // other environment not tested List<File> fileList = (List<File>) tr.getTransferData(DataFlavor.javaFileListFlavor); for (File file : fileList) { text.append(file.getCanonicalPath() + "\n"); } } catch (UnsupportedFlavorException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } // Mark that drop is completed. evt.getDropTargetContext().dropComplete(true); } } }
import java.io.*; import java.net.*; import java.util.ArrayList; public class Test { public static void main(String[] args) throws IOException { /* * Real data from a debug session: * * file:///tmp/demo1.txt\nfile:///tmp/demo2.txt\n\0 */ byte[] bytes = { 102, 105, 108, 101, 58, 47, 47, 47, 116, 109, 112, 47, 100, 101, 109, 111, 49, 46, 116, 120, 116, 13, 10, 102, 105, 108, 101, 58, 47, 47, 47, 116, 109, 112, 47, 100, 101, 109, 111, 50, 46, 116, 120, 116, 13, 10, 0 }; URI[] list = simpleTestCaseFixed( new ByteArrayInputStream(bytes), bytes, "UTF-8" ); for (URI uri : list) { System.out.println(uri); } } /* * This function correspond with a fragment of sun.awt.X11.XDataTransferer.dragQueryURIs (~256) * It's modified to ignore lines containing only a string with null terminator char. * */ private static URI[] simpleTestCaseFixed(InputStream stream, byte[] bytes, String charset) throws IOException { BufferedReader reader = null; reader = new BufferedReader(new InputStreamReader(stream, charset)); String line; ArrayList<URI> uriList = new ArrayList<URI>(); while ((line = reader.readLine()) != null) { try { // Only take on care of not "empty" lines if (!"\0".equals(line)){ uriList.add(new URI(line)); } } catch (URISyntaxException uriSyntaxException) { throw new IOException(uriSyntaxException); } } return uriList.toArray(new URI[uriList.size()]); } /* * This function is a verbatim copy of fragment of sun.awt.X11.XDataTransferer.dragQueryURIs (~256) */ private static URI[] simpleTestCase(InputStream stream, byte[] bytes, String charset) throws IOException { BufferedReader reader = null; reader = new BufferedReader(new InputStreamReader(stream, charset)); String line; ArrayList<URI> uriList = new ArrayList<URI>(); URI uri; while ((line = reader.readLine()) != null) { try { uri = new URI(line);// <- fails here if line == "\0" } catch (URISyntaxException uriSyntaxException) { throw new IOException(uriSyntaxException); } uriList.add(uri); } return uriList.toArray(new URI[uriList.size()]); } }
diff -uNr openjdk-orig/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java openjdk/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java --- openjdk-orig/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java 2012-10-16 22:36:45.000000000 +0200 +++ openjdk/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java 2012-12-15 12:14:59.281673529 +0100 @@ -283,14 +283,14 @@ reader = new BufferedReader(new InputStreamReader(stream, charset)); String line; ArrayList<URI> uriList = new ArrayList<URI>(); - URI uri; while ((line = reader.readLine()) != null) { try { - uri = new URI(line); + if (!"\0".equals(line)) { + uriList.add(new URI(line)); + } } catch (URISyntaxException uriSyntaxException) { throw new IOException(uriSyntaxException); } - uriList.add(uri); } return uriList.toArray(new URI[uriList.size()]); } finally {