package org.jabref.gui.exporter; import java.awt.Toolkit; import java.awt.datatransfer.ClipboardOwner; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Objects; import javax.swing.BorderFactory; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.ListSelectionModel; import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.JabRefFrame; import org.jabref.gui.worker.AbstractWorker; import org.jabref.logic.exporter.ExportFormats; import org.jabref.logic.exporter.IExportFormat; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ExportToClipboardAction extends AbstractWorker { private static final Log LOGGER = LogFactory.getLog(ExportToClipboardAction.class); private final JabRefFrame frame; /** * written by run() and read by update() */ private String message; public ExportToClipboardAction(JabRefFrame frame) { this.frame = Objects.requireNonNull(frame); } @Override public void run() { BasePanel panel = frame.getCurrentBasePanel(); if (panel == null) { return; } if (panel.getSelectedEntries().isEmpty()) { message = Localization.lang("This operation requires one or more entries to be selected."); getCallBack().update(); return; } List<IExportFormat> exportFormats = new LinkedList<>(ExportFormats.getExportFormats().values()); Collections.sort(exportFormats, (e1, e2) -> e1.getDisplayName().compareTo(e2.getDisplayName())); String[] exportFormatDisplayNames = new String[exportFormats.size()]; for (int i = 0; i < exportFormats.size(); i++) { IExportFormat exportFormat = exportFormats.get(i); exportFormatDisplayNames[i] = exportFormat.getDisplayName(); } JList<String> list = new JList<>(exportFormatDisplayNames); list.setBorder(BorderFactory.createEtchedBorder()); list.setSelectionInterval(0, 0); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); int answer = JOptionPane.showOptionDialog(frame, list, Localization.lang("Select export format"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, new String[] {Localization.lang("Export"), Localization.lang("Cancel")}, Localization.lang("Export")); if (answer == JOptionPane.NO_OPTION) { return; } IExportFormat format = exportFormats.get(list.getSelectedIndex()); // Set the global variable for this database's file directory before exporting, // so formatters can resolve linked files correctly. // (This is an ugly hack!) Globals.prefs.fileDirForDatabase = frame.getCurrentBasePanel().getBibDatabaseContext() .getFileDirectories(Globals.prefs.getFileDirectoryPreferences()); File tmp = null; try { // To simplify the exporter API we simply do a normal export to a temporary // file, and read the contents afterwards: tmp = File.createTempFile("jabrefCb", ".tmp"); tmp.deleteOnExit(); List<BibEntry> entries = panel.getSelectedEntries(); // Write to file: format.performExport(panel.getBibDatabaseContext(), tmp.getPath(), panel.getBibDatabaseContext().getMetaData().getEncoding() .orElse(Globals.prefs.getDefaultEncoding()), entries); // Read the file and put the contents on the clipboard: StringBuilder sb = new StringBuilder(); try (Reader reader = new InputStreamReader(new FileInputStream(tmp), panel.getBibDatabaseContext().getMetaData().getEncoding() .orElse(Globals.prefs.getDefaultEncoding()))) { int s; while ((s = reader.read()) != -1) { sb.append((char) s); } } ClipboardOwner owner = (clipboard, content) -> { // Do nothing }; RtfTransferable rs = new RtfTransferable(sb.toString()); Toolkit.getDefaultToolkit().getSystemClipboard() .setContents(rs, owner); message = Localization.lang("Entries exported to clipboard") + ": " + entries.size(); } catch (Exception e) { LOGGER.error("Error exporting to clipboard", e); //To change body of catch statement use File | Settings | File Templates. message = Localization.lang("Error exporting to clipboard"); } finally { // Clean up: if ((tmp != null) && !tmp.delete()) { LOGGER.info("Cannot delete temporary clipboard file"); } } } @Override public void update() { frame.output(message); } }