package textbender.g.beans.beancontext; // Copyright 2001-2005, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Textbender Software"), to deal in the Textbender Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Textbender Software, and to permit persons to whom the Textbender Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Textbender Software. THE TEXTBENDER SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE TEXTBENDER SOFTWARE OR THE USE OR OTHER DEALINGS IN THE TEXTBENDER SOFTWARE. import java.beans.beancontext.*; import java.util.Iterator; import java.util.logging.*; /** BeanContextServices utilities. */ public final class BeanContextServicesX { private BeanContextServicesX() {} /** Registers a new service listener, * {@linkplain #fireUp firing it up} to the current service state. * * @param serviceSource to register the listener with * @param listener to register * @param fireUp if true, * listener is immediately {@linkplain #fireUp fired up} * to the current state; otherwise it is not */ public static void addBeanContextServicesListener( BeanContextServices serviceSource, BeanContextServicesListener listener, boolean fireUp ) { final Iterator serviceIterator; synchronized( serviceSource.globalHierarchyLock ) // sync for atomic copy of service state and registration, preventing duplicate or missed events during fire up { serviceIterator = serviceSource.getCurrentServiceClasses(); // this iterator is backed by a copy of the service class list in BeanContextServicesSupport, and I think this will be generally true for implementations of BeanContextServices, otherwise they would be useless in a threaded environment serviceSource.addBeanContextServicesListener( listener ); } if( fireUp ) fireUp( serviceIterator, listener, serviceSource ); // out of sync, to avoid deadlock with other threads requesting globalHierarchyLock, that are already holding a lock (might be any lock) required to complete fire up } /** Fires up a listener to the current service state. * This entails immediately re-firing BeanContextServiceAvailableEvents * for every service already present in the source. * All re-fired events will be sent to the listener before this method returns. * * @param listener to fire up * @param serviceSource to fire the listener up to */ public static void fireUp( BeanContextServicesListener listener, BeanContextServices serviceSource ) { fireUp( serviceSource.getCurrentServiceClasses(), listener, serviceSource ); } //// P r i v a t e /////////////////////////////////////////////////////////////////////// private static void fireUp( Iterator serviceIterator, BeanContextServicesListener listener, BeanContextServices serviceSource ){ while( serviceIterator.hasNext() ) { try { listener.serviceAvailable ( new BeanContextServiceAvailableEvent ( serviceSource, (Class)serviceIterator.next() ) ); } catch( Exception x ) { Logger.getLogger(BeanContextServicesX.class.getPackage().getName()).log( Level.WARNING, /*message*/"", x ); } } } }