All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.exolab.castor.util.EventListenerList Maven / Gradle / Ivy

Go to download

The core XML data binding framework with support for marshalling Java objects to and unmarshalling from XML documents.

The newest version!
/**
 * Redistribution and use of this software and associated documentation ("Software"), with or
 * without modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
 * must also contain a copy of this document.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or other materials provided with
 * the distribution.
 *
 * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
 * without prior written permission of Intalio, Inc. For written permission, please contact
 * [email protected].
 *
 * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
 * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
 * Intalio, Inc.
 *
 * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
 *
 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * Contribution(s):
 *
 * - Jeff Norris, [email protected] - Original Author
 *
 * $Id$
 */

package org.exolab.castor.util;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.EventListener;

/**
 * 

* This class is an efficient repository for EventListeners based on javax.swing.EventListenerList. *

* *

* This modification of javax.swing.EventListenerList retains the core functionality of that class * but changes the basic API and adds a few more features, as summarized below: *

* *

    *
  1. javax.swing.EventListenerList requires all listeners to be added in conjunction with a class * object that identified the type of the listener. This implementation's add methods simply take * the listener object. * *
  2. The listener list returned from javax.swing.EventListenerList had to be iterated over in a * cumbersome manner because the listeners were stored along with their Class objects in the array. * Since listener classes are not stored in this listener list, the returned listener array can be * iterated over normally (1 element at a time). * *
  3. The remove method in javax.swing.EventListenerList had return type "void". This * implementation's remove method returns true if the specified listener was found in the listener * array and false otherwise. * *
  4. This implementation adds {@link #add(EventListener, int)}, which allows the addition of a * listener at a specific position in the array. * *
  5. The add and remove methods in this implementation throw IllegalArgumentExceptions when their * arguments are null. *
* *

* As is the case with javax.swing.EventListenerList, this class provides multi-threaded safety * through a copy-on-modify strategy. It is optimized to provide high performance when events are * being fired, with slightly slower performance than the Collection API when listeners are being * added and removed. Like its predecessor, this class will never return a null array from * getListenerList. *

* *

* The most important thing to keep in mind when using this class is that the array returned by * getListenerList is the actual internal array of this class and MUST NOT BE MODIFIED UNDER ANY * CIRCUMSTANCES. Below is an example of how to use this class, borrowed (and slightly modified) * from the javax.swing.EventListenerList documentation: *

* *

* Usage example: Say one is defining a class that sends out FooEvents, and one wants to allow users * of the class to register FooListeners and receive notification when FooEvents occur. The * following should be added to the class definition: *

* *
 * EventListenerList listenerList = new EventListenerList();
 * FooEvent fooEvent = null;
 *
 * public void addFooListener(FooListener l) {
 *   listenerList.add(l);
 * }
 *
 * public void removeFooListener(FooListener l) {
 *   listenerList.remove(l);
 * }
 *
 * // Notify all listeners that have registered interest for
 * // notification on this event type. The event instance
 * // is lazily created using the parameters passed into
 * // the fire method.
 *
 * protected void fireFooXXX() {
 *   // Guaranteed to return a non-null array
 *   EventListener[] listeners = listenerList.getListenerList();
 *   // Process the listeners last to first, notifying
 *   // those that are interested in this event
 *   for (int i = 0; i < listeners.length; i++) {
 *     // Lazily create the event:
 *     if (fooEvent == null)
 *       fooEvent = new FooEvent(this);
 *     ((FooListener) listeners[i]).fooXXX(fooEvent);
 *   }
 * }
 * 
* *

* foo should be changed to the appropriate name, and fireFooXxx to the appropriate method name. One * fire method should exist for each notification method in the FooListener interface. *

* *

* The authors of javax.swing.EventListenerList are Georges Saab, Hans Muller, and James Gosling. *

* * @author Jeff Norris * @version $Revision$ $Date: 2005-12-13 14:58:48 -0700 (Tue, 13 Dec 2005) $ */ public class EventListenerList implements Serializable { /** SerialVersionUID */ private static final long serialVersionUID = 4472874989562384564L; /** * A null array to be shared by all empty listener lists */ private final static EventListener[] NULL_ARRAY = new EventListener[0]; /** * The internal list of listeners that is returned from getListenerList */ protected transient EventListener[] listenerList = NULL_ARRAY; /** *

* Passes back the event listener list as an array of EventListeners. *

* *

* Note that for performance reasons, this implementation passes back the actual data structure in * which the listener data is stored internally! This method is guaranteed to pass back a non-null * array, so that no null-checking is required in fire methods. A zero-length array of Object will * be returned if there are currently no listeners. *

* * WARNING!!! Absolutely NO modification of the data contained in this array should be made -- if * any such manipulation is necessary, it should be done on a copy of the array returned rather * than the array itself. */ public EventListener[] getListenerList() { return listenerList; } /** *

* Returns the total number of listeners in this listener list. *

* */ public int getListenerCount() { return listenerList.length; } /** *

* Adds the listener to the end of the listener list. *

* * @param newListener the listener to be added * @exception IllegalArgumentException if the specified newListener is null */ public synchronized void add(EventListener newListener) { if (newListener == null) throw new IllegalArgumentException("Listener to add must not be null."); if (listenerList == NULL_ARRAY) { // if this is the first listener added, // initialize the lists listenerList = new EventListener[] {newListener}; } else { // Otherwise copy the array and add the new listener int oldLength = listenerList.length; EventListener[] tmp = new EventListener[oldLength + 1]; System.arraycopy(listenerList, 0, tmp, 0, oldLength); tmp[oldLength] = newListener; listenerList = tmp; } } /** *

* Adds the listener at the specified index in the listener list. *

* * @param newListener the listener to be added * @exception IllegalArgumentException if the specified newListener is null, or the specified * index is less than zero or greater than the length of the listener list array. */ public synchronized void add(EventListener newListener, int index) { if (newListener == null) throw new IllegalArgumentException("Listener to add must not be null."); if ((index < 0) || (index > listenerList.length)) throw new IllegalArgumentException("Index to add listener (" + index + ") is out of bounds. List length is " + listenerList.length); if (listenerList == NULL_ARRAY) { // if this is the first listener added, initialize the lists listenerList = new EventListener[] {newListener}; } else { // Otherwise copy the array and add the new listener int oldLength = listenerList.length; EventListener[] tmp = new EventListener[oldLength + 1]; // Copy up to the index where the new listener should go System.arraycopy(listenerList, 0, tmp, 0, index); // Skip a cell and copy the rest of the list System.arraycopy(listenerList, index, tmp, index + 1, oldLength - index); // Insert the new listener tmp[index] = newListener; listenerList = tmp; } } /** * Removes the listener as a listener of the specified type. * * @param listenerToRemove the listener to be removed * @exception IllegalArgumentException if the specified listener is null */ public synchronized boolean remove(EventListener listenerToRemove) { if (listenerToRemove == null) throw new IllegalArgumentException("Listener to remove must " + "not be null."); // Is listenerToRemove on the list? int index = -1; for (int i = listenerList.length - 1; i >= 0; i--) { if (listenerList[i].equals(listenerToRemove) == true) { index = i; break; } } // If so, remove it if (index != -1) { EventListener[] tmp = new EventListener[listenerList.length - 1]; // Copy the list up to index System.arraycopy(listenerList, 0, tmp, 0, index); // Copy from one past the index, up to the end of tmp (which is // one element shorter than the old list) if (index < tmp.length) System.arraycopy(listenerList, index + 1, tmp, index, tmp.length - index); // set the listener array to the new array or null listenerList = (tmp.length == 0) ? NULL_ARRAY : tmp; return true; } return false; } // Serialization support. private void writeObject(ObjectOutputStream s) throws IOException { Object[] lList = listenerList; s.defaultWriteObject(); // Save the non-null event listeners: for (int i = 0; i < lList.length; i += 1) { EventListener l = (EventListener) lList[i]; if ((l != null) && (l instanceof Serializable)) { s.writeObject(l); } } s.writeObject(null); } private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { listenerList = NULL_ARRAY; s.defaultReadObject(); EventListener listenerOrNull; while (null != (listenerOrNull = (EventListener) s.readObject())) { add(listenerOrNull); } } /** * Returns a string representation of the EventListenerList. */ public String toString() { Object[] lList = listenerList; String s = "EventListenerList: "; s += lList.length + " listeners: "; for (int i = 0; i < lList.length; i++) { s += " listener " + lList[i + 1]; } return s; } } // -- class: EventListenerList




© 2015 - 2024 Weber Informatics LLC | Privacy Policy