From a26b4cf776ffe95d2d09f16e80d591910b9117f9 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 5 Aug 2009 20:06:04 +0000 Subject: [PATCH] merged r2368 changes for AbstractDispatcher's handler set --- .../dispatcher/AbstractDispatcher.java | 35 ++++---- .../dispatcher/OrderedAwareLinkedHashSet.java | 84 ++++++++++++++----- 2 files changed, 83 insertions(+), 36 deletions(-) diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/dispatcher/AbstractDispatcher.java b/org.springframework.integration/src/main/java/org/springframework/integration/dispatcher/AbstractDispatcher.java index eee5322726..20582165d6 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/dispatcher/AbstractDispatcher.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/dispatcher/AbstractDispatcher.java @@ -16,7 +16,7 @@ package org.springframework.integration.dispatcher; -import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; @@ -25,17 +25,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.integration.message.MessageHandler; -import org.springframework.util.StringUtils; /** * Base class for {@link MessageDispatcher} implementations. *

- * The subclasses implement the actual dispatching strategy, but this base - * class manages the registration of {@link MessageHandler}s. Although the - * implemented dispatching strategies may invoke handles in different ways - * (e.g. round-robin vs. failover), this class does maintain the order of the - * underlying collection. See the {@link OrderedAwareLinkedHashSet} for more - * detail. + * The subclasses implement the actual dispatching strategy, but this base class + * manages the registration of {@link MessageHandler}s. Although the implemented + * dispatching strategies may invoke handles in different ways (e.g. round-robin + * vs. failover), this class does maintain the order of the underlying + * collection. See the {@link OrderedAwareLinkedHashSet} for more detail. * * @author Mark Fisher * @author Iwein Fuld @@ -49,25 +47,34 @@ public abstract class AbstractDispatcher implements MessageDispatcher { /** - * Returns a copied, unmodifiable List of this dispatcher's handlers. - * This is provided for access by subclasses. + * Returns a copied, unmodifiable List of this dispatcher's handlers. This + * is provided for access by subclasses. */ - @SuppressWarnings("unchecked") protected List getHandlers() { - return Collections.unmodifiableList(new ArrayList(this.handlers)); + return Collections.unmodifiableList(Arrays.asList( + this.handlers.toArray(new MessageHandler[this.handlers.size()]))); } + /** + * Add the handler to the internal Set. + * + * @return the result of {@link Set#add(Object)} + */ public boolean addHandler(MessageHandler handler) { return this.handlers.add(handler); } + /** + * Remove the handler from the internal handler Set. + * + * @return the result of {@link Set#remove(Object)} + */ public boolean removeHandler(MessageHandler handler) { return this.handlers.remove(handler); } public String toString() { - String handlerList = StringUtils.collectionToCommaDelimitedString(this.handlers); - return this.getClass().getSimpleName() + " with handlers: " + handlerList; + return this.getClass().getSimpleName() + " with handlers: " + this.handlers.toString(); } } diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/dispatcher/OrderedAwareLinkedHashSet.java b/org.springframework.integration/src/main/java/org/springframework/integration/dispatcher/OrderedAwareLinkedHashSet.java index b6e01b59c8..5e289c3a50 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/dispatcher/OrderedAwareLinkedHashSet.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/dispatcher/OrderedAwareLinkedHashSet.java @@ -20,14 +20,16 @@ import java.util.Collection; import java.util.Comparator; import java.util.LinkedHashSet; import java.util.Set; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import org.springframework.core.OrderComparator; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; /** * Special Set that maintains the following semantics: @@ -39,8 +41,12 @@ import org.springframework.util.CollectionUtils; * order but themselves do not equal to one another the more recent addition will be placed to the * right of (appended next to) the existing element with the same order, thus preserving the order * of the insertion and maintaining {@link LinkedHashSet} semantics for the un-ordered elements. + *

+ * The class is package-protected and only intended for use by the AbstractDispatcher. It + * must enforce safe concurrent access for all usage by the dispatcher. * * @author Oleg Zhurakousky + * @author Mark Fisher * @since 1.0.3 */ @SuppressWarnings({"unchecked", "serial"}) @@ -48,7 +54,11 @@ class OrderedAwareLinkedHashSet extends LinkedHashSet { private final OrderComparator comparator = new OrderComparator(); - private final Lock lock = new ReentrantLock(); + private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); + + private final ReadLock readLock = rwl.readLock(); + + private final WriteLock writeLock = rwl.writeLock(); /** @@ -58,17 +68,19 @@ class OrderedAwareLinkedHashSet extends LinkedHashSet { */ public boolean add(E o) { Assert.notNull(o,"Can not add NULL object"); - lock.lock(); + writeLock.lock(); try { boolean present = false; if (o instanceof Ordered){ present = this.addOrderedElement((Ordered) o); - } else { + } + else { present = super.add(o); } return present; - } finally { - lock.unlock(); + } + finally { + writeLock.unlock(); } } @@ -77,14 +89,15 @@ class OrderedAwareLinkedHashSet extends LinkedHashSet { */ public boolean addAll(Collection c) { Assert.notNull(c,"Can not merge with NULL set"); - lock.lock(); + writeLock.lock(); try { for (E object : c) { this.add(object); } return true; - } finally { - lock.unlock(); + } + finally { + writeLock.unlock(); } } @@ -92,11 +105,12 @@ class OrderedAwareLinkedHashSet extends LinkedHashSet { * {@inheritDoc} */ public boolean remove(Object o) { - lock.lock(); + writeLock.lock(); try { return super.remove(o); - } finally { - lock.unlock(); + } + finally { + writeLock.unlock(); } } @@ -107,39 +121,65 @@ class OrderedAwareLinkedHashSet extends LinkedHashSet { if (CollectionUtils.isEmpty(c)){ return false; } - lock.lock(); + writeLock.lock(); try { return super.removeAll(c); - } finally { - lock.unlock(); + } + finally { + writeLock.unlock(); + } + } + + @Override + public T[] toArray(T[] a) { + readLock.lock(); + try { + return super.toArray(a); + } + finally { + readLock.unlock(); + } + } + + @Override + public String toString() { + readLock.lock(); + try { + return StringUtils.collectionToCommaDelimitedString(this); + } + finally { + readLock.unlock(); } } private boolean addOrderedElement(Ordered adding) { boolean added = false; E[] tempUnorderedElements = (E[]) this.toArray(); - if (super.contains(adding)){ + if (super.contains(adding)) { return false; } super.clear(); - if (tempUnorderedElements.length == 0){ + if (tempUnorderedElements.length == 0) { added = super.add((E) adding); - } else { + } + else { Set tempSet = new LinkedHashSet(); for (E current : tempUnorderedElements) { if (current instanceof Ordered) { if (this.comparator.compare(adding, current) < 0) { added = super.add((E) adding); super.add(current); - } else { + } + else { super.add(current); } - } else { + } + else { tempSet.add(current); } } - if (!added){ + if (!added) { added = super.add((E) adding); } for (Object object : tempSet) {