2013-05-01 8 views
9

Ich experimentiere derzeit mit Drag & Drop Java 7 Update 21.Java 7: Wie implementiert man Drag & Drop in Java?

Mein Ziel-Betriebssysteme sind:

  • Windows 7
  • Ubuntu 12.04
  • Mac OSX 10,6/10,8

Die Anforderungen sind:

  • ziehen Sie Dateien aus dem Dateisystem und legen Sie es auf meine Java-Anwendung (eine Kopie der Datei in ein temporäres Verzeichnis zu machen) -> arbeitet für Linux & MacOSX & Windows-

  • Drag E-Mails aus Thunderbird und Drop auf meine Java-Anwendung (Speicher sie als komplette * EML-Datei auf dem Dateisystem)

der folgende Code mit einfacher Datei arbeitet fällt auf meine Anwendung für Windows, Mac OS X und Ubuntu. Eine weitere Anforderung besteht darin, E-Mails von Thunderbird an meine Java-Anwendung zu senden (die E-Mail wird automatisch in eine * .eml-Datei konvertiert und auf der Festplatte gespeichert). Dies funktioniert auch für Windows, aber ich erhalte eine „Data Flavor nicht unterstützt Ausnahme“ in Ubuntu und Mac OS X ...

EDIT: Ich habe versucht, es mit OpenJDK 7 auf Ubuntu, aber mit, dass auch normale Datei fällt doesn arbeite nicht. Nur mit der JDK-Version von Oracle.

Hat jemand eine Idee, wie man das schafft/erreicht?

Vielen Dank im Voraus!

Hier ist ein einfaches executeable Beispiel:

import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.Transferable; 
import java.awt.datatransfer.UnsupportedFlavorException; 
import java.awt.dnd.DnDConstants; 
import java.awt.dnd.DropTarget; 
import java.awt.dnd.DropTargetDropEvent; 
import java.io.File; 
import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Paths; 
import java.nio.file.StandardCopyOption; 
import java.util.List; 


public class DragDropTest extends javax.swing.JFrame { 


    public DragDropTest() { 
     initComponents(); 
     initDragAndDrop(); 
    } 

    private void initDragAndDrop() { 
     this.setDropTarget(new DropTarget(){ 
      @Override 
      public synchronized void drop(DropTargetDropEvent dtde) { 
       try { 
        Transferable transfer = dtde.getTransferable(); 
        if(transfer.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { 
         dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); 
         List objects = (List)transfer.getTransferData(DataFlavor.javaFileListFlavor); 
         for(Object object : objects) { 
          if(object instanceof File) { 
           File source = (File)object; 
           File dest = new File(System.getProperty("user.home")+File.separator+source.getName()); 
           Files.copy(Paths.get(source.getAbsolutePath()), Paths.get(dest.getAbsolutePath()), StandardCopyOption.REPLACE_EXISTING); 
           System.out.println("File copied from "+source.getAbsolutePath()+" to "+dest.getAbsolutePath()); 
          } 
         } 
        } else if(transfer.isDataFlavorSupported(DataFlavor.stringFlavor)) { 
         dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); 
         String type = (String)transfer.getTransferData(DataFlavor.stringFlavor); 
         System.err.println("Data flavor not supported: "+type); 
        } else { 
         System.err.println("Data flavor not supported."); 
        } 
       } catch(UnsupportedFlavorException ex) { 
        System.err.println(ex.getMessage()); 
       } catch(IOException ex) { 
        System.err.println(ex.getMessage()); 
       } catch(Exception ex) { 
        System.err.println(ex.getMessage()); 
       } finally { 
        dtde.dropComplete(true); 
       } 
      } 
     }); 
    } 

    @SuppressWarnings("unchecked")      
    private void initComponents() { 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     setTitle("Drag & Drop"); 
     setResizable(false); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGap(0, 200, Short.MAX_VALUE) 
     ); 
     layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGap(0, 200, Short.MAX_VALUE) 
     ); 

     pack(); 
    }      

    public static void main(String args[]) { 
     new DragDropTest().setVisible(true); 
    } 

} 

Antwort

0

Hier ist ein Work-Around, wie ich das Problem für den Moment endlich gelöst habe.

  1. wenn Datei-Liste-Geschmack nicht unterstützt wird, imap URL aus dem Drop-Ereignisse
  2. öffnen eine imap Verbindung mit den zur Verfügung gestellten Informationen aus der imap URL
  3. offen imap-store, imap-Ordner erhalten, Suchmeldung von UID und schließlich holen Nachricht
  4. Konvertit * EML-Format

benötigte Bibliotheken: Apache Commons I/O und Java Mail API

Das Folgende ist die Drop-Ereignis Umsetzung:

scrDocuments.setDropTarget(new DropTarget() { 
     @Override 
     public synchronized void drop(DropTargetDropEvent evt) { 
      try { 
       Transferable transfer = evt.getTransferable(); 
       if(transfer.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { 
        evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); 
        List objects = (List)transfer.getTransferData(DataFlavor.javaFileListFlavor); 
        for(Object object : objects) { 
         if(object instanceof File) { 
          File file = (File)object; 
          // store file ... 
         } 
        } 
       } else { 
        try { 
         String url = fetchURL(evt, transfer); 
         ImapMessage eml = new ImapMessage(url); 
         File file = eml.fetchMessage(); 
         // store file ... 
        } catch(Exception ex) { 
         System.err.println(ex.getMessage()); 
        } 
       } 
      } catch(Exception ex) { 
       System.err.println(ex.getMessage()); 
      } finally { 
       evt.dropComplete(true); 
      } 
     } 
    }); 

private String fetchURL(DropTargetDropEvent evt, Transferable transfer) throws IOException, UnsupportedEncodingException, UnsupportedFlavorException { 
    for(DataFlavor flavor : transfer.getTransferDataFlavors()) { 
     if(flavor.isRepresentationClassInputStream()) { 
      if(flavor.getHumanPresentableName().equals("application/x-moz-file-promise-url")) { 
       evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); 
       BufferedReader reader = new BufferedReader(new InputStreamReader((InputStream)transfer.getTransferData(flavor), "ISO-8859-1")); 
       String fAddress = reader.readLine(); 
       reader.close(); 
       return fAddress; 
      } 
     } 
    } 
    throw new IOException("No transferable object or stream found."); 
} 

Und die folgende Klasse sucht-up der IMAP-Server und holt die E-Mail:

public class ImapMessage { 

    private String authority; 
    private String protocol; 
    private String host; 
    private int port; 
    private String username; 
    private String password; 
    private String foldername; 
    private long msgid; 
    private String filename; 
    private Message message; 

    public ImapMessage(String url) throws IOException, MessagingException { 
     parseURL(decodeURL(url)); 
    } 

    @Override 
    public String toString() { 
     return "protocol: "+protocol+"\n"+ 
       "host: "+host+"\n"+ 
       "port: "+port+"\n"+ 
       "username: "+username+"\n"+ 
       "password: "+password+"\n"+ 
       "folder: "+foldername+"\n"+ 
       "msgid: "+msgid+"\n"+ 
       "filename: "+filename; 
    } 

    private String decodeURL(String url) throws IOException { 
     if(url!=null && !url.isEmpty()) { 
      String newurl = ""; 
      for(int i=0; i<url.length(); i+=2) { 
       newurl+=url.substring(i, i+1); 
      } 
      newurl = StringUtils.replace(newurl, "%3E", ">"); 
      newurl = StringUtils.replace(newurl, "%20", " "); 
      return newurl; 
     } else { 
      throw new IOException("The given URL is empty or invalid."); 
     } 
    } 


    private void parseURL(String url) throws IOException, MalformedURLException { 
     if(url!=null && !url.isEmpty()) { 
      //<editor-fold defaultstate="collapsed" desc="Parse Protocol"> 
      if(url.startsWith("imaps")) { 
       url = StringUtils.replace(url, "imaps", "http", 1); 
       protocol = "imaps"; 
      } else if(url.startsWith("imap")) { 
       url = StringUtils.replace(url, "imap", "http", 1); 
       protocol = "imap"; 
      } else { 
       throw new IOException("Unsupported protocol: "+url.substring(0, url.indexOf("://"))); 
      } 

      try { 
       URL newurl = new URL(url); 
       String path = newurl.getPath(); 
       String query = newurl.getQuery(); 
       authority = newurl.getAuthority(); 
       host = newurl.getHost(); 
       port = newurl.getPort(); 
       username = newurl.getUserInfo(); 
       password = "provide your password here"; 
       foldername = path.substring(path.indexOf(">/")+2, path.lastIndexOf(">")); 
       msgid = Long.parseLong(path.substring(path.lastIndexOf(">")+1, path.length())); 
       filename = query.substring(query.indexOf("=")+1, query.length()); 
      } catch (MalformedURLException ex) { 
       throw ex; 
      } 
     } else { 
      throw new IOException("The given URL is empty or invalid."); 
     } 
    } 

     public File fetchMessage() throws IOException, FileNotFoundException, MessagingException { 

      Store store = null; 
      Folder folder = null; 
      File filepath = new File("/destination/directory"); 
      try { 
       Properties props = System.getProperties(); 
       props.setProperty("mail.store.protocol", protocol); 
       Session session = Session.getDefaultInstance(props, null); 
       // session.setDebug(true); 
       store = session.getStore(protocol); 
       store.connect(host, port, username, password); 
       folder = store.getFolder(foldername); 
       folder.open(Folder.READ_ONLY); 
       UIDFolder ufolder = (UIDFolder)folder; 
       message = ufolder.getMessageByUID(msgid); 
       if(message!=null) { 
        File file = null; 
        if(filename.equals("null")) { 
         file = new File(filepath.getAbsolutePath()+File.separator+Long.toString(System.nanoTime())+".eml"); 
        } else { 
         file = new File(filepath.getAbsolutePath()+File.separator+filename); 
        } 
        message.writeTo(new FileOutputStream(file)); 
        return file; 
       } else { 
        throw new MessagingException("The requested e-mail could not be found on the mail server."); 
       } 
      } catch(Exception ex) { 
       throw ex; 
      } finally { 
       if(folder!=null) { 
        folder.close(true); 
       } 
       if(store!=null) { 
        store.close(); 
       } 
      } 
     } 

    } 
5

Statt werfen, warum nicht drucken, welche Daten Aromen Sie auf der übertragbar erhalten, und sehen, ob es ist, die Sie verwenden können. Etwas wie,

else { 
     for(DataFlavor f : transfer.getTransferDataFlavors()) { 
      System.out.println("flavor f:" + f + " type:" + f.getMimeType() + " javaClas:" + f.getDefaultRepresentationClass()); 
     } 
} 

Angesichts der Ausgabe von, gibt es eine gute Chance können Sie sehen, wie Sie es in eine Datei speichern.

+1

einen Schritt weiter gehen, um den Geschmack drucken Sie und versuchen, um es zu manipulieren, vielleicht alles in Datei zu speichern und dann zu sehen, was .eml ist, obwohl ich vermute, dass nur einer gesetzt wird. Wenn du nichts verwendbares bekommst, könnte ein Problem mit Thunderbird für * nix sein – tgkprog

6

Eigentlich ist das Problem nicht in Ihrem Java-Code ... Es ist ein Fehler in Ubuntu selbst, während Ubuntu Unity Drag & Drop nicht über zwei Windows unterstützt (In Ihrer Anwendung zwischen Mozilla Thunderbird und Java App). während es möglich ist, eine Datei aus dem Dateisystem in ein Fenster zu ziehen und abzulegen.

Um dies zu bestätigen, versuchen Sie, eine Mail-Datei von Thunderbird in einen Browser-Fenster als Gmail Attachment ziehen ,,, es wird nicht funktionieren. https://bugs.launchpad.net/unity/+bug/995039

+0

Danke für deinen Vorschlag. Ich habe versucht, Mousetweaks mit "sudo apt-get purge mousetweaks" zu entfernen. Aber es funktioniert immer noch nicht ... :-( – salocinx