title: Drag and drop differences between JDK1.6 and JDK1.7
body: <p>Does anybody know about differences in the drag-and-drop behavior between JDK1.6 and JDK1.7 ? I encountered a difference (illustrated below) when drag-and-dropping an URL from a browser onto an application which needs to support JDK1.5, JDK1.6 and JDK1.7 . I am now wondering whether other differences exists and if they are documented somewhere.</p>
  
  <p>The different behavior I encountered is when drag-and-drop an URL from a browser (not from the address bar but from the page) by click-and-drag the URL onto the Java application. On JDK1.6, the Transferable does not support the <code>DataFlavor.javaFileListFlavor</code> and on JDK1.7 it does (although when requesting for its transfer data you get an empty list). The following code illustrates the issue. It opens a <code>JFrame</code> on which you can drag-and-drop an URL like <a href="http://www.google.com" rel="nofollow">http://www.google.com</a> and which prints out whether it uses the file list flavor or the URI-list flavor</p>
  
  <pre><code>import javax.swing.JComponent;
  import javax.swing.JFrame;
  import javax.swing.JLabel;
  import javax.swing.JPanel;
  import javax.swing.TransferHandler;
  import java.awt.BorderLayout;
  import java.awt.EventQueue;
  import java.awt.datatransfer.DataFlavor;
  import java.awt.datatransfer.Transferable;
  import java.awt.datatransfer.UnsupportedFlavorException;
  import java.io.File;
  import java.io.IOException;
  import java.lang.reflect.InvocationTargetException;
  import java.util.List;
  
  public class DragAndDropTester {
    private static DataFlavor URI_LIST_FLAVOR = null;
  
    static {
      try {
        URI_LIST_FLAVOR = new DataFlavor( "text/uri-list;class=java.lang.String" );
      }
      catch ( ClassNotFoundException ignore ) {
      }
    }
    public static void main( String[] args ) {
      try {
        EventQueue.invokeAndWait( new Runnable() {
          public void run() {
  
            JFrame testFrame = new JFrame( "Test" );
  
            JPanel contents = new JPanel( new BorderLayout() );
            contents.add( new JLabel( "TestLabel" ), BorderLayout.CENTER );
  
            contents.setTransferHandler( createTransferHandler() );
  
            testFrame.getContentPane().add( contents );
            testFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
            testFrame.setSize( 200, 200 );
            testFrame.setVisible( true );
          }
        } );
      } catch ( InterruptedException e ) {
        throw new RuntimeException( e );
      } catch ( InvocationTargetException e ) {
        throw new RuntimeException( e );
      }
    }
  
    private static TransferHandler createTransferHandler(){
      return new TransferHandler(  ){
        @Override
        public boolean importData( JComponent comp, Transferable aTransferable ) {
          try {
            if ( aTransferable.isDataFlavorSupported( DataFlavor.javaFileListFlavor ) ) {
              System.out.println("File list flavor");
              List&lt;File&gt; file_list = ( List&lt;File&gt; ) aTransferable.getTransferData( DataFlavor.javaFileListFlavor );
              System.out.println( "file_list = " + file_list );
            }
                if ( URI_LIST_FLAVOR != null &amp;&amp; aTransferable.isDataFlavorSupported( URI_LIST_FLAVOR ) ){
              System.out.println("URI list flavor");
              String uri_list = ( String ) aTransferable.getTransferData( URI_LIST_FLAVOR );
              System.out.println( "uri_list = " + uri_list );
            }
          } catch ( UnsupportedFlavorException e ) {
            throw new RuntimeException( e );
          } catch ( IOException e ) {
            throw new RuntimeException( e );
          }
          return true;
        }
  
        @Override
        public boolean canImport( JComponent comp, DataFlavor[] transferFlavors ) {
          return true;
        }
      };
    }
  }
  </code></pre>
  
  <p>Resulting output on JDK 1.7.01</p>
  
  <pre><code>File list flavor
  file_list = []
  URI list flavor
  uri_list = http://www.google.com
  </code></pre>
  
  <p>Resulting output on JDK1.6.0.18</p>
  
  <pre><code>URI list flavor
  uri_list = http://www.google.com
  </code></pre>
  
  <p>I can easily create a workaround for this issue, but I am more interested in any more know differences and/or documentation about those differences.</p>
  
  <p><strong>Edit</strong></p>
  
  <p>Some further investigation/googling makes me think the behavior on JDK7 is to create both the URI and filelist data flavor and offering them both in the transferable. The filelist then only contains the URI's which represent a file. Hence when only drag-and-dropping an URL, the file list is empty. I cannot find this in the JDK source code as it seems the transferable/transferdata is created in native code (or at least code for which I do not find the sources). On the OpenJDK mailing list there was a discussion about a <a href="http://osdir.com/ml/java.openjdk.awt.devel/2008-06/msg00002.html" rel="nofollow">similar issue</a>, containing the following quote</p>
  
  <blockquote>
    <p>If you drag a file list from native into Java, the application sees both a URI list and a file list. If you drag in a URI list it sees a URI list, and if all URIs are files also a non-empty file list, otherwise just an empty file list. </p>
  </blockquote>
  
  <p><strong>Edit2</strong></p>
  
  <p>Based on the answer of serg.nechaev I performed some more tests on 32/64 bit Linux systems and several Windows system (ranging from XP to Windows7). On Linux with JDK7 I always get the URI dataflavor, combined with an empty filelist flavor. On Windows, I get a URI dataflavor and a non-empty filelist data flavor. It seems a <code>.URL</code> file gets created in the temp dir, and this is passed in the filelist data flavor as well, which wasn't the case on JDK 6.</p>
  
  <p>Solution in all these cases is to check for the URI dataflavor first, and use the file list data flavor as fall-back</p>