Author: trustin
Date: Wed Nov 14 03:55:12 2007
New Revision: 594841
URL: http://svn.apache.org/viewvc?rev=594841&view=rev
Log:
Made sure DefaultIoFilterChainBuilder.setFilters to accept only ordered maps.
Modified:
mina/trunk/core/src/main/java/org/apache/mina/common/DefaultIoFilterChainBuilder.java
Modified:
mina/trunk/core/src/main/java/org/apache/mina/common/DefaultIoFilterChainBuilder.java
URL:
http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/common/DefaultIoFilterChainBuilder.java?rev=594841&r1=594840&r2=594841&view=diff
==============================================================================
---
mina/trunk/core/src/main/java/org/apache/mina/common/DefaultIoFilterChainBuilder.java
(original)
+++
mina/trunk/core/src/main/java/org/apache/mina/common/DefaultIoFilterChainBuilder.java
Wed Nov 14 03:55:12 2007
@@ -21,14 +21,18 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
+import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.mina.common.IoFilter.NextFilter;
import org.apache.mina.common.IoFilterChain.Entry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* The default implementation of [EMAIL PROTECTED] IoFilterChainBuilder} which
is useful
@@ -55,6 +59,8 @@
* @version $Rev$, $Date$
*/
public class DefaultIoFilterChainBuilder implements IoFilterChainBuilder {
+
+ private final Logger logger = LoggerFactory.getLogger(getClass());
private final List<Entry> entries;
/**
@@ -317,14 +323,22 @@
/**
* Clears the current list of filters and adds the specified
- * filter mapping to this builder. Please make sure to use a [EMAIL
PROTECTED] Map}
- * implementation that iterated the filter mapping in the order of addition
- * such as [EMAIL PROTECTED] LinkedHashMap}.
+ * filter mapping to this builder. Please note that you must specify
+ * a [EMAIL PROTECTED] Map} implementation that iterates the filter
mapping in the
+ * order of insertion such as [EMAIL PROTECTED] LinkedHashMap}.
Otherwise, it will
+ * throw an [EMAIL PROTECTED] IllegalArgumentException}.
*/
- public synchronized void setFilters(Map<String, ? extends IoFilter>
filters) {
+ public void setFilters(Map<String, ? extends IoFilter> filters) {
if (filters == null) {
throw new NullPointerException("filters");
}
+
+ if (!isOrderedMap(filters)) {
+ throw new IllegalArgumentException(
+ "filters is not an ordered map. Please try " +
+ LinkedHashMap.class.getName() + ".");
+ }
+
filters = new LinkedHashMap<String, IoFilter>(filters);
for (Map.Entry<String, ? extends IoFilter> e: filters.entrySet()) {
if (e.getKey() == null) {
@@ -335,11 +349,90 @@
}
}
- clear();
+ synchronized (this) {
+ clear();
+ for (Map.Entry<String, ? extends IoFilter> e: filters.entrySet()) {
+ addLast(e.getKey(), e.getValue());
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private boolean isOrderedMap(Map map) {
+ Class<?> mapType = map.getClass();
+ if (LinkedHashMap.class.isAssignableFrom(mapType)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(mapType.getSimpleName() + " is an ordered map.");
+ }
+ return true;
+ }
+
+ // Detect Jakarta Commons Collections OrderedMap implementations.
+ Class<?> type = mapType;
+ while (type != null) {
+ for (Class<?> i: type.getInterfaces()) {
+ if (i.getName().endsWith("OrderedMap")) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ mapType.getSimpleName() +
+ " is an ordered map (guessed from that it " +
+ " implements OrderedMap interface.)");
+ }
+ return true;
+ }
+ }
+ type = type.getSuperclass();
+ }
+
+ // Last resort: try to create a new instance and test if it maintains
+ // the insertion order.
+ logger.debug(
+ "Last resort; trying to create a new map instance with a " +
+ "default constructor and test if insertion order is " +
+ "maintained.");
+
+ Map newMap;
+ try {
+ newMap = (Map) mapType.newInstance();
+ } catch (Exception e) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "Failed to create a new map instance of '" +
+ mapType.getName() +"'.", e);
+ }
+ return false;
+ }
+
+ Random rand = new Random();
+ List<String> expectedNames = new ArrayList<String>();
+ IoFilter dummyFilter = new IoFilterAdapter();
+ for (int i = 0; i < 65536; i ++) {
+ String filterName;
+ do {
+ filterName = String.valueOf(rand.nextInt());
+ } while (newMap.containsKey(filterName));
+
+ newMap.put(filterName, dummyFilter);
+ expectedNames.add(filterName);
+ }
+
+ Iterator<String> i = expectedNames.iterator();
+ for (Object key: newMap.keySet()) {
+ if (!i.next().equals(key)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "The specified map didn't pass the insertion " +
+ "order test.");
+ }
+ return false;
+ }
+ }
- for (Map.Entry<String, ? extends IoFilter> e: filters.entrySet()) {
- addLast(e.getKey(), e.getValue());
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "The specified map passed the insertion order test.");
}
+ return true;
}
public void buildFilterChain(IoFilterChain chain) throws Exception {