1 /* 2 * Copyright (c) 2003, 2011, 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<? extends EventListener> listenerClass) { 57 if (listenerClass == null) { 58 throw new NullPointerException("listener class is null"); 59 } 60 61 listenerList = (EventListener[])Array.newInstance(listenerClass, 0); 62 } 63 64 private Class<?> getListenerClass() { 65 return listenerList.getClass().getComponentType(); 66 } 67 68 /** 69 * Adds the listener to this aggregate. 70 * 71 * @param listener the listener to be added 72 * 73 * @throws ClassCastException if <code>listener</code> is not 74 * an instatce of <code>listenerClass</code> specified 75 * in the constructor 76 */ 77 public synchronized void add(EventListener listener) { 78 Class<?> listenerClass = getListenerClass(); 79 80 if (!listenerClass.isInstance(listener)) { // null is not an instance of any class 81 throw new ClassCastException("listener " + listener + " is not " + 82 "an instance of listener class " + listenerClass); 83 } 84 85 EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass, listenerList.length + 1); 86 System.arraycopy(listenerList, 0, tmp, 0, listenerList.length); 87 tmp[listenerList.length] = listener; 88 listenerList = tmp; 89 } 90 91 /** 92 * Removes a listener that is equal to the given one from this aggregate. 93 * <code>equals()</code> method is used to compare listeners. 94 * 95 * @param listener the listener to be removed 96 * 97 * @return <code>true</code> if this aggregate contained the specified 98 * <code>listener</code>; <code>false</code> otherwise 99 * 100 * @throws ClassCastException if <code>listener</code> is not 101 * an instatce of <code>listenerClass</code> specified 102 * in the constructor 103 */ 104 public synchronized boolean remove(EventListener listener) { 105 Class<?> listenerClass = getListenerClass(); 106 107 if (!listenerClass.isInstance(listener)) { // null is not an instance of any class 108 throw new ClassCastException("listener " + listener + " is not " + 109 "an instance of listener class " + listenerClass); 110 } 111 112 for (int i = 0; i < listenerList.length; i++) { 113 if (listenerList[i].equals(listener)) { 114 EventListener[] tmp = (EventListener[])Array.newInstance(listenerClass, 115 listenerList.length - 1); 116 System.arraycopy(listenerList, 0, tmp, 0, i); 117 System.arraycopy(listenerList, i + 1, tmp, i, listenerList.length - i - 1); 118 listenerList = tmp; 119 120 return true; 121 } 122 } 123 124 return false; 125 } 126 127 /** 128 * Returns an array of all the listeners contained in this aggregate. 129 * The array is the data structure in which listeners are stored internally. 130 * The runtime type of the returned array is "array of <code>listenerClass</code>" 131 * (<code>listenerClass</code> has been specified as a parameter to 132 * the constructor of this class). 133 * 134 * @return all the listeners contained in this aggregate (an empty 135 * array if there are no listeners) 136 */ 137 public synchronized EventListener[] getListenersInternal() { 138 return listenerList; 139 } 140 141 /** 142 * Returns an array of all the listeners contained in this aggregate. 143 * The array is a copy of the data structure in which listeners are stored 144 * internally. 145 * The runtime type of the returned array is "array of <code>listenerClass</code>" 146 * (<code>listenerClass</code> has been specified as a parameter to 147 * the constructor of this class). 148 * 149 * @return a copy of all the listeners contained in this aggregate (an empty 150 * array if there are no listeners) 151 */ 152 public synchronized EventListener[] getListenersCopy() { 153 return (listenerList.length == 0) ? listenerList : listenerList.clone(); 154 } 155 156 /** 157 * Returns the number of lisetners in this aggregate. 158 * 159 * @return the number of lisetners in this aggregate 160 */ 161 public synchronized int size() { 162 return listenerList.length; 163 } 164 165 /** 166 * Returns <code>true</code> if this aggregate contains no listeners, 167 * <code>false</code> otherwise. 168 * 169 * @return <code>true</code> if this aggregate contains no listeners, 170 * <code>false</code> otherwise 171 */ 172 public synchronized boolean isEmpty() { 173 return listenerList.length == 0; 174 } 175 }