001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.context.event;
018:
019: import java.util.Collection;
020: import java.util.LinkedHashSet;
021:
022: import org.springframework.beans.BeanUtils;
023: import org.springframework.context.ApplicationListener;
024: import org.springframework.core.CollectionFactory;
025:
026: /**
027: * Abstract implementation of the {@link ApplicationEventMulticaster} interface,
028: * providing the basic listener registration facility.
029: *
030: * <p>Doesn't permit multiple instances of the same listener by default,
031: * as it keeps listeners in a linked Set. The collection class used to hold
032: * ApplicationListener objects can be overridden through the "collectionClass"
033: * bean property.
034: *
035: * <p>Implementing ApplicationEventMulticaster's actual {@link #multicastEvent} method
036: * is left to subclasses. {@link SimpleApplicationEventMulticaster} simply multicasts
037: * all events to all registered listeners, invoking them in the calling thread.
038: * Alternative implementations could be more sophisticated in those respects.
039: *
040: * @author Juergen Hoeller
041: * @since 1.2.3
042: * @see #setCollectionClass
043: * @see #getApplicationListeners()
044: * @see SimpleApplicationEventMulticaster
045: */
046: public abstract class AbstractApplicationEventMulticaster implements
047: ApplicationEventMulticaster {
048:
049: /** Collection of ApplicationListeners */
050: private Collection applicationListeners = new LinkedHashSet();
051:
052: /**
053: * Set whether this multicaster should expect concurrent updates at runtime
054: * (i.e. after context startup finished). In case of concurrent updates,
055: * a copy-on-write strategy is applied, keeping iteration (for multicasting)
056: * without synchronization while still making listener updates thread-safe.
057: */
058: public void setConcurrentUpdates(boolean concurrent) {
059: Collection newColl = (concurrent ? CollectionFactory
060: .createCopyOnWriteSet() : new LinkedHashSet());
061: // Add all previously registered listeners (usually none).
062: newColl.addAll(this .applicationListeners);
063: this .applicationListeners = newColl;
064: }
065:
066: /**
067: * Specify the collection class to use. Can be populated with a fully
068: * qualified class name when defined in a Spring application context.
069: * <p>Default is a linked HashSet, keeping the registration order.
070: * Note that a Set class specified will not permit multiple instances
071: * of the same listener, while a List class will allow for registering
072: * the same listener multiple times.
073: */
074: public void setCollectionClass(Class collectionClass) {
075: if (collectionClass == null) {
076: throw new IllegalArgumentException(
077: "'collectionClass' must not be null");
078: }
079: if (!Collection.class.isAssignableFrom(collectionClass)) {
080: throw new IllegalArgumentException(
081: "'collectionClass' must implement [java.util.Collection]");
082: }
083: // Create desired collection instance.
084: Collection newColl = (Collection) BeanUtils
085: .instantiateClass(collectionClass);
086: // Add all previously registered listeners (usually none).
087: newColl.addAll(this .applicationListeners);
088: this .applicationListeners = newColl;
089: }
090:
091: public void addApplicationListener(ApplicationListener listener) {
092: this .applicationListeners.add(listener);
093: }
094:
095: public void removeApplicationListener(ApplicationListener listener) {
096: this .applicationListeners.remove(listener);
097: }
098:
099: public void removeAllListeners() {
100: this .applicationListeners.clear();
101: }
102:
103: /**
104: * Return the current Collection of ApplicationListeners.
105: * <p>Note that this is the raw Collection of ApplicationListeners,
106: * potentially modified when new listeners get registered or
107: * existing ones get removed. This Collection is not a snapshot copy.
108: * @return a Collection of ApplicationListeners
109: * @see org.springframework.context.ApplicationListener
110: */
111: protected Collection getApplicationListeners() {
112: return this.applicationListeners;
113: }
114:
115: }
|