/* * JBoss, Home of Professional Open Source. * Copyright 2006, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ //package org.gjt.lindfors.util; Taken from Juha Lindfors implementation as stated in package org.jboss.verifier.event; /* * Class org.jboss.verifier.event.EventGeneratorSupport (refer Class org.gjt.lindfors.util.EventGeneratorSupport at gjt.org) * Copyright (C) 1999 Juha Lindfors * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * This package and its source code is available at www.gjt.org * $Id: EventGeneratorSupport.java 85945 2009-03-16 19:45:12Z dimitris@jboss.org $ * * You can reach the author by sending email to jpl@gjt.org or * directly to jplindfo@helsinki.fi. */ // standard imports import java.util.*; import java.awt.*; import java.io.*; // dependencies to non-standard packages and classes /** * Support class for objects implementing the * {@link org.gjt.lindfors.util.EventGenerator EventGenerator} interface. * Contains implementations for addListener, removeListener, and hasListeners. * * <p> * * Every effort has been made to try to achieve thread-safety in * EventGeneratorSupport class. Of course, this doesn't mean * nasty race conditions and dead locks don't exist. I'm just * not aware of them :) * * <p> * * For more detailed documentation, refer to the * <a href="http://www.gjt.org/%7ejpl/org_gjt_lindfors_util/index.html"> * * Util Library Tutorial * * </a> and * * <a href="http://www.gjt.org/%7ejpl/org_gjt_lindfors_util/specs/index.html"> * * Util Library Specifications * * </a>. See Also: * * <a href="http://www.artima.com/designtechniques/index.html"> * * The Event Generator Idiom * * </a> by Bill Venners. * * * @see org.gjt.lindfors.util.EventGenerator * * @author Juha Lindfors * @version $Revision: 85945 $ * @since JDK1.1 */ public abstract class EventGeneratorSupport implements Serializable, Cloneable{ /* * [TODO] Implement different algorithms for listener notification. Use the * one implemented in this class as default, and implement high * performance notifications. Use strategy pattern to allow any * number of algorithms to be added. * * [TODO] write performance tests to compare the implementations * * [TODO] Could use Doug Lea's latch implementation here. Prettier than * using a mutex :P * * [TODO] The use of this class could be used as an example of bridge. * Also, the concrete implementations usually act as adapters (not * allowing just any listener to be added, but a specific type). * Can subclassing be used as an adapter pattern? */ /** * Vector for storing the registered listeners. Vector will use lazy * instantiation and will be constructed only upon request. To ensure * proper behaviour in a multi-threaded environment, use the private * getListInstance method any time you need a reference to this vector. */ private transient Vector list = null; /** * Clone of listener list. This clone is used as a snapshot of the listener * list. The clone is updated every time a listener is either registered * or unregistered. This way we can avoid cloning the listener list for * the getListeners method call which is usually called by the event * firing methods. Since we don't have to clone the listener list for every * event notification, we gain a significantly better performance. */ private transient Vector clone = null; /** * Mutex lock for instantiating the listener collection. */ private transient final boolean[] MUTEX = new boolean[0]; /** * Always use this method to get a reference to listener collection. * This guarantees thread safety. */ private Vector getListInstance() { synchronized (MUTEX) { if (list == null) { list = new Vector(); clone = (Vector)list.clone(); } } return list; } /** * Constructs support object. */ public EventGeneratorSupport() {} /** * Checks if any registered listeners exist. * * @return true if one or more listeners exist, false otherwise */ public boolean hasListeners() { if (list == null) // lazy list, not instantiated return false; if (list.size() == 0) // instantiated but empty return false; return true; } /** * Returns the listeners registered to this object. * * @return enumeration of registered listener objects */ protected Enumeration getListeners() { if (list == null) return new Enumeration() { public boolean hasMoreElements() { return false; } public Object nextElement() { return null; } }; Vector v = (Vector)list.clone(); return v.elements(); } /** * Registers a new listener to this object. Duplicate listeners are * discarded. * * <p> * * This method is marked as protected and is supposed to be used only by * the concrete implementations of generator support classes. The concrete * subclasses must ensure only the correct type of listeners are allowed * to register, as this method allows any listener to be added, therefore * not being type safe. * * @param listener the listener object */ protected void addListener(EventListener listener) { synchronized (MUTEX) { Vector v = getListInstance(); if (!v.contains(listener)) v.addElement(listener); } } /** * Unregisters a listener from this object. It is safe to attempt to * unregister non-existant listeners. * * @param listener the listener object */ protected void removeListener(EventListener listener) { if (list != null) { list.removeElement(listener); } } /** * Returns a string representation of this EventGeneratorSupport object. * * <p> * * The output will be similar to the following form:<br> * <pre> * EventGeneratorSupport[Registered Listeners=1] * </pre> */ public String toString() { int count; // don't want to instantiate listener just to tell it has zero elements if (list == null) count = 0; else count = getListInstance().size(); return Library.getClassName(this) + "[Registered Listeners=" + count + "]"; } /** * [PENDING] */ public Component toComponent() { // [FIXME] this exception class has disappeared! //throw new UnsupportedOperationException("not implemented yet."); return null; } /** * [PENDING] */ public Object clone() { // [FIXME] this exception class has disappeared! //throw new UnsupportedOperationException("not implemented yet."); return null; } }