From c95b219a56311c72b8ee8bb4b6b916cad898df23 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Mon, 25 Aug 2008 03:38:13 +0000 Subject: [PATCH] * Extracted Bootstrap.isOrderedMap into util.MapUtil * More test coverage for Bootstrap --- .../org/jboss/netty/bootstrap/Bootstrap.java | 104 +------------ .../java/org/jboss/netty/util/MapUtil.java | 143 ++++++++++++++++++ .../jboss/netty/bootstrap/BootstrapTest.java | 24 +++ 3 files changed, 169 insertions(+), 102 deletions(-) create mode 100644 src/main/java/org/jboss/netty/util/MapUtil.java diff --git a/src/main/java/org/jboss/netty/bootstrap/Bootstrap.java b/src/main/java/org/jboss/netty/bootstrap/Bootstrap.java index 11d987d016..2e17e6df2c 100644 --- a/src/main/java/org/jboss/netty/bootstrap/Bootstrap.java +++ b/src/main/java/org/jboss/netty/bootstrap/Bootstrap.java @@ -24,13 +24,9 @@ package org.jboss.netty.bootstrap; import static org.jboss.netty.channel.Channels.*; -import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import java.util.Random; import java.util.TreeMap; import org.jboss.netty.channel.Channel; @@ -38,9 +34,7 @@ import org.jboss.netty.channel.ChannelFactory; import org.jboss.netty.channel.ChannelHandler; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.SimpleChannelHandler; -import org.jboss.netty.logging.InternalLogger; -import org.jboss.netty.logging.InternalLoggerFactory; +import org.jboss.netty.util.MapUtil; /** * Helper class which helps a user initialize a {@link Channel}. This class @@ -58,8 +52,6 @@ import org.jboss.netty.logging.InternalLoggerFactory; */ public class Bootstrap { - private static InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class); - private volatile ChannelFactory factory; private volatile ChannelPipeline pipeline = pipeline(); private volatile ChannelPipelineFactory pipelineFactory = pipelineFactory(pipeline); @@ -181,7 +173,7 @@ public class Bootstrap { throw new NullPointerException("pipelineMap"); } - if (!isOrderedMap(pipelineMap)) { + if (!MapUtil.isOrderedMap(pipelineMap)) { throw new IllegalArgumentException( "pipelineMap is not an ordered map. " + "Please use " + @@ -270,96 +262,4 @@ public class Bootstrap { options.put(key, value); } } - - private static boolean isOrderedMap(Map map) { - Class> mapType = getMapClass(map); - if (LinkedHashMap.class.isAssignableFrom(mapType)) { - if (logger.isDebugEnabled()) { - logger.debug(mapType.getSimpleName() + " is an ordered map."); - } - return true; - } - - if (logger.isDebugEnabled()) { - logger.debug( - mapType.getName() + " is not a " + - LinkedHashMap.class.getSimpleName()); - } - - // Detect Apache 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(); - } - - if (logger.isDebugEnabled()) { - logger.debug( - mapType.getName() + - " doesn't implement OrderedMap interface."); - } - - // 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 = 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 expectedNames = new ArrayList(); - ChannelHandler dummyHandler = new SimpleChannelHandler(); - for (int i = 0; i < 65536; i ++) { - String filterName; - do { - filterName = String.valueOf(rand.nextInt()); - } while (newMap.containsKey(filterName)); - - newMap.put(filterName, dummyHandler); - expectedNames.add(filterName); - - Iterator it = expectedNames.iterator(); - for (Object key: newMap.keySet()) { - if (!it.next().equals(key)) { - if (logger.isDebugEnabled()) { - logger.debug( - "The specified map didn't pass the insertion " + - "order test after " + (i + 1) + " tries."); - } - return false; - } - } - } - - logger.debug("The specified map passed the insertion order test."); - return true; - } - - @SuppressWarnings("unchecked") - private static Class> getMapClass( - Map map) { - return (Class>) map.getClass(); - } } diff --git a/src/main/java/org/jboss/netty/util/MapUtil.java b/src/main/java/org/jboss/netty/util/MapUtil.java new file mode 100644 index 0000000000..70750b5bb0 --- /dev/null +++ b/src/main/java/org/jboss/netty/util/MapUtil.java @@ -0,0 +1,143 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2008, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt 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.jboss.netty.util; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.jboss.netty.channel.ChannelHandler; +import org.jboss.netty.channel.SimpleChannelHandler; +import org.jboss.netty.logging.InternalLogger; +import org.jboss.netty.logging.InternalLoggerFactory; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * + * @version $Rev$, $Date$ + * + */ +public class MapUtil { + private static final InternalLogger logger = + InternalLoggerFactory.getInstance(MapUtil.class); + + public static boolean isOrderedMap(Map map) { + Class> mapType = getMapClass(map); + if (LinkedHashMap.class.isAssignableFrom(mapType)) { + if (logger.isDebugEnabled()) { + logger.debug(mapType.getSimpleName() + " is an ordered map."); + } + return true; + } + + if (logger.isDebugEnabled()) { + logger.debug( + mapType.getName() + " is not a " + + LinkedHashMap.class.getSimpleName()); + } + + // Detect Apache 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(); + } + + if (logger.isDebugEnabled()) { + logger.debug( + mapType.getName() + + " doesn't implement OrderedMap interface."); + } + + // 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 = 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 expectedNames = new ArrayList(); + ChannelHandler dummyHandler = new SimpleChannelHandler(); + for (int i = 0; i < 65536; i ++) { + String filterName; + do { + filterName = String.valueOf(rand.nextInt()); + } while (newMap.containsKey(filterName)); + + newMap.put(filterName, dummyHandler); + expectedNames.add(filterName); + + Iterator it = expectedNames.iterator(); + for (Object key: newMap.keySet()) { + if (!it.next().equals(key)) { + if (logger.isDebugEnabled()) { + logger.debug( + "The specified map didn't pass the insertion " + + "order test after " + (i + 1) + " tries."); + } + return false; + } + } + } + + logger.debug("The specified map passed the insertion order test."); + return true; + } + + @SuppressWarnings("unchecked") + private static Class> getMapClass( + Map map) { + return (Class>) map.getClass(); + } + + private MapUtil() { + // Unused + } +} diff --git a/src/test/java/org/jboss/netty/bootstrap/BootstrapTest.java b/src/test/java/org/jboss/netty/bootstrap/BootstrapTest.java index 0b3de027cc..db346217d6 100644 --- a/src/test/java/org/jboss/netty/bootstrap/BootstrapTest.java +++ b/src/test/java/org/jboss/netty/bootstrap/BootstrapTest.java @@ -31,12 +31,17 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.NoSuchElementException; import java.util.Map.Entry; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jboss.netty.channel.ChannelDownstreamHandler; import org.jboss.netty.channel.ChannelFactory; import org.jboss.netty.channel.ChannelHandler; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.DefaultChannelPipeline; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; @@ -88,6 +93,11 @@ public class BootstrapTest { new Bootstrap().setPipeline(null); } + @Test(expected = NullPointerException.class) + public void shouldNotAllowNullPipelineMap() { + new Bootstrap().setPipelineAsMap(null); + } + @Test public void shouldHaveNonNullInitialPipelineFactory() { assertNotNull(new Bootstrap().getPipelineFactory()); @@ -167,6 +177,7 @@ public class BootstrapTest { @Test public void shouldHaveOrderedPipelineWhenSetFromMap() { + Logger.getGlobal().setLevel(Level.SEVERE); Map m = new LinkedHashMap(); m.put("a", createMock(ChannelDownstreamHandler.class)); m.put("b", createMock(ChannelDownstreamHandler.class)); @@ -263,4 +274,17 @@ public class BootstrapTest { public void shouldNotAllowNullOptionMap() { new Bootstrap().setOptions(null); } + + @BeforeClass + public static void setUp() { + // DefaultChannelPipeline will generate expected warning messages. + // Suppress them. + Logger.getLogger(DefaultChannelPipeline.class.getName()).setLevel(Level.SEVERE); + } + + @AfterClass + public static void tearDown() { + // Revert the logger settings back. + Logger.getLogger(DefaultChannelPipeline.class.getName()).setLevel(Level.INFO); + } }