source: josm/trunk/src/org/openstreetmap/josm/gui/datatransfer/ClipboardUtils.java @ 11535

Last change on this file since 11535 was 11535, checked in by Don-vip, 2 years ago

sonar - squid:S2142 - "InterruptedException" should not be ignored

File size: 6.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.datatransfer;
3
4import java.awt.GraphicsEnvironment;
5import java.awt.HeadlessException;
6import java.awt.Toolkit;
7import java.awt.datatransfer.Clipboard;
8import java.awt.datatransfer.ClipboardOwner;
9import java.awt.datatransfer.DataFlavor;
10import java.awt.datatransfer.StringSelection;
11import java.awt.datatransfer.Transferable;
12import java.awt.datatransfer.UnsupportedFlavorException;
13import java.io.IOException;
14
15import org.openstreetmap.josm.Main;
16import org.openstreetmap.josm.gui.util.GuiHelper;
17import org.openstreetmap.josm.tools.Utils;
18
19/**
20 * This is a utility class that provides methods useful for general data transfer support.
21 *
22 * @author Michael Zangl
23 * @since 10604
24 */
25public final class ClipboardUtils {
26    private static final class DoNothingClipboardOwner implements ClipboardOwner {
27        @Override
28        public void lostOwnership(Clipboard clpbrd, Transferable t) {
29            // Do nothing
30        }
31    }
32
33    private static Clipboard clipboard;
34
35    private ClipboardUtils() {
36    }
37
38    /**
39     * This method should be used from all of JOSM to access the clipboard.
40     * <p>
41     * It will default to the system clipboard except for cases where that clipboard is not accessible.
42     * @return A clipboard.
43     * @see #getClipboardContent()
44     */
45    public static synchronized Clipboard getClipboard() {
46        // Might be unsupported in some more cases, we need a fake clipboard then.
47        if (clipboard == null) {
48            try {
49                clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
50            } catch (HeadlessException e) {
51                Main.warn("Headless. Using fake clipboard.", e);
52                clipboard = new Clipboard("fake");
53            }
54        }
55        return clipboard;
56    }
57
58    /**
59     * Gets the singleton instance of the system selection as a <code>Clipboard</code> object.
60     * This allows an application to read and modify the current, system-wide selection.
61     * @return the system selection as a <code>Clipboard</code>, or <code>null</code> if the native platform does not
62     *         support a system selection <code>Clipboard</code> or if GraphicsEnvironment.isHeadless() returns true
63     * @see Toolkit#getSystemSelection
64     */
65    public static Clipboard getSystemSelection() {
66        if (GraphicsEnvironment.isHeadless()) {
67            return null;
68        } else {
69            return Toolkit.getDefaultToolkit().getSystemSelection();
70        }
71    }
72
73    /**
74     * Gets the clipboard content as string.
75     * @return the content if available, <code>null</code> otherwise.
76     */
77    public static String getClipboardStringContent() {
78        try {
79            Transferable t = getClipboardContent();
80            if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
81                return (String) t.getTransferData(DataFlavor.stringFlavor);
82            }
83        } catch (UnsupportedFlavorException | IOException ex) {
84            Main.error(ex);
85        }
86        return null;
87    }
88
89    /**
90     * Extracts clipboard content as {@code Transferable} object. Using this method avoids some problems on some platforms.
91     * @return The content or <code>null</code> if it is not available
92     */
93    public static synchronized Transferable getClipboardContent() {
94        return getClipboardContent(getClipboard());
95    }
96
97    /**
98     * Extracts clipboard content as {@code Transferable} object. Using this method avoids some problems on some platforms.
99     * @param clipboard clipboard from which contents are retrieved
100     * @return clipboard contents if available, {@code null} otherwise.
101     */
102    public static Transferable getClipboardContent(Clipboard clipboard) {
103        Transferable t = null;
104        for (int tries = 0; t == null && tries < 10; tries++) {
105            try {
106                t = clipboard.getContents(null);
107            } catch (IllegalStateException e) {
108                // Clipboard currently unavailable.
109                // On some platforms, the system clipboard is unavailable while it is accessed by another application.
110                Main.trace("Clipboard unavailable.", e);
111                try {
112                    Thread.sleep(1);
113                } catch (InterruptedException ex) {
114                    Main.warn(ex, "InterruptedException in " + Utils.class.getSimpleName()
115                            + " while getting clipboard content");
116                    Thread.currentThread().interrupt();
117                }
118            } catch (NullPointerException e) {
119                // JDK-6322854: On Linux/X11, NPE can happen for unknown reasons, on all versions of Java
120                Main.error(e);
121            }
122        }
123        return t;
124    }
125
126    /**
127     * Copy the given string to the clipboard.
128     * @param s The string to copy.
129     * @return True if the  copy was successful
130     */
131    public static boolean copyString(String s) {
132        return copy(new StringSelection(s));
133    }
134
135    /**
136     * Copies the given transferable to the clipboard. Handles state problems that occur on some platforms.
137     * @param transferable The transferable to copy.
138     * @return True if the copy was successful
139     */
140    public static boolean copy(final Transferable transferable) {
141        return GuiHelper.runInEDTAndWaitAndReturn(() -> {
142            try {
143                getClipboard().setContents(transferable, new DoNothingClipboardOwner());
144                return Boolean.TRUE;
145            } catch (IllegalStateException ex) {
146                Main.error(ex);
147                return Boolean.FALSE;
148            }
149        });
150    }
151
152    /**
153     * Returns a new {@link DataFlavor} for the given class and human-readable name.
154     * @param c class
155     * @param humanPresentableName the human-readable string used to identify this flavor
156     * @return a new {@link DataFlavor} for the given class and human-readable name
157     * @since 10801
158     */
159    public static DataFlavor newDataFlavor(Class<?> c, String humanPresentableName) {
160        try {
161            return new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + c.getName(),
162                    humanPresentableName, c.getClassLoader());
163        } catch (ClassNotFoundException e) {
164            throw new IllegalArgumentException(e);
165        }
166    }
167}
Note: See TracBrowser for help on using the repository browser.