--- old/src/share/classes/sun/awt/datatransfer/SunClipboard.java 2014-07-17 14:35:51.000000000 +0400
+++ /dev/null 2014-07-17 14:35:51.000000000 +0400
@@ -1,451 +0,0 @@
-/*
- * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.awt.datatransfer;
-
-import java.awt.EventQueue;
-
-import java.awt.datatransfer.Clipboard;
-import java.awt.datatransfer.FlavorTable;
-import java.awt.datatransfer.SystemFlavorMap;
-import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.ClipboardOwner;
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.FlavorListener;
-import java.awt.datatransfer.FlavorEvent;
-import java.awt.datatransfer.UnsupportedFlavorException;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-
-import java.util.Objects;
-import java.util.Set;
-import java.util.HashSet;
-
-import java.io.IOException;
-
-import sun.awt.AppContext;
-import sun.awt.PeerEvent;
-import sun.awt.SunToolkit;
-
-
-/**
- * Serves as a common, helper superclass for the Win32 and X11 system
- * Clipboards.
- *
- * @author Danila Sinopalnikov
- * @author Alexander Gerasimov
- *
- * @since 1.3
- */
-public abstract class SunClipboard extends Clipboard
- implements PropertyChangeListener {
-
- private AppContext contentsContext = null;
-
- private final Object CLIPBOARD_FLAVOR_LISTENER_KEY;
-
- /**
- * A number of FlavorListener
s currently registered
- * on this clipboard across all AppContext
s.
- */
- private volatile int numberOfFlavorListeners = 0;
-
- /**
- * A set of DataFlavor
s that is available on
- * this clipboard. It is used for tracking changes
- * of DataFlavor
s available on this clipboard.
- */
- private volatile Set currentDataFlavors;
-
-
- public SunClipboard(String name) {
- super(name);
- CLIPBOARD_FLAVOR_LISTENER_KEY = new StringBuffer(name + "_CLIPBOARD_FLAVOR_LISTENER_KEY");
- }
-
- public synchronized void setContents(Transferable contents,
- ClipboardOwner owner) {
- // 4378007 : Toolkit.getSystemClipboard().setContents(null, null)
- // should throw NPE
- if (contents == null) {
- throw new NullPointerException("contents");
- }
-
- initContext();
-
- final ClipboardOwner oldOwner = this.owner;
- final Transferable oldContents = this.contents;
-
- try {
- this.owner = owner;
- this.contents = new TransferableProxy(contents, true);
-
- setContentsNative(contents);
- } finally {
- if (oldOwner != null && oldOwner != owner) {
- EventQueue.invokeLater(() -> oldOwner.lostOwnership(SunClipboard.this, oldContents));
- }
- }
- }
-
- private synchronized void initContext() {
- final AppContext context = AppContext.getAppContext();
-
- if (contentsContext != context) {
- // Need to synchronize on the AppContext to guarantee that it cannot
- // be disposed after the check, but before the listener is added.
- synchronized (context) {
- if (context.isDisposed()) {
- throw new IllegalStateException("Can't set contents from disposed AppContext");
- }
- context.addPropertyChangeListener
- (AppContext.DISPOSED_PROPERTY_NAME, this);
- }
- if (contentsContext != null) {
- contentsContext.removePropertyChangeListener
- (AppContext.DISPOSED_PROPERTY_NAME, this);
- }
- contentsContext = context;
- }
- }
-
- public synchronized Transferable getContents(Object requestor) {
- if (contents != null) {
- return contents;
- }
- return new ClipboardTransferable(this);
- }
-
-
- /**
- * @return the contents of this clipboard if it has been set from the same
- * AppContext as it is currently retrieved or null otherwise
- * @since 1.5
- */
- private synchronized Transferable getContextContents() {
- AppContext context = AppContext.getAppContext();
- return (context == contentsContext) ? contents : null;
- }
-
-
- /**
- * @see java.awt.Clipboard#getAvailableDataFlavors
- * @since 1.5
- */
- public DataFlavor[] getAvailableDataFlavors() {
- Transferable cntnts = getContextContents();
- if (cntnts != null) {
- return cntnts.getTransferDataFlavors();
- }
-
- long[] formats = getClipboardFormatsOpenClose();
-
- return DataTransferer.getInstance().
- getFlavorsForFormatsAsArray(formats, getDefaultFlavorTable());
- }
-
- /**
- * @see java.awt.Clipboard#isDataFlavorAvailable
- * @since 1.5
- */
- public boolean isDataFlavorAvailable(DataFlavor flavor) {
- if (flavor == null) {
- throw new NullPointerException("flavor");
- }
-
- Transferable cntnts = getContextContents();
- if (cntnts != null) {
- return cntnts.isDataFlavorSupported(flavor);
- }
-
- long[] formats = getClipboardFormatsOpenClose();
-
- return formatArrayAsDataFlavorSet(formats).contains(flavor);
- }
-
- /**
- * @see java.awt.Clipboard#getData
- * @since 1.5
- */
- public Object getData(DataFlavor flavor)
- throws UnsupportedFlavorException, IOException {
- if (flavor == null) {
- throw new NullPointerException("flavor");
- }
-
- Transferable cntnts = getContextContents();
- if (cntnts != null) {
- return cntnts.getTransferData(flavor);
- }
-
- long format = 0;
- byte[] data = null;
- Transferable localeTransferable = null;
-
- try {
- openClipboard(null);
-
- long[] formats = getClipboardFormats();
- Long lFormat = DataTransferer.getInstance().
- getFlavorsForFormats(formats, getDefaultFlavorTable()).get(flavor);
-
- if (lFormat == null) {
- throw new UnsupportedFlavorException(flavor);
- }
-
- format = lFormat.longValue();
- data = getClipboardData(format);
-
- if (DataTransferer.getInstance().isLocaleDependentTextFormat(format)) {
- localeTransferable = createLocaleTransferable(formats);
- }
-
- } finally {
- closeClipboard();
- }
-
- return DataTransferer.getInstance().
- translateBytes(data, flavor, format, localeTransferable);
- }
-
- /**
- * The clipboard must be opened.
- *
- * @since 1.5
- */
- protected Transferable createLocaleTransferable(long[] formats) throws IOException {
- return null;
- }
-
- /**
- * @throws IllegalStateException if the clipboard has not been opened
- */
- public void openClipboard(SunClipboard newOwner) {}
- public void closeClipboard() {}
-
- public abstract long getID();
-
- public void propertyChange(PropertyChangeEvent evt) {
- if (AppContext.DISPOSED_PROPERTY_NAME.equals(evt.getPropertyName()) &&
- Boolean.TRUE.equals(evt.getNewValue())) {
- final AppContext disposedContext = (AppContext)evt.getSource();
- lostOwnershipLater(disposedContext);
- }
- }
-
- protected void lostOwnershipImpl() {
- lostOwnershipLater(null);
- }
-
- /**
- * Clears the clipboard state (contents, owner and contents context) and
- * notifies the current owner that ownership is lost. Does nothing if the
- * argument is not null
and is not equal to the current
- * contents context.
- *
- * @param disposedContext the AppContext that is disposed or
- * null
if the ownership is lost because another
- * application acquired ownership.
- */
- protected void lostOwnershipLater(final AppContext disposedContext) {
- final AppContext context = this.contentsContext;
- if (context == null) {
- return;
- }
-
- final Runnable runnable = new Runnable() {
- public void run() {
- final SunClipboard sunClipboard = SunClipboard.this;
- ClipboardOwner owner = null;
- Transferable contents = null;
-
- synchronized (sunClipboard) {
- final AppContext context = sunClipboard.contentsContext;
-
- if (context == null) {
- return;
- }
-
- if (disposedContext == null || context == disposedContext) {
- owner = sunClipboard.owner;
- contents = sunClipboard.contents;
- sunClipboard.contentsContext = null;
- sunClipboard.owner = null;
- sunClipboard.contents = null;
- sunClipboard.clearNativeContext();
- context.removePropertyChangeListener
- (AppContext.DISPOSED_PROPERTY_NAME, sunClipboard);
- } else {
- return;
- }
- }
- if (owner != null) {
- owner.lostOwnership(sunClipboard, contents);
- }
- }
- };
-
- SunToolkit.postEvent(context, new PeerEvent(this, runnable,
- PeerEvent.PRIORITY_EVENT));
- }
-
- protected abstract void clearNativeContext();
-
- protected abstract void setContentsNative(Transferable contents);
-
- /**
- * @since 1.5
- */
- protected long[] getClipboardFormatsOpenClose() {
- try {
- openClipboard(null);
- return getClipboardFormats();
- } finally {
- closeClipboard();
- }
- }
-
- /**
- * Returns zero-length array (not null) if the number of available formats is zero.
- *
- * @throws IllegalStateException if formats could not be retrieved
- */
- protected abstract long[] getClipboardFormats();
-
- protected abstract byte[] getClipboardData(long format) throws IOException;
-
-
- private static Set formatArrayAsDataFlavorSet(long[] formats) {
- return (formats == null) ? null :
- DataTransferer.getInstance().
- getFlavorsForFormatsAsSet(formats, getDefaultFlavorTable());
- }
-
-
- public synchronized void addFlavorListener(FlavorListener listener) {
- if (listener == null) {
- return;
- }
- AppContext appContext = AppContext.getAppContext();
- Set flavorListeners = getFlavorListeners(appContext);
- if (flavorListeners == null) {
- flavorListeners = new HashSet<>();
- appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, flavorListeners);
- }
- flavorListeners.add(listener);
-
- if (numberOfFlavorListeners++ == 0) {
- long[] currentFormats = null;
- try {
- openClipboard(null);
- currentFormats = getClipboardFormats();
- } catch (IllegalStateException exc) {
- } finally {
- closeClipboard();
- }
- currentDataFlavors = formatArrayAsDataFlavorSet(currentFormats);
-
- registerClipboardViewerChecked();
- }
- }
-
- public synchronized void removeFlavorListener(FlavorListener listener) {
- if (listener == null) {
- return;
- }
- Set flavorListeners = getFlavorListeners(AppContext.getAppContext());
- if (flavorListeners == null){
- //else we throw NullPointerException, but it is forbidden
- return;
- }
- if (flavorListeners.remove(listener) && --numberOfFlavorListeners == 0) {
- unregisterClipboardViewerChecked();
- currentDataFlavors = null;
- }
- }
-
- @SuppressWarnings("unchecked")
- private Set getFlavorListeners(AppContext appContext) {
- return (Set)appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
- }
-
- public synchronized FlavorListener[] getFlavorListeners() {
- Set flavorListeners = getFlavorListeners(AppContext.getAppContext());
- return flavorListeners == null ? new FlavorListener[0]
- : flavorListeners.toArray(new FlavorListener[flavorListeners.size()]);
- }
-
- public boolean areFlavorListenersRegistered() {
- return (numberOfFlavorListeners > 0);
- }
-
- protected abstract void registerClipboardViewerChecked();
-
- protected abstract void unregisterClipboardViewerChecked();
-
- /**
- * Checks change of the DataFlavor
s and, if necessary,
- * posts notifications on FlavorEvent
s to the
- * AppContexts' EDTs.
- * The parameter formats
is null iff we have just
- * failed to get formats available on the clipboard.
- *
- * @param formats data formats that have just been retrieved from
- * this clipboard
- */
- public void checkChange(long[] formats) {
- Set prevDataFlavors = currentDataFlavors;
- currentDataFlavors = formatArrayAsDataFlavorSet(formats);
-
- if (Objects.equals(prevDataFlavors, currentDataFlavors)) {
- // we've been able to successfully get available on the clipboard
- // DataFlavors this and previous time and they are coincident;
- // don't notify
- return;
- }
-
- for (AppContext appContext : AppContext.getAppContexts()) {
- if (appContext == null || appContext.isDisposed()) {
- continue;
- }
- Set flavorListeners = getFlavorListeners(appContext);
- if (flavorListeners != null) {
- for (FlavorListener listener : flavorListeners) {
- if (listener != null) {
- PeerEvent peerEvent = new PeerEvent(this,
- () -> listener.flavorsChanged(new FlavorEvent(SunClipboard.this)),
- PeerEvent.PRIORITY_EVENT);
- SunToolkit.postEvent(appContext, peerEvent);
- }
- }
- }
- }
- }
-
- public static FlavorTable getDefaultFlavorTable() {
- return (FlavorTable) SystemFlavorMap.getDefaultFlavorMap();
- }
-}
--- /dev/null 2014-07-17 14:35:51.000000000 +0400
+++ new/src/share/classes/sun/awt/datatransfer/desktop/SunClipboard.java 2014-07-17 14:35:51.000000000 +0400
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.awt.datatransfer.desktop;
+
+import java.awt.EventQueue;
+
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.FlavorTable;
+import java.awt.datatransfer.SystemFlavorMap;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.FlavorListener;
+import java.awt.datatransfer.FlavorEvent;
+import java.awt.datatransfer.UnsupportedFlavorException;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import java.util.Objects;
+import java.util.Set;
+import java.util.HashSet;
+
+import java.io.IOException;
+
+import sun.awt.AppContext;
+import sun.awt.PeerEvent;
+import sun.awt.SunToolkit;
+import sun.awt.datatransfer.TransferableProxy;
+
+
+/**
+ * Serves as a common, helper superclass for the Win32 and X11 system
+ * Clipboards.
+ *
+ * @author Danila Sinopalnikov
+ * @author Alexander Gerasimov
+ *
+ * @since 1.3
+ */
+public abstract class SunClipboard extends Clipboard
+ implements PropertyChangeListener {
+
+ private AppContext contentsContext = null;
+
+ private final Object CLIPBOARD_FLAVOR_LISTENER_KEY;
+
+ /**
+ * A number of FlavorListener
s currently registered
+ * on this clipboard across all AppContext
s.
+ */
+ private volatile int numberOfFlavorListeners = 0;
+
+ /**
+ * A set of DataFlavor
s that is available on
+ * this clipboard. It is used for tracking changes
+ * of DataFlavor
s available on this clipboard.
+ */
+ private volatile Set currentDataFlavors;
+
+
+ public SunClipboard(String name) {
+ super(name);
+ CLIPBOARD_FLAVOR_LISTENER_KEY = new StringBuffer(name + "_CLIPBOARD_FLAVOR_LISTENER_KEY");
+ }
+
+ public synchronized void setContents(Transferable contents,
+ ClipboardOwner owner) {
+ // 4378007 : Toolkit.getSystemClipboard().setContents(null, null)
+ // should throw NPE
+ if (contents == null) {
+ throw new NullPointerException("contents");
+ }
+
+ initContext();
+
+ final ClipboardOwner oldOwner = this.owner;
+ final Transferable oldContents = this.contents;
+
+ try {
+ this.owner = owner;
+ this.contents = new TransferableProxy(contents, true);
+
+ setContentsNative(contents);
+ } finally {
+ if (oldOwner != null && oldOwner != owner) {
+ EventQueue.invokeLater(() -> oldOwner.lostOwnership(SunClipboard.this, oldContents));
+ }
+ }
+ }
+
+ private synchronized void initContext() {
+ final AppContext context = AppContext.getAppContext();
+
+ if (contentsContext != context) {
+ // Need to synchronize on the AppContext to guarantee that it cannot
+ // be disposed after the check, but before the listener is added.
+ synchronized (context) {
+ if (context.isDisposed()) {
+ throw new IllegalStateException("Can't set contents from disposed AppContext");
+ }
+ context.addPropertyChangeListener
+ (AppContext.DISPOSED_PROPERTY_NAME, this);
+ }
+ if (contentsContext != null) {
+ contentsContext.removePropertyChangeListener
+ (AppContext.DISPOSED_PROPERTY_NAME, this);
+ }
+ contentsContext = context;
+ }
+ }
+
+ public synchronized Transferable getContents(Object requestor) {
+ if (contents != null) {
+ return contents;
+ }
+ return new ClipboardTransferable(this);
+ }
+
+
+ /**
+ * @return the contents of this clipboard if it has been set from the same
+ * AppContext as it is currently retrieved or null otherwise
+ * @since 1.5
+ */
+ private synchronized Transferable getContextContents() {
+ AppContext context = AppContext.getAppContext();
+ return (context == contentsContext) ? contents : null;
+ }
+
+
+ /**
+ * @see java.awt.datatransfer.Clipboard#getAvailableDataFlavors
+ * @since 1.5
+ */
+ public DataFlavor[] getAvailableDataFlavors() {
+ Transferable cntnts = getContextContents();
+ if (cntnts != null) {
+ return cntnts.getTransferDataFlavors();
+ }
+
+ long[] formats = getClipboardFormatsOpenClose();
+
+ return DataTransferer.getInstance().
+ getFlavorsForFormatsAsArray(formats, getDefaultFlavorTable());
+ }
+
+ /**
+ * @see java.awt.datatransfer.Clipboard#isDataFlavorAvailable
+ * @since 1.5
+ */
+ public boolean isDataFlavorAvailable(DataFlavor flavor) {
+ if (flavor == null) {
+ throw new NullPointerException("flavor");
+ }
+
+ Transferable cntnts = getContextContents();
+ if (cntnts != null) {
+ return cntnts.isDataFlavorSupported(flavor);
+ }
+
+ long[] formats = getClipboardFormatsOpenClose();
+
+ return formatArrayAsDataFlavorSet(formats).contains(flavor);
+ }
+
+ /**
+ * @see java.awt.datatransfer.Clipboard#getData
+ * @since 1.5
+ */
+ public Object getData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException {
+ if (flavor == null) {
+ throw new NullPointerException("flavor");
+ }
+
+ Transferable cntnts = getContextContents();
+ if (cntnts != null) {
+ return cntnts.getTransferData(flavor);
+ }
+
+ long format = 0;
+ byte[] data = null;
+ Transferable localeTransferable = null;
+
+ try {
+ openClipboard(null);
+
+ long[] formats = getClipboardFormats();
+ Long lFormat = DataTransferer.getInstance().
+ getFlavorsForFormats(formats, getDefaultFlavorTable()).get(flavor);
+
+ if (lFormat == null) {
+ throw new UnsupportedFlavorException(flavor);
+ }
+
+ format = lFormat.longValue();
+ data = getClipboardData(format);
+
+ if (DataTransferer.getInstance().isLocaleDependentTextFormat(format)) {
+ localeTransferable = createLocaleTransferable(formats);
+ }
+
+ } finally {
+ closeClipboard();
+ }
+
+ return DataTransferer.getInstance().
+ translateBytes(data, flavor, format, localeTransferable);
+ }
+
+ /**
+ * The clipboard must be opened.
+ *
+ * @since 1.5
+ */
+ protected Transferable createLocaleTransferable(long[] formats) throws IOException {
+ return null;
+ }
+
+ /**
+ * @throws IllegalStateException if the clipboard has not been opened
+ */
+ public void openClipboard(SunClipboard newOwner) {}
+ public void closeClipboard() {}
+
+ public abstract long getID();
+
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (AppContext.DISPOSED_PROPERTY_NAME.equals(evt.getPropertyName()) &&
+ Boolean.TRUE.equals(evt.getNewValue())) {
+ final AppContext disposedContext = (AppContext)evt.getSource();
+ lostOwnershipLater(disposedContext);
+ }
+ }
+
+ protected void lostOwnershipImpl() {
+ lostOwnershipLater(null);
+ }
+
+ /**
+ * Clears the clipboard state (contents, owner and contents context) and
+ * notifies the current owner that ownership is lost. Does nothing if the
+ * argument is not null
and is not equal to the current
+ * contents context.
+ *
+ * @param disposedContext the AppContext that is disposed or
+ * null
if the ownership is lost because another
+ * application acquired ownership.
+ */
+ protected void lostOwnershipLater(final AppContext disposedContext) {
+ final AppContext context = this.contentsContext;
+ if (context == null) {
+ return;
+ }
+
+ final Runnable runnable = new Runnable() {
+ public void run() {
+ final SunClipboard sunClipboard = SunClipboard.this;
+ ClipboardOwner owner = null;
+ Transferable contents = null;
+
+ synchronized (sunClipboard) {
+ final AppContext context = sunClipboard.contentsContext;
+
+ if (context == null) {
+ return;
+ }
+
+ if (disposedContext == null || context == disposedContext) {
+ owner = sunClipboard.owner;
+ contents = sunClipboard.contents;
+ sunClipboard.contentsContext = null;
+ sunClipboard.owner = null;
+ sunClipboard.contents = null;
+ sunClipboard.clearNativeContext();
+ context.removePropertyChangeListener
+ (AppContext.DISPOSED_PROPERTY_NAME, sunClipboard);
+ } else {
+ return;
+ }
+ }
+ if (owner != null) {
+ owner.lostOwnership(sunClipboard, contents);
+ }
+ }
+ };
+
+ SunToolkit.postEvent(context, new PeerEvent(this, runnable,
+ PeerEvent.PRIORITY_EVENT));
+ }
+
+ protected abstract void clearNativeContext();
+
+ protected abstract void setContentsNative(Transferable contents);
+
+ /**
+ * @since 1.5
+ */
+ protected long[] getClipboardFormatsOpenClose() {
+ try {
+ openClipboard(null);
+ return getClipboardFormats();
+ } finally {
+ closeClipboard();
+ }
+ }
+
+ /**
+ * Returns zero-length array (not null) if the number of available formats is zero.
+ *
+ * @throws IllegalStateException if formats could not be retrieved
+ */
+ protected abstract long[] getClipboardFormats();
+
+ protected abstract byte[] getClipboardData(long format) throws IOException;
+
+
+ private static Set formatArrayAsDataFlavorSet(long[] formats) {
+ return (formats == null) ? null :
+ DataTransferer.getInstance().
+ getFlavorsForFormatsAsSet(formats, getDefaultFlavorTable());
+ }
+
+
+ public synchronized void addFlavorListener(FlavorListener listener) {
+ if (listener == null) {
+ return;
+ }
+ AppContext appContext = AppContext.getAppContext();
+ Set flavorListeners = getFlavorListeners(appContext);
+ if (flavorListeners == null) {
+ flavorListeners = new HashSet<>();
+ appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, flavorListeners);
+ }
+ flavorListeners.add(listener);
+
+ if (numberOfFlavorListeners++ == 0) {
+ long[] currentFormats = null;
+ try {
+ openClipboard(null);
+ currentFormats = getClipboardFormats();
+ } catch (IllegalStateException exc) {
+ } finally {
+ closeClipboard();
+ }
+ currentDataFlavors = formatArrayAsDataFlavorSet(currentFormats);
+
+ registerClipboardViewerChecked();
+ }
+ }
+
+ public synchronized void removeFlavorListener(FlavorListener listener) {
+ if (listener == null) {
+ return;
+ }
+ Set flavorListeners = getFlavorListeners(AppContext.getAppContext());
+ if (flavorListeners == null){
+ //else we throw NullPointerException, but it is forbidden
+ return;
+ }
+ if (flavorListeners.remove(listener) && --numberOfFlavorListeners == 0) {
+ unregisterClipboardViewerChecked();
+ currentDataFlavors = null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Set getFlavorListeners(AppContext appContext) {
+ return (Set)appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
+ }
+
+ public synchronized FlavorListener[] getFlavorListeners() {
+ Set flavorListeners = getFlavorListeners(AppContext.getAppContext());
+ return flavorListeners == null ? new FlavorListener[0]
+ : flavorListeners.toArray(new FlavorListener[flavorListeners.size()]);
+ }
+
+ public boolean areFlavorListenersRegistered() {
+ return (numberOfFlavorListeners > 0);
+ }
+
+ protected abstract void registerClipboardViewerChecked();
+
+ protected abstract void unregisterClipboardViewerChecked();
+
+ /**
+ * Checks change of the DataFlavor
s and, if necessary,
+ * posts notifications on FlavorEvent
s to the
+ * AppContexts' EDTs.
+ * The parameter formats
is null iff we have just
+ * failed to get formats available on the clipboard.
+ *
+ * @param formats data formats that have just been retrieved from
+ * this clipboard
+ */
+ public void checkChange(long[] formats) {
+ Set prevDataFlavors = currentDataFlavors;
+ currentDataFlavors = formatArrayAsDataFlavorSet(formats);
+
+ if (Objects.equals(prevDataFlavors, currentDataFlavors)) {
+ // we've been able to successfully get available on the clipboard
+ // DataFlavors this and previous time and they are coincident;
+ // don't notify
+ return;
+ }
+
+ for (AppContext appContext : AppContext.getAppContexts()) {
+ if (appContext == null || appContext.isDisposed()) {
+ continue;
+ }
+ Set flavorListeners = getFlavorListeners(appContext);
+ if (flavorListeners != null) {
+ for (FlavorListener listener : flavorListeners) {
+ if (listener != null) {
+ PeerEvent peerEvent = new PeerEvent(this,
+ () -> listener.flavorsChanged(new FlavorEvent(SunClipboard.this)),
+ PeerEvent.PRIORITY_EVENT);
+ SunToolkit.postEvent(appContext, peerEvent);
+ }
+ }
+ }
+ }
+ }
+
+ public static FlavorTable getDefaultFlavorTable() {
+ return (FlavorTable) SystemFlavorMap.getDefaultFlavorMap();
+ }
+}