--- old/src/share/classes/java/awt/datatransfer/Clipboard.java 2014-03-18 19:41:32.000000000 +0400 +++ new/src/share/classes/java/awt/datatransfer/Clipboard.java 2014-03-18 19:41:32.000000000 +0400 @@ -27,14 +27,13 @@ import java.awt.EventQueue; +import java.util.Objects; import java.util.Set; import java.util.HashSet; import java.util.Arrays; import java.io.IOException; -import sun.awt.EventListenerAggregate; - /** * A class that implements a mechanism to transfer data using * cut/copy/paste operations. @@ -68,7 +67,7 @@ * * @since 1.5 */ - private EventListenerAggregate flavorListeners; + private final Set flavorListeners = new HashSet<>(); /** * A set of DataFlavors that is available on @@ -131,11 +130,7 @@ this.contents = contents; if (oldOwner != null && oldOwner != owner) { - EventQueue.invokeLater(new Runnable() { - public void run() { - oldOwner.lostOwnership(Clipboard.this, oldContents); - } - }); + EventQueue.invokeLater(() -> oldOwner.lostOwnership(Clipboard.this, oldContents)); } fireFlavorsChanged(); } @@ -261,9 +256,8 @@ if (listener == null) { return; } - if (flavorListeners == null) { + if (flavorListeners.isEmpty()) { currentDataFlavors = getAvailableDataFlavorSet(); - flavorListeners = new EventListenerAggregate(FlavorListener.class); } flavorListeners.add(listener); } @@ -286,7 +280,7 @@ * @since 1.5 */ public synchronized void removeFlavorListener(FlavorListener listener) { - if (listener == null || flavorListeners == null) { + if (listener == null) { return; } flavorListeners.remove(listener); @@ -305,8 +299,7 @@ * @since 1.5 */ public synchronized FlavorListener[] getFlavorListeners() { - return flavorListeners == null ? new FlavorListener[0] : - (FlavorListener[])flavorListeners.getListenersCopy(); + return flavorListeners.toArray(new FlavorListener[flavorListeners.size()]); } /** @@ -317,24 +310,14 @@ * @since 1.5 */ private void fireFlavorsChanged() { - if (flavorListeners == null) { - return; - } Set prevDataFlavors = currentDataFlavors; currentDataFlavors = getAvailableDataFlavorSet(); - if (prevDataFlavors.equals(currentDataFlavors)) { + if (Objects.equals(prevDataFlavors, currentDataFlavors)) { return; } - FlavorListener[] flavorListenerArray = - (FlavorListener[])flavorListeners.getListenersInternal(); - for (int i = 0; i < flavorListenerArray.length; i++) { - final FlavorListener listener = flavorListenerArray[i]; - EventQueue.invokeLater(new Runnable() { - public void run() { - listener.flavorsChanged(new FlavorEvent(Clipboard.this)); - } - }); - } + flavorListeners.forEach(listener -> + EventQueue.invokeLater(() -> + listener.flavorsChanged(new FlavorEvent(Clipboard.this)))); } /** --- old/src/share/classes/sun/awt/datatransfer/SunClipboard.java 2014-03-18 19:41:33.000000000 +0400 +++ new/src/share/classes/sun/awt/datatransfer/SunClipboard.java 2014-03-18 19:41:33.000000000 +0400 @@ -40,7 +40,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.Iterator; +import java.util.Objects; import java.util.Set; import java.util.HashSet; @@ -49,7 +49,6 @@ import sun.awt.AppContext; import sun.awt.PeerEvent; import sun.awt.SunToolkit; -import sun.awt.EventListenerAggregate; /** @@ -110,11 +109,7 @@ setContentsNative(contents); } finally { if (oldOwner != null && oldOwner != owner) { - EventQueue.invokeLater(new Runnable() { - public void run() { - oldOwner.lostOwnership(SunClipboard.this, oldContents); - } - }); + EventQueue.invokeLater(() -> oldOwner.lostOwnership(SunClipboard.this, oldContents)); } } } @@ -358,13 +353,12 @@ return; } AppContext appContext = AppContext.getAppContext(); - EventListenerAggregate contextFlavorListeners = (EventListenerAggregate) - appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY); - if (contextFlavorListeners == null) { - contextFlavorListeners = new EventListenerAggregate(FlavorListener.class); - appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, contextFlavorListeners); + Set flavorListeners = getFlavorListeners(appContext); + if (flavorListeners == null) { + flavorListeners = new HashSet<>(); + appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, flavorListeners); } - contextFlavorListeners.add(listener); + flavorListeners.add(listener); if (numberOfFlavorListeners++ == 0) { long[] currentFormats = null; @@ -385,25 +379,26 @@ if (listener == null) { return; } - AppContext appContext = AppContext.getAppContext(); - EventListenerAggregate contextFlavorListeners = (EventListenerAggregate) - appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY); - if (contextFlavorListeners == null){ + Set flavorListeners = getFlavorListeners(AppContext.getAppContext()); + if (flavorListeners == null){ //else we throw NullPointerException, but it is forbidden return; } - if (contextFlavorListeners.remove(listener) && - --numberOfFlavorListeners == 0) { + 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() { - EventListenerAggregate contextFlavorListeners = (EventListenerAggregate) - AppContext.getAppContext().get(CLIPBOARD_FLAVOR_LISTENER_KEY); - return contextFlavorListeners == null ? new FlavorListener[0] : - (FlavorListener[])contextFlavorListeners.getListenersCopy(); + Set flavorListeners = getFlavorListeners(AppContext.getAppContext()); + return flavorListeners == null ? new FlavorListener[0] + : flavorListeners.toArray(new FlavorListener[flavorListeners.size()]); } public boolean areFlavorListenersRegistered() { @@ -424,49 +419,32 @@ * @param formats data formats that have just been retrieved from * this clipboard */ - public void checkChange(long[] formats) { + public synchronized void checkChange(long[] formats) { Set prevDataFlavors = currentDataFlavors; currentDataFlavors = formatArrayAsDataFlavorSet(formats); - if ((prevDataFlavors != null) && (currentDataFlavors != null) && - prevDataFlavors.equals(currentDataFlavors)) { + 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; } - class SunFlavorChangeNotifier implements Runnable { - private final FlavorListener flavorListener; - - SunFlavorChangeNotifier(FlavorListener flavorListener) { - this.flavorListener = flavorListener; - } - - public void run() { - if (flavorListener != null) { - flavorListener.flavorsChanged(new FlavorEvent(SunClipboard.this)); - } - } - }; - - for (Iterator it = AppContext.getAppContexts().iterator(); it.hasNext();) { - AppContext appContext = (AppContext)it.next(); + for (AppContext appContext : AppContext.getAppContexts()) { if (appContext == null || appContext.isDisposed()) { continue; } - EventListenerAggregate flavorListeners = (EventListenerAggregate) - appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY); + Set flavorListeners = getFlavorListeners(appContext); if (flavorListeners != null) { - FlavorListener[] flavorListenerArray = - (FlavorListener[])flavorListeners.getListenersInternal(); - for (int i = 0; i < flavorListenerArray.length; i++) { - SunToolkit.postEvent(appContext, new PeerEvent(this, - new SunFlavorChangeNotifier(flavorListenerArray[i]), - PeerEvent.PRIORITY_EVENT)); + 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); + } } } } } - } --- old/src/share/classes/sun/awt/EventListenerAggregate.java 2014-03-18 19:41:34.000000000 +0400 +++ /dev/null 2014-03-18 19:41:34.000000000 +0400 @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2003, 2011, 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; - -import java.lang.reflect.Array; -import java.util.EventListener; - - -/** - * A class that assists in managing {@link java.util.EventListener}s of - * the specified type. Its instance holds an array of listeners of the same - * type and allows to perform the typical operations on the listeners. - * This class is thread-safe. - * - * @author Alexander Gerasimov - * - * @since 1.5 - */ -public class EventListenerAggregate { - - private EventListener[] listenerList; - - /** - * Constructs an EventListenerAggregate object. - * - * @param listenerClass the type of the listeners to be managed by this object - * - * @throws NullPointerException if listenerClass is - * null - * @throws ClassCastException if listenerClass is not - * assignable to java.util.EventListener - */ - public EventListenerAggregate(Class listenerClass) { - if (listenerClass == null) { - throw new NullPointerException("listener class is null"); - } - - listenerList = (EventListener[])Array.newInstance(listenerClass, 0); - } - - private Class getListenerClass() { - return listenerList.getClass().getComponentType(); - } - - /** - * Adds the listener to this aggregate. - * - * @param listener the listener to be added - * - * @throws ClassCastException if listener is not - * an instatce of listenerClass specified - * in the constructor - */ - public synchronized void add(EventListener listener) { - Class listenerClass = getListenerClass(); - - if (!listenerClass.isInstance(listener)) { // null is not an instance of any class - throw new ClassCastException("listener " + listener + " is not " + - "an instance of listener class " + listenerClass); - } - - EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass, listenerList.length + 1); - System.arraycopy(listenerList, 0, tmp, 0, listenerList.length); - tmp[listenerList.length] = listener; - listenerList = tmp; - } - - /** - * Removes a listener that is equal to the given one from this aggregate. - * equals() method is used to compare listeners. - * - * @param listener the listener to be removed - * - * @return true if this aggregate contained the specified - * listener; false otherwise - * - * @throws ClassCastException if listener is not - * an instatce of listenerClass specified - * in the constructor - */ - public synchronized boolean remove(EventListener listener) { - Class listenerClass = getListenerClass(); - - if (!listenerClass.isInstance(listener)) { // null is not an instance of any class - throw new ClassCastException("listener " + listener + " is not " + - "an instance of listener class " + listenerClass); - } - - for (int i = 0; i < listenerList.length; i++) { - if (listenerList[i].equals(listener)) { - EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass, - listenerList.length - 1); - System.arraycopy(listenerList, 0, tmp, 0, i); - System.arraycopy(listenerList, i + 1, tmp, i, listenerList.length - i - 1); - listenerList = tmp; - - return true; - } - } - - return false; - } - - /** - * Returns an array of all the listeners contained in this aggregate. - * The array is the data structure in which listeners are stored internally. - * The runtime type of the returned array is "array of listenerClass" - * (listenerClass has been specified as a parameter to - * the constructor of this class). - * - * @return all the listeners contained in this aggregate (an empty - * array if there are no listeners) - */ - public synchronized EventListener[] getListenersInternal() { - return listenerList; - } - - /** - * Returns an array of all the listeners contained in this aggregate. - * The array is a copy of the data structure in which listeners are stored - * internally. - * The runtime type of the returned array is "array of listenerClass" - * (listenerClass has been specified as a parameter to - * the constructor of this class). - * - * @return a copy of all the listeners contained in this aggregate (an empty - * array if there are no listeners) - */ - public synchronized EventListener[] getListenersCopy() { - return (listenerList.length == 0) ? listenerList : listenerList.clone(); - } - - /** - * Returns the number of lisetners in this aggregate. - * - * @return the number of lisetners in this aggregate - */ - public synchronized int size() { - return listenerList.length; - } - - /** - * Returns true if this aggregate contains no listeners, - * false otherwise. - * - * @return true if this aggregate contains no listeners, - * false otherwise - */ - public synchronized boolean isEmpty() { - return listenerList.length == 0; - } -}