1 /* 2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt; 27 28 import java.lang.reflect.Array; 29 import java.util.EventListener; 30 31 32 /** 33 * A class that assists in managing {@link java.util.EventListener}s of 34 * the specified type. Its instance holds an array of listeners of the same 35 * type and allows to perform the typical operations on the listeners. 36 * This class is thread-safe. 37 * 38 * @author Alexander Gerasimov 39 * 40 * @since 1.5 41 */ 42 public class EventListenerAggregate { 43 44 private EventListener[] listenerList; 45 46 /** 47 * Constructs an <code>EventListenerAggregate</code> object. 48 * 49 * @param listenerClass the type of the listeners to be managed by this object 50 * 51 * @throws NullPointerException if <code>listenerClass</code> is 52 * <code>null</code> 53 * @throws ClassCastException if <code>listenerClass</code> is not 54 * assignable to <code>java.util.EventListener</code> 55 */ 56 public EventListenerAggregate(Class listenerClass) { 57 if (listenerClass == null) { 58 throw new NullPointerException("listener class is null"); 59 } 60 61 if (!EventListener.class.isAssignableFrom(listenerClass)) { 62 throw new ClassCastException("listener class " + listenerClass + 63 " is not assignable to EventListener"); 64 } 65 66 listenerList = (EventListener[])Array.newInstance(listenerClass, 0); 67 } 68 69 private Class getListenerClass() { 70 return listenerList.getClass().getComponentType(); 71 } 72 73 /** 74 * Adds the listener to this aggregate. 75 * 76 * @param listener the listener to be added 77 * 78 * @throws ClassCastException if <code>listener</code> is not 79 * an instatce of <code>listenerClass</code> specified 80 * in the constructor 81 */ 82 public synchronized void add(EventListener listener) { 83 Class listenerClass = getListenerClass(); 84 85 if (!listenerClass.isInstance(listener)) { // null is not an instance of any class 86 throw new ClassCastException("listener " + listener + " is not " + 87 "an instance of listener class " + listenerClass); 88 } 89 90 EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass, listenerList.length + 1); 91 System.arraycopy(listenerList, 0, tmp, 0, listenerList.length); 92 tmp[listenerList.length] = listener; 93 listenerList = tmp; 94 } 95 96 /** 97 * Removes a listener that is equal to the given one from this aggregate. 98 * <code>equals()</code> method is used to compare listeners. 99 * 100 * @param listener the listener to be removed 101 * 102 * @return <code>true</code> if this aggregate contained the specified 103 * <code>listener</code>; <code>false</code> otherwise 104 * 105 * @throws ClassCastException if <code>listener</code> is not 106 * an instatce of <code>listenerClass</code> specified 107 * in the constructor 108 */ 109 public synchronized boolean remove(EventListener listener) { 110 Class listenerClass = getListenerClass(); 111 112 if (!listenerClass.isInstance(listener)) { // null is not an instance of any class 113 throw new ClassCastException("listener " + listener + " is not " + 114 "an instance of listener class " + listenerClass); 115 } 116 117 for (int i = 0; i < listenerList.length; i++) { 118 if (listenerList[i].equals(listener)) { 119 EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass, 120 listenerList.length - 1); 121 System.arraycopy(listenerList, 0, tmp, 0, i); 122 System.arraycopy(listenerList, i + 1, tmp, i, listenerList.length - i - 1); 123 listenerList = tmp; 124 125 return true; 126 } 127 } 128 129 return false; 130 } 131 132 /** 133 * Returns an array of all the listeners contained in this aggregate. 134 * The array is the data structure in which listeners are stored internally. 135 * The runtime type of the returned array is "array of <code>listenerClass</code>" 136 * (<code>listenerClass</code> has been specified as a parameter to 137 * the constructor of this class). 138 * 139 * @return all the listeners contained in this aggregate (an empty 140 * array if there are no listeners) 141 */ 142 public synchronized EventListener[] getListenersInternal() { 143 return listenerList; 144 } 145 146 /** 147 * Returns an array of all the listeners contained in this aggregate. 148 * The array is a copy of the data structure in which listeners are stored 149 * internally. 150 * The runtime type of the returned array is "array of <code>listenerClass</code>" 151 * (<code>listenerClass</code> has been specified as a parameter to 152 * the constructor of this class). 153 * 154 * @return a copy of all the listeners contained in this aggregate (an empty 155 * array if there are no listeners) 156 */ 157 public synchronized EventListener[] getListenersCopy() { 158 return (listenerList.length == 0) ? listenerList : (EventListener[])listenerList.clone(); 159 } 160 161 /** 162 * Returns the number of lisetners in this aggregate. 163 * 164 * @return the number of lisetners in this aggregate 165 */ 166 public synchronized int size() { 167 return listenerList.length; 168 } 169 170 /** 171 * Returns <code>true</code> if this aggregate contains no listeners, 172 * <code>false</code> otherwise. 173 * 174 * @return <code>true</code> if this aggregate contains no listeners, 175 * <code>false</code> otherwise 176 */ 177 public synchronized boolean isEmpty() { 178 return listenerList.length == 0; 179 } 180 }