Logo Search packages:      
Sourcecode: jabref version File versions  Download package

ExternalFilePanel.java

package net.sf.jabref.external;

import java.awt.Component;
import java.awt.GridLayout;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.xml.transform.TransformerException;

import net.sf.jabref.BibtexDatabase;
import net.sf.jabref.BibtexEntry;
import net.sf.jabref.BibtexFields;
import net.sf.jabref.EntryEditor;
import net.sf.jabref.FieldEditor;
import net.sf.jabref.Globals;
import net.sf.jabref.JabRefFrame;
import net.sf.jabref.MetaData;
import net.sf.jabref.OpenFileFilter;
import net.sf.jabref.UrlDragDrop;
import net.sf.jabref.Util;
import net.sf.jabref.gui.FileDialogs;
import net.sf.jabref.net.URLDownload;
import net.sf.jabref.util.XMPUtil;

/**
 * Initial Version:
 * 
 * @author alver
 * @version Date: May 7, 2005 Time: 7:17:42 PM
 * 
 * Current Version:
 * 
 * @author $Author: mortenalver $
 * @version $Revision: 2950 $ ($Date: 2009-04-14 20:17:08 +0200 (Tue, 14 Apr 2009) $)
 * 
 */
00050 public class ExternalFilePanel extends JPanel {

      private static final long serialVersionUID = 3653290879640642718L;

      private JButton browseBut, download, auto, xmp;

      private EntryEditor entryEditor;

    private JabRefFrame frame;

      private OpenFileFilter off;

      private BibtexEntry entry;
      
      private BibtexDatabase database;

      private MetaData metaData;

      public ExternalFilePanel(final String fieldName, final MetaData metaData,
            final BibtexEntry entry, final FieldEditor editor, final OpenFileFilter off) {
            this(null, metaData, null, fieldName, off, editor);
            this.entry = entry;
        this.entryEditor = null;
    }

      public ExternalFilePanel(final JabRefFrame frame, final MetaData metaData,
            final EntryEditor entryEditor, final String fieldName, final OpenFileFilter off,
            final FieldEditor editor) {

            this.frame = frame;
            this.metaData = metaData;
            this.off = off;
            this.entryEditor = entryEditor;

        setLayout(new GridLayout(2, 2));

            browseBut = new JButton(Globals.lang("Browse"));
            download = new JButton(Globals.lang("Download"));
            auto = new JButton(Globals.lang("Auto"));
            xmp = new JButton(Globals.lang("Write XMP"));
            xmp.setToolTipText(Globals.lang("Write BibtexEntry as XMP-metadata to PDF."));

            browseBut.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        browseFile(fieldName, editor);
                        // editor.setText(chosenValue);
                        entryEditor.storeFieldAction.actionPerformed(new ActionEvent(editor, 0, ""));
                  }
            });

            download.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        downLoadFile(fieldName, editor, frame);
                  }
            });

            auto.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        autoSetFile(fieldName, editor);
                  }
            });
            xmp.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        pushXMP(fieldName, editor);
                  }
            });

            add(browseBut);
            add(download);
            add(auto);
            add(xmp);

            // Add drag and drop support to the field
            if (editor != null)
                  ((JComponent) editor).setDropTarget(new DropTarget((Component) editor,
                        DnDConstants.ACTION_NONE, new UrlDragDrop(entryEditor, frame, editor)));
      }

      /**
       * Change which entry this panel is operating on. This is used only when
       * this panel is not attached to an entry editor.
       */
00132       public void setEntry(BibtexEntry entry, BibtexDatabase database) {
            this.entry = entry;
            this.database = database;
      }
      
      public BibtexDatabase getDatabase(){
            return (database != null ? database : entryEditor.getDatabase());
      }

      public BibtexEntry getEntry() {
            return (entry != null ? entry : entryEditor.getEntry());
      }

      protected Object getKey() {
            return getEntry().getField(BibtexFields.KEY_FIELD);
      }

      protected void output(String s) {
            if (frame != null)
                  frame.output(s);
      }

      public void pushXMP(final String fieldName, final FieldEditor editor) {


            (new Thread() {
                  public void run() {

                        output(Globals.lang("Looking for pdf..."));
                        
                        // Find the default directory for this field type, if any:
                        String dir = metaData.getFileDirectory(fieldName);
                        File file = null;
                        if (dir != null) {
                              File tmp = Util.expandFilename(editor.getText(), new String[] { dir, "." });
                              if (tmp != null)
                                    file = tmp;
                        }

                        if (file == null) {
                              file = new File(editor.getText());
                        }
                        
                        final File finalFile = file;
            
                        output(Globals.lang("Writing XMP to '%0'...", finalFile.getName()));
                        try {
                              XMPUtil.writeXMP(finalFile, getEntry(), getDatabase());
                              output(Globals.lang("Wrote XMP to '%0'.", finalFile.getName()));
                        } catch (IOException e) {
                              JOptionPane.showMessageDialog(editor.getParent(), Globals.lang(
                                    "Error writing XMP to file: %0", e.getLocalizedMessage()), Globals
                                    .lang("Writing XMP"), JOptionPane.ERROR_MESSAGE);
                              Globals.logger(Globals.lang("Error writing XMP to file: %0", finalFile
                                    .getAbsolutePath()));
                              output(Globals.lang("Error writing XMP to file: %0", finalFile.getName()));
                              
                        } catch (TransformerException e) {
                              JOptionPane.showMessageDialog(editor.getParent(), Globals.lang(
                                    "Error converting Bibtex to XMP: %0", e.getLocalizedMessage()), Globals
                                    .lang("Writing XMP"), JOptionPane.ERROR_MESSAGE);
                              Globals.logger(Globals.lang("Error while converting BibtexEntry to XMP %0",
                                    finalFile.getAbsolutePath()));
                              output(Globals.lang("Error converting XMP to '%0'...", finalFile.getName()));
                        }
                  }
            }).start();
      }

      public void browseFile(final String fieldName, final FieldEditor editor) {

            String directory = metaData.getFileDirectory(fieldName);
            if ((directory != null) && directory.equals(""))
                  directory = null;

            String dir = editor.getText(), retVal = null;

            if ((directory == null) || !(new File(dir)).isAbsolute()) {
                  if (directory != null)
                        dir = directory;
                  else
                        dir = Globals.prefs.get(fieldName + Globals.FILETYPE_PREFS_EXT, "");
            }

            String chosenFile = FileDialogs.getNewFile(frame, new File(dir), "." + fieldName,
                  JFileChooser.OPEN_DIALOG, false);

            if (chosenFile != null) {
                  File newFile = new File(chosenFile);
                  String position = newFile.getParent();

                  if ((directory != null) && position.startsWith(directory)) {
                        // Construct path relative to pdf base dir
                        String relPath = position.substring(directory.length(), position.length())
                              + File.separator + newFile.getName();

                        // Remove leading path separator
                        if (relPath.startsWith(File.separator)) {
                              relPath = relPath.substring(File.separator.length(), relPath.length());

                              // Set relative path as field value
                        }

                        retVal = relPath;
                  } else
                        retVal = newFile.getPath();

                  editor.setText(retVal);
                  Globals.prefs.put(fieldName + Globals.FILETYPE_PREFS_EXT, newFile.getPath());
            }
      }

      public void downLoadFile(final String fieldName, final FieldEditor fieldEditor,
            final Component parent) {

            final String res = JOptionPane.showInputDialog(parent, Globals
                  .lang("Enter URL to download"));

            if (res == null || res.trim().length() == 0)
                  return;

            /*
             * If this panel belongs in an entry editor, note which entry is
             * currently shown:
             */
            final BibtexEntry targetEntry;
            if (entryEditor != null)
                  targetEntry = entryEditor.getEntry();
            else
                  targetEntry = entry;

            (new Thread() {

                  public String getPlannedFileName(String res) {
                        String suffix = off.getSuffix(res);
                        if (suffix == null)
                              suffix = "." + fieldName.toLowerCase();

                        String plannedName = null;
                        if (getKey() != null)
                              plannedName = getKey() + suffix;
                        else {
                              plannedName = JOptionPane.showInputDialog(parent, Globals
                                    .lang("BibTeX key not set. Enter a name for the downloaded file"));
                              if (plannedName != null && !off.accept(plannedName))
                                    plannedName += suffix;
                        }

                        /*
                         * [ 1548875 ] download pdf produces unsupported filename
                         * 
                         * http://sourceforge.net/tracker/index.php?func=detail&aid=1548875&group_id=92314&atid=600306
                         * 
                         */
                        if (Globals.ON_WIN) {
                              plannedName = plannedName.replaceAll(
                                    "\\?|\\*|\\<|\\>|\\||\\\"|\\:|\\.$|\\[|\\]", "");
                        } else if (Globals.ON_MAC) {
                              plannedName = plannedName.replaceAll(":", "");
                        }

                        return plannedName;
                  }

                  public void run() {
                        String originalText = fieldEditor.getText();
                        fieldEditor.setEnabled(false);
                        boolean updateEditor = true;

                        try {
                              fieldEditor.setText(Globals.lang("Downloading..."));
                              output(Globals.lang("Downloading..."));
                              String plannedName = getPlannedFileName(res);

                              // Find the default directory for this field type:
                              String directory = metaData.getFileDirectory(fieldName);

                              if (!new File(directory).exists()) {
                                    JOptionPane.showMessageDialog(parent, Globals.lang(
                                          "Could not find directory for %0-files: %1", fieldName, directory),
                                          Globals.lang("Download file"), JOptionPane.ERROR_MESSAGE);
                                    Globals.logger(Globals.lang("Could not find directory for %0-files: %1",
                                          fieldName, directory));
                                    return;
                              }
                              File file = new File(new File(directory), plannedName);

                              URL url = new URL(res);

                              URLDownload udl = new URLDownload(parent, url, file);
                              try {
                                    udl.download();
                              } catch (IOException e2) {
                                    JOptionPane.showMessageDialog(parent, Globals.lang("Invalid URL")+": "
                                          + e2.getMessage(), Globals.lang("Download file"),
                                          JOptionPane.ERROR_MESSAGE);
                                    Globals.logger("Error while downloading " + url.toString());
                                    return;
                              }
                              output(Globals.lang("Download completed"));

                              String textToSet = file.getPath();
                              if (textToSet.startsWith(directory)) {
                                    // Construct path relative to pdf base dir
                                    textToSet = textToSet.substring(directory.length(), textToSet.length());

                                    // Remove leading path separator
                                    if (textToSet.startsWith(File.separator)) {
                                          textToSet = textToSet.substring(File.separator.length());
                                    }
                              }

                              /*
                               * Check if we should update the editor text field, or
                               * update the target entry directly:
                               */
                    if (entryEditor == null || entryEditor.getEntry() != targetEntry) {
                                    /*
                                     * Editor has probably changed to show a different
                                     * entry. So we must update the target entry directly
                                     * and not set the text of the editor.
                                     */
                                    targetEntry.setField(fieldName, textToSet);
                        fieldEditor.setText(textToSet);
                        fieldEditor.setEnabled(true);
                        updateEditor = false;
                              } else {
                                    /*
                                     * Need to set the fieldEditor first before running
                                     * updateField-Action, because otherwise we might get a
                                     * race condition.
                                     * 
                                     * (Hopefully a) Fix for: [ 1545601 ] downloading pdf
                                     * corrupts pdf field text
                                     * 
                                     * http://sourceforge.net/tracker/index.php?func=detail&aid=1545601&group_id=92314&atid=600306
                                     */
                                    fieldEditor.setText(textToSet);
                                    fieldEditor.setEnabled(true);
                                    updateEditor = false;
                                    SwingUtilities.invokeLater(new Thread() {
                                          public void run() {
                                                entryEditor.updateField(fieldEditor);
                                          }
                                    });
                              }

                        } catch (MalformedURLException e1) {
                              JOptionPane.showMessageDialog(parent, Globals.lang("Invalid URL"), Globals
                                    .lang("Download file"), JOptionPane.ERROR_MESSAGE);
                        } finally {
                              // If stuff goes wrong along the road, put back original
                              // value
                              if (updateEditor) {
                                    fieldEditor.setText(originalText);
                                    fieldEditor.setEnabled(true);
                              }
                }
                  }
            }).start();
      }

      /**
       * Starts a thread that searches the external file directory for the given
       * field name, including subdirectories, and looks for files named after the
       * current entry's bibtex key. Returns a reference to the thread for callers
       * that may want to wait for the thread to finish (using join()).
       * 
       * @param fieldName
       *            The field to set.
       * @param editor
       *            An EntryEditor instance where to set the value found.
       * @return A reference to the Thread that performs the operation.
       */
00406       public Thread autoSetFile(final String fieldName, final FieldEditor editor) {
            Object o = getKey();
            if ((o == null) || (Globals.prefs.get(fieldName + "Directory") == null)) {
                  output(Globals.lang("You must set both BibTeX key and %0 directory", fieldName
                        .toUpperCase())
                        + ".");
                  return null;
            }
            output(Globals.lang("Searching for %0 file", fieldName.toUpperCase()) + " '" + o + "."
                  + fieldName + "'...");
            Thread t = (new Thread() {
                  public void run() {
                        /*
                         * Find the following directories to look in for:
                         * 
                         * default directory for this field type.
                         * 
                         * directory of bibtex-file. // NOT POSSIBLE at the moment.
                         * 
                         * JabRef-directory.
                         */
                        LinkedList<String> list = new LinkedList<String>();
                        list.add(metaData.getFileDirectory(fieldName));

                        /*
                         * File fileOfDb = frame.basePanel().file(); if (fileOfDb !=
                         * null){ list.add(fileOfDb.getParentFile().getPath()); }
                         */
                        list.add(".");

                        String found = Util.findPdf(getEntry(), fieldName, list
                              .toArray(new String[list.size()]));// , off);
                                        
                                
                        // To activate findFile:
                        // String found = Util.findFile(getEntry(), null, dir,
                        // ".*[bibtexkey].*");

                        if (found != null) {
                              editor.setText(found);
                              if (entryEditor != null)
                                    entryEditor.updateField(editor);
                              output(Globals.lang("%0 field set", fieldName.toUpperCase()) + ".");
                        } else {
                              output(Globals.lang("No %0 found", fieldName.toUpperCase()) + ".");
                        }

                  }
            });

            t.start();
            return t;

      }

}

Generated by  Doxygen 1.6.0   Back to index