[jboss-cvs] JBossAS SVN: r90503 - in branches/Branch_5_x: cluster/src/main/org/jboss/ha/framework/server and 2 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Jun 22 13:15:13 EDT 2009


Author: bstansberry at jboss.com
Date: 2009-06-22 13:15:13 -0400 (Mon, 22 Jun 2009)
New Revision: 90503

Added:
   branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ChannelInfo.java
   branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackConfigInfo.java
   branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackUtil.java
   branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/managed/
   branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/channelfactory/
   branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ChannelFactoryManagedObjectsTestCase.java
   branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/JChannelFactoryOverrideUnitTestCase.java
   branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/OpenChannelsMapperUnitTestCase.java
   branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ProtocolStackConfigurationsMapperUnitTestCase.java
Modified:
   branches/Branch_5_x/cluster/build.xml
   branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/JChannelFactory.java
   branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/JChannelFactoryMBean.java
   branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAInvokerUnitTestCase.java
   branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/JChannelFactoryUnitTestCase.java
Log:
[JBAS-7016] ChannelFactory managed object interface
[JBAS-7014] Fix addSingletonName handling
[JBAS-7009] Don't subclass JGroups version
[JBAS-7015] Always add singleton_name

Modified: branches/Branch_5_x/cluster/build.xml
===================================================================
--- branches/Branch_5_x/cluster/build.xml	2009-06-22 17:04:50 UTC (rev 90502)
+++ branches/Branch_5_x/cluster/build.xml	2009-06-22 17:15:13 UTC (rev 90503)
@@ -84,6 +84,7 @@
       <path refid="jboss.jboss.deployers.classpath"/>  
       <path refid="jboss.jboss.man.classpath"/>      
       <path refid="jboss.jboss.mdr.classpath"/>
+      <path refid="jboss.jboss.reflect.classpath"/>
       <path refid="jboss.microcontainer.classpath"/>
       <path refid="jboss.integration.classpath"/>
       <path refid="jboss.jboss.javaee.classpath"/>

Copied: branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ChannelInfo.java (from rev 90500, trunk/cluster/src/main/org/jboss/ha/framework/server/ChannelInfo.java)
===================================================================
--- branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ChannelInfo.java	                        (rev 0)
+++ branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ChannelInfo.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -0,0 +1,111 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.ha.framework.server;
+
+import java.util.List;
+
+import javax.management.ObjectName;
+
+import org.jgroups.Address;
+import org.jgroups.Channel;
+import org.jgroups.View;
+import org.jgroups.conf.ProtocolData;
+
+/**
+ * Information describing an open JGroups Channel.
+ *
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class ChannelInfo
+{
+   private final String id;
+   private final String stackName;
+   private final Channel channel;
+   private final ProtocolData[] protocolStackConfiguration;
+   private final ObjectName channelObjectName;
+   private final List<ObjectName> protocolObjectNames;
+   
+   public ChannelInfo(String id, String stackName, Channel channel, 
+         ProtocolData[] config, ObjectName channelObjectName, 
+         List<ObjectName> protocolObjectNames)
+   {
+      if (channel == null)
+      {
+         throw new IllegalArgumentException("null channel");
+      }
+      
+      this.id = id;
+      this.stackName = stackName;
+      this.channel = channel;
+      this.protocolStackConfiguration = config;
+      this.channelObjectName = channelObjectName;
+      this.protocolObjectNames = protocolObjectNames;
+   }
+   
+   public String getId()
+   {
+      return id;
+   }
+   
+   public String getClusterName()
+   {
+      return channel.getClusterName();
+   }
+   
+   public String getStackName()
+   {
+      return stackName;
+   }
+   
+   public Channel getChannel()
+   {
+      return channel;
+   }
+   
+   public ProtocolData[] getProtocolStackConfiguration()
+   {
+      return protocolStackConfiguration;
+   }
+   
+   public ObjectName getChannelObjectName()
+   {
+      return channelObjectName;
+   }
+   
+   public List<ObjectName> getProtocolObjectNames()
+   {
+      return protocolObjectNames;
+   } 
+   
+   public Address getLocalAddress()
+   {
+      return this.channel.getLocalAddress();
+   }
+   
+   public View getCurrentView()
+   {
+      return this.channel.getView();
+   }
+}

Modified: branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/JChannelFactory.java
===================================================================
--- branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/JChannelFactory.java	2009-06-22 17:04:50 UTC (rev 90502)
+++ branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/JChannelFactory.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -21,15 +21,22 @@
  */
 package org.jboss.ha.framework.server;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
 import java.net.InetAddress;
+import java.net.URL;
 import java.rmi.dgc.VMID;
 import java.rmi.server.UID;
 import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 
 import javax.management.MBeanRegistration;
@@ -37,17 +44,27 @@
 import javax.management.ObjectName;
 
 import org.jboss.config.ServerConfigUtil;
+import org.jboss.ha.framework.server.managed.OpenChannelsMapper;
+import org.jboss.ha.framework.server.managed.ProtocolStackConfigurationsMapper;
 import org.jboss.logging.Logger;
+import org.jboss.managed.api.annotation.ManagementComponent;
+import org.jboss.managed.api.annotation.ManagementObject;
+import org.jboss.managed.api.annotation.ManagementProperties;
+import org.jboss.managed.api.annotation.ManagementProperty;
+import org.jboss.managed.api.annotation.ViewUse;
+import org.jboss.metatype.api.annotations.MetaMapping;
 import org.jboss.system.ServiceMBean;
 import org.jboss.util.loading.ContextClassLoaderSwitcher;
 import org.jgroups.Channel;
 import org.jgroups.ChannelException;
+import org.jgroups.ChannelFactory;
 import org.jgroups.ChannelListenerAdapter;
 import org.jgroups.Event;
 import org.jgroups.Global;
 import org.jgroups.JChannel;
 import org.jgroups.conf.ConfiguratorFactory;
 import org.jgroups.conf.ProtocolData;
+import org.jgroups.conf.ProtocolParameter;
 import org.jgroups.conf.ProtocolStackConfigurator;
 import org.jgroups.jmx.JmxConfigurator;
 import org.jgroups.protocols.TP;
@@ -60,10 +77,11 @@
 import org.jgroups.util.ThreadFactory;
 import org.jgroups.util.ThreadManager;
 import org.jgroups.util.Util;
+import org.w3c.dom.Element;
 
 /**
- * Extension to the JGroups JChannelFactory that supports a number of 
- * JBoss AS-specific behaviors:
+ * Implementation of the JGroups <code>ChannelFactory</code> that supports a 
+ * number of JBoss AS-specific behaviors:
  * <p>
  * <ul>
  * <li>Passing a config event to newly created channels containing 
@@ -76,6 +94,7 @@
  * <li>Configures the channel's thread pools and thread factories to ensure
  * that application thread context classloaders don't leak to the channel
  * threads.</li>
+ * <li>Exposes a ProfileService ManagementView interface.</li>
  * </ul>
  * </p>
  * 
@@ -84,13 +103,25 @@
  * 
  * @version $Revision$
  */
-public class JChannelFactory extends org.jgroups.JChannelFactory
-      implements JChannelFactoryMBean, MBeanRegistration
+ at ManagementObject(name="JChannelFactory", 
+      componentType=@ManagementComponent(type="MCBean", subtype="JGroupsChannelFactory"),
+      properties=ManagementProperties.EXPLICIT,
+      isRuntime=true)
+public class JChannelFactory
+      implements ChannelFactory, JChannelFactoryMBean, MBeanRegistration
 {
    protected static final Logger log = Logger.getLogger(JChannelFactory.class);
    
+   /** 
+    * Prefix prepended to the protocol stack name to create a synthetic
+    * transport protocol <code>singleton_name</code> value for channels
+    * that don't configure a <code>singleton_name</code>. 
+    */
    public static final String UNSHARED_TRANSPORT_NAME_BASE = "unnamed_";
    
+   /** Default value for property {@link #getDomain() domain}. */
+   public static final String DEFAULT_JMX_DOMAIN = "jgroups";
+   
    private static final int CREATED = ServiceMBean.CREATED;
    private static final int STARTING = ServiceMBean.STARTING;
    private static final int STARTED = ServiceMBean.STARTED;
@@ -107,10 +138,47 @@
    private boolean manageNewThreadClassLoader = true;
    private boolean manageReleasedThreadClassLoader = false;
    private boolean addMissingSingletonName = true;
-   private boolean domainSet;
    private final ContextClassLoaderSwitcher classLoaderSwitcher;
-   private final Set<String> registeredChannels = new HashSet<String>();
+   private final Map<Channel, ChannelInfo> registeredChannels = 
+      new ConcurrentHashMap<Channel, ChannelInfo>(16, 0.75f, 2);
+   
+   private ChannelCloseListener closeListener = new ChannelCloseListener();
 
+   /**
+    * Map<String,ProtocolStackConfigurator>. Hashmap which maps stack names to JGroups
+    * configurations. Keys are stack names, values are plain JGroups stack
+    * configs. This is (re-)populated whenever a setMultiplexerConfig() method
+    * is called
+    */
+   private final Map<String,ProtocolStackConfigInfo> stacks = 
+      new ConcurrentHashMap<String, ProtocolStackConfigInfo>(16, 0.75f, 2);
+
+   /** 
+    * Placeholder for stacks injected via {@link #setProtocolStackConfigurations(Map)}
+    * until createService is called.
+    */
+   private Map<String,ProtocolStackConfigInfo> injectedStacks;
+   
+   /**
+    * The MBeanServer to expose JMX management data with (no management data
+    * will be available if null)
+    */
+   private MBeanServer server = null;
+
+   /** To expose the channels and protocols */
+   private String domain = DEFAULT_JMX_DOMAIN;
+   private boolean domainSet = false;
+
+   /** Whether or not to expose channels via JMX */
+   private boolean expose_channels=true;
+
+   /** Whether to expose the factory only, or all protocols as well */
+   private boolean expose_protocols=true;
+
+   /**
+    * Creates a new JChannelFactory.
+    */
+   @SuppressWarnings("unchecked")
    public JChannelFactory()
    {
       this.classLoaderSwitcher = (ContextClassLoaderSwitcher) AccessController.doPrivileged(ContextClassLoaderSwitcher.INSTANTIATOR);
@@ -119,73 +187,80 @@
    /**
     * Always throws <code>ChannelException</code>; this method is not supported.
     */   
-   @Override
    public Channel createChannel() throws ChannelException
    {
       throw new ChannelException("No-arg createChannel() is not supported");
    }
 
-   @Override
+   /**
+    * Creates a channel by passing <code>properties</code> to the 
+    * <code>org.jgroups.JChannel</code> constructor.
+    * 
+    * @param properties protocol stack configuration object; can be <code>null</code>
+    *                   in which case a default stack will be used
+    * 
+    * @return the channel
+    */
    public Channel createChannel(Object properties) throws ChannelException
    {
       checkStarted();
-      
-      @SuppressWarnings("deprecation")      
-      Channel channel = super.createChannel(properties);
-      
-      if (manageNewThreadClassLoader || manageReleasedThreadClassLoader)
+
+      if (properties == null)
+         properties = JChannel.DEFAULT_PROTOCOL_STACK;
+
+      ProtocolStackConfigurator config = null;
+
+      try
       {
-         fixChannelThreadManagement(channel);
+         @SuppressWarnings("deprecation")
+         ProtocolStackConfigurator c = ConfiguratorFactory.getStackConfigurator(properties);
+         config = c;
       }
-      
-      if (assignLogicalAddresses)
+      catch (Exception x)
       {
-         setChannelUniqueId(channel);
+         throw new ChannelException("unable to load protocol stack", x);
       }
-      
-      // can't register in JMX as we don't have a channel name
-      
+
+      JChannel channel = initializeChannel(config, null, false);
+
+      try
+      {
+         registerChannel(channel, null, null, ProtocolStackUtil.getProtocolData(config));
+      }
+      catch (ChannelException ce)
+      {
+         throw ce;
+      }
+      catch (Exception e)
+      {
+         throw new ChannelException("unable to register channel", e);
+      }
+
       return channel;
    }
 
    /**
     * Create a {@link Channel} using the specified stack. Channel will use a 
-    * shared transport if the <code>singleton-name</code> attribute is
-    * set on the stack's transport protocol.
+    * shared transport.
     * 
-    * @param stack_name the name of the stack
-    * @return the channel
+    * @param stack_name 
+    *            The name of the stack to be used. All stacks are defined in
+    *            the configuration with which the factory is configured (see
+    *            {@link #setMultiplexerConfig(Object)} for example. If
+    *            clients attempt to create a Channel for an undefined stack 
+    *            name an exception will be thrown.
     * 
+    * @return an implementation of Channel configured with a shared transport.
+    * 
+    * @throws IllegalArgumentException if <code>stack_name</code> is 
+    * <code>null</code> or {@link #getConfig(String)} returns <code>null</code>
+    * when <code>stack_name</code> is used.
+    * 
     * @throws Exception
     */
-   @Override
    public Channel createChannel(String stack_name) throws Exception
    {
-      checkStarted();
-      
-      String props=stack_name != null? getConfig(stack_name) : null;
-      if (props == null)
-      {
-         log.warn("No protocol stack found with name " + stack_name +
-                  "; creating default channel");
-         return createChannel();
-      }
-      
-      JChannel channel = new JChannel(props);
-      
-      if (manageNewThreadClassLoader || manageReleasedThreadClassLoader)
-      {
-         fixChannelThreadManagement(channel);
-      }
-      
-      if (assignLogicalAddresses)
-      {
-         setChannelUniqueId(channel);
-      }
-      
-      // can't register in JMX as we don't have a channel name
-      
-      return channel;
+      return createChannelFromRegisteredStack(stack_name, null, false);
    }
    
    /**
@@ -215,12 +290,12 @@
     *            {@link #setMultiplexerConfig(Object)} for example. If
     *            clients attempt to create a Channel for an undefined stack 
     *            name an Exception will be thrown.
-    * @param id  Only used if the transport protocol configuration for the
-    *            specified stack does not include the <code>singleton_name</code>
-    *            attribute; then it is used to create a synthetic singleton-name
-    *            for the channel's protocol stack.
+    * @param id  Only used if {@link #isExposeChannels()} returns <code>true</code>,
+    *            in which case, if not <code>null</code>, is used as part of
+    *            the <code>ObjectName</code> for the JMX mbeans that represent
+    *            the channel and its protocols. Can be <code>null</code>.
     *            
-    * @return An implementation of Channel configured with a shared transport.
+    * @return an implementation of Channel configured with a shared transport.
     *         
     * @throws IllegalStateException if the specified protocol stack does not
     *                               declare a <code>singleton_name</code> and
@@ -228,60 +303,10 @@
     *                               <code>false</code>.
     * @throws ChannelException
     */
-   @Override
    public Channel createMultiplexerChannel(String stack_name, String id) throws Exception
    {
-      checkStarted();
-      
-      String configStr = getConfig(stack_name);
-      
-      if (configStr == null)
-         throw new IllegalStateException("Unknown stack_name " + stack_name);
-      
-      ProtocolStackConfigurator config = ConfiguratorFactory.getStackConfigurator(configStr);
-      Map<String, String> tpProps = getTransportProperties(config);
-      
-      if (!tpProps.containsKey(Global.SINGLETON_NAME))
-      {
-         if (addMissingSingletonName)
-         {
-            String singletonName = UNSHARED_TRANSPORT_NAME_BASE + stack_name;
-            
-            log.warn("Config for " + stack_name + " does not include " +
-                      "singleton_name; adding a name of " + singletonName +
-                      ". You should configure a singleton_name for this stack.");
-            
-            config = addSingletonName(config, singletonName);
-            log.debug("Stack config after adding singleton_name is " + config.getProtocolStackString());
-            tpProps = getTransportProperties(config);                       
-         }
-         else
-         {
-            throw new IllegalStateException("Config for " + stack_name + " does not include " +
-                      "singleton_name and MuxChannels are not supported.");
-         }
-      }
-      
-      JChannel channel = new JChannel(config);
-      
-      if (manageNewThreadClassLoader || manageReleasedThreadClassLoader)
-      {
-         fixChannelThreadManagement(channel);
-      }
-      
-      if (assignLogicalAddresses)
-      {
-         setChannelUniqueId(channel);
-      }
-      
-      if (isExposeChannels() && id != null && id.length() > 0)
-      {
-         registerChannel(channel, id);
-      }
-      
-      return channel;
+      return createChannelFromRegisteredStack(stack_name, id, true);
    }  
-
    
    /**
     * Creates and returns a shared transport Channel configured with the specified 
@@ -303,19 +328,149 @@
     *                               <code>false</code>.
     * @throws ChannelException
     */
-   @Override
    public Channel createMultiplexerChannel(String stack_name, String id, boolean register_for_state_transfer, String substate_id) throws Exception
    {
       return createMultiplexerChannel(stack_name, id);
    }
    
-   @Override
+   /**
+    * {@link #parse(Element) Parses <code>properties</code>} and then adds
+    * the resulting protocol stack configurations to the set available for use.
+    * Same as 
+    * {@link #setMultiplexerConfig(Element, boolean) <code>setMultiplexerConfig(properties, true</code>}.
+    * 
+    * @param properties document root node for XML content in the JGroups 
+    *                   <code>stacks.xml</code> format
+    */
+   public void setMultiplexerConfig(Element properties) throws Exception
+   {
+      setMultiplexerConfig(properties, true);
+   }
+
+   /**
+    * {@link #parse(InputStream) Parses} an input stream created from 
+    * <code>properties</code> and then adds the resulting protocol stack 
+    * configurations to the set available for use. Same as 
+    * {@link #setMultiplexerConfig(File, boolean) <code>setMultiplexerConfig(properties, true</code>}.
+    * 
+    * @param properties file which must contain XML content in the JGroups 
+    *              <code>stacks.xml</code> format
+    */
+   public void setMultiplexerConfig(File properties) throws Exception
+   {
+      setMultiplexerConfig(properties, true);      
+   }
+
+   /**
+    * {@link #parse(InputStream) Parses} an input stream created from 
+    * <code>properties</code> and then adds the resulting protocol stack 
+    * configurations to the set available for use. Same as 
+    * {@link #setMultiplexerConfig(Object, boolean) <code>setMultiplexerConfig(properties, true</code>}.
+    * 
+    * @param properties object that can be {@link ConfiguratorFactory#getConfigStream(Object) converted into a stream}
+    *                   which must contain XML content in the JGroups 
+    *                   <code>stacks.xml</code> format
+    */
+   public void setMultiplexerConfig(Object properties) throws Exception
+   {
+      setMultiplexerConfig(properties, true);
+   }
+
+   /**
+    * {@link #parse(InputStream) Parses} an input stream created from 
+    * <code>properties</code> and then adds the resulting protocol stack 
+    * configurations to the set available for use. Same as 
+    * {@link #setMultiplexerConfig(String, boolean) <code>setMultiplexerConfig(properties, true</code>}.
+    * 
+    * @param properties string that can be {@link ConfiguratorFactory#getConfigStream(String) converted into a stream}
+    *                   which must contain XML content in the JGroups 
+    *                   <code>stacks.xml</code> format
+    */
+   public void setMultiplexerConfig(String properties) throws Exception
+   {
+      setMultiplexerConfig(properties, true);
+   }
+
+   /**
+    * {@link #parse(InputStream) Parses} an input stream created from 
+    * <code>properties</code> and then adds the resulting protocol stack 
+    * configurations to the set available for use. Same as 
+    * {@link #setMultiplexerConfig(URL, boolean) <code>setMultiplexerConfig(properties, true</code>}.
+    * 
+    * @param properties URL which must contain XML content in the JGroups 
+    *              <code>stacks.xml</code> format
+    */
+   public void setMultiplexerConfig(URL properties) throws Exception
+   {
+      setMultiplexerConfig(properties, true);
+   }
+
+   // -------------------------------------------------------------  Properties
+
+   /**
+    * Gets the MBeanServer to use to register mbeans for channels and protocols
+    * we create.
+    * 
+    * @return the MBeanServer, or <code>null</code> if one isn't registered
+    */
+   public MBeanServer getServer() 
+   {
+       return server;
+   }
+
+   /**
+    * Sets the MBeanServer to use to register mbeans for channels and protocols
+    * we create.
+    * 
+    * @param server the MBeanServer. May be <code>null</code>
+    */
+   public void setServer(MBeanServer server) 
+   {
+       this.server=server;
+   }
+
+   /**
+    * Gets the domain portion of the JMX ObjectName to use when registering channels and protocols
+    * 
+    * @return the domain. Will not return <code>null</code> after {@link #create()}
+    *         has been invoked.
+    */
+   @ManagementProperty(use={ViewUse.CONFIGURATION}, description="The domain portion of the JMX ObjectName to use when registering channels and protocols")
+   public String getDomain() 
+   {
+       return domain == null ? "jgroups" : domain;
+   }
+   
    public void setDomain(String domain)
    {
-      super.setDomain(domain);
-      domainSet = true;
+      this.domain = domain;
+      this.domainSet = true;
    }
 
+   @ManagementProperty(use={ViewUse.CONFIGURATION}, description="Whether to expose channels we create via JMX")
+   public boolean isExposeChannels() 
+   {
+       return expose_channels;
+   }
+
+   public void setExposeChannels(boolean expose_channels) 
+   {
+       this.expose_channels=expose_channels;
+   }
+
+   @ManagementProperty(use={ViewUse.CONFIGURATION}, description="Whether to expose protocols via JMX as well if we expose channels")
+   public boolean isExposeProtocols() 
+   {
+       return expose_protocols;
+   }
+
+   public void setExposeProtocols(boolean expose_protocols) 
+   {      
+       this.expose_protocols=expose_protocols;
+       if (expose_protocols)
+          this.expose_channels=true;
+   }
+
    /**
     * Get any logical name assigned to this server; if not null this value
     * will be the value of the 
@@ -324,6 +479,7 @@
     * 
     * @return the logical name for this server, or <code>null</code>.
     */
+   @ManagementProperty(use={ViewUse.CONFIGURATION}, description="The cluster-unique logical name of this node")
    public String getNodeName()
    {
       return nodeName;
@@ -405,6 +561,7 @@
     * 
     * @see #setAssignLogicalAddresses(boolean)
     */
+   @ManagementProperty(use={ViewUse.CONFIGURATION}, description="Whether this factory should assign a logical address for this node to all channels")
    public boolean getAssignLogicalAddresses()
    {
       return assignLogicalAddresses;
@@ -438,6 +595,7 @@
     * @return <code>true</code> if the factories should be updated.
     *         Default is <code>true</code>.
     */
+   @ManagementProperty(use={ViewUse.CONFIGURATION}, description="Whether this factory should update the standard JGroups thread factories to ensure classloader leaks do not occur")
    public boolean getManageNewThreadClassLoader()
    {
       return manageNewThreadClassLoader;
@@ -464,6 +622,7 @@
     * @return <code>true</code> if the pools should be updated.
     *         Default is <code>false</code>.
     */
+   @ManagementProperty(use={ViewUse.CONFIGURATION}, description="Whether this factory should update the standard JGroups thread pools to ensure classloader leaks do not occur")
    public boolean getManageReleasedThreadClassLoader()
    {
       return manageReleasedThreadClassLoader;
@@ -498,6 +657,8 @@
     * @return <code>true</code> if synthetic singleton names should be created.
     *         Default is <code>true</code>.
     */
+   @ManagementProperty(use={ViewUse.CONFIGURATION}, 
+         description="Whether this factory should create a synthetic singleton name attribute for a channel's transport protocol if one isn't configured")
    public boolean getAddMissingSingletonName()
    {
       return addMissingSingletonName;
@@ -515,8 +676,207 @@
    {
       this.addMissingSingletonName = addMissingSingletonName;
    }
+   
+   // -------------------------------------------------------------  Public
 
-   @Override
+   /**
+    * {@link #parse(Element) Parses <code>properties</code>} and then adds
+    * the resulting protocol stack configurations to the set available for use.
+    * 
+    * @param properties document root node for XML content in the JGroups 
+    *                   <code>stacks.xml</code> format
+    * @param replace <code>true</code> if a configuration with the same
+    *                stack name as an already registered configuration should
+    *                replace that configuration; <code>false</code> if it
+    *                should be discarded.
+    */
+   public void setMultiplexerConfig(Element properties, boolean replace) throws Exception
+   {
+      Map<String, ProtocolStackConfigInfo> map = ProtocolStackUtil.parse(properties);
+      
+      for (Map.Entry<String, ProtocolStackConfigInfo> entry : map.entrySet())
+      {
+         addConfig(entry.getKey(), entry.getValue(), replace);
+      }
+   }
+
+   /**
+    * {@link #parse(InputStream) Parses} an input stream created from 
+    * <code>properties</code> and then adds the resulting protocol stack 
+    * configurations to the set available for use.
+    * 
+    * @param properties file which must contain XML content in the JGroups 
+    *              <code>stacks.xml</code> format
+    * @param replace <code>true</code> if a configuration with the same
+    *                stack name as an already registered configuration should
+    *                replace that configuration; <code>false</code> if it
+    *                should be discarded.
+    */
+   public void setMultiplexerConfig(File properties, boolean replace) throws Exception
+   {
+      InputStream input=ConfiguratorFactory.getConfigStream(properties);      
+      addConfigs(input, properties.toString(), replace);
+   }
+
+   /**
+    * {@link #parse(InputStream) Parses} an input stream created from 
+    * <code>properties</code> and then adds the resulting protocol stack 
+    * configurations to the set available for use. 
+    * 
+    * @param properties object that can be {@link ConfiguratorFactory#getConfigStream(Object) converted into a stream}
+    *                   which must contain XML content in the JGroups 
+    *                   <code>stacks.xml</code> format
+    * @param replace <code>true</code> if a configuration with the same
+    *                stack name as an already registered configuration should
+    *                replace that configuration; <code>false</code> if it
+    *                should be discarded.
+    */
+   public void setMultiplexerConfig(Object properties, boolean replace) throws Exception
+   {
+      InputStream input=ConfiguratorFactory.getConfigStream(properties);
+      addConfigs(input, properties.toString(), replace);   
+   }
+
+   /**
+    * {@link #parse(InputStream) Parses} an input stream created from 
+    * <code>properties</code> and then adds the resulting protocol stack 
+    * configurations to the set available for use.
+    * 
+    * @param properties string that can be {@link ConfiguratorFactory#getConfigStream(String) converted into a stream}
+    *                   which must contain XML content in the JGroups 
+    *                   <code>stacks.xml</code> format
+    * @param replace <code>true</code> if a configuration with the same
+    *                stack name as an already registered configuration should
+    *                replace that configuration; <code>false</code> if it
+    *                should be discarded.
+    */
+   public void setMultiplexerConfig(String properties, boolean replace) throws Exception
+   {
+      InputStream input=ConfiguratorFactory.getConfigStream(properties);      
+      addConfigs(input, properties, replace);
+   }
+
+   /**
+    * {@link #parse(InputStream) Parses} an input stream created from 
+    * <code>properties</code> and then adds the resulting protocol stack 
+    * configurations to the set available for use.
+    * 
+    * @param properties URL which must contain XML content in the JGroups 
+    *              <code>stacks.xml</code> format
+    * @param replace <code>true</code> if a configuration with the same
+    *                stack name as an already registered configuration should
+    *                replace that configuration; <code>false</code> if it
+    *                should be discarded.
+    */
+   public void setMultiplexerConfig(URL url, boolean replace) throws Exception
+   {
+      InputStream input=ConfiguratorFactory.getConfigStream(url);      
+      addConfigs(input, url.toString(), replace);
+   }
+   
+
+   // --------------------------------------------------------  Management View
+   
+   /**
+    * Gets information on channels created by this factory that are currently
+    * open.
+    */
+   @ManagementProperty(use={ViewUse.STATISTIC}, 
+         description="Information on channels created by this factory that are currently open",
+         readOnly=true)
+   @MetaMapping(value=OpenChannelsMapper.class)
+   public Set<ChannelInfo> getOpenChannels()
+   {
+      return new HashSet<ChannelInfo>(registeredChannels.values());
+   }
+   
+   @ManagementProperty(use={ViewUse.CONFIGURATION, ViewUse.RUNTIME}, 
+         description="Protocol stack configurations available for use")
+   @MetaMapping(value=ProtocolStackConfigurationsMapper.class)
+   public Map<String, ProtocolStackConfigInfo> getProtocolStackConfigurations()
+   {
+      return Collections.unmodifiableMap(stacks);
+   }
+   
+   public void setProtocolStackConfigurations(Map<String, ProtocolStackConfigInfo> configs)
+   {
+      this.injectedStacks = configs;      
+      
+      if (state == STARTED)
+      {
+         // We're already running so this must be a ManagedComponent update
+         // so apply immediately
+         processInjectedStacks();
+      }
+   }
+
+   // ---------------------------------------------------  JChannelFactoryMBean
+
+   /**
+    * {@inheritDoc}
+    */
+   public void clearConfigurations()
+   {
+      this.stacks.clear();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String dumpChannels()
+   {
+      return "";
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String dumpConfiguration()
+   {
+      return stacks.keySet().toString();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String getConfig(String stack_name) throws Exception
+   {
+      ProtocolStackConfigInfo cfg = stacks.get(stack_name);
+      if (cfg == null)
+         throw new Exception("stack \"" + stack_name + "\" not found in " + stacks.keySet());
+      return cfg.getConfigurator().getProtocolStackString();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String getMultiplexerConfig()
+   {
+      StringBuilder sb = new StringBuilder();
+      for (Map.Entry<String, ProtocolStackConfigInfo> entry : stacks.entrySet())
+      {
+         sb.append(entry.getKey()).append(": ").append(entry.getValue().getConfigurator().getProtocolStackString()).append("\n");
+      }
+      return sb.toString();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean removeConfig(String stack_name)
+   {
+      return stack_name != null && this.stacks.remove(stack_name) != null;
+   }
+   
+   // -------------------------------------------------------------  Lifecycle
+
+   /**
+    * {@inheritDoc}
+    * <p>
+    * This method largely directly concerns itself with the {@link #getStateString() state}
+    * field, delegating the real work to {@link #createService()}.
+    * </p>
+    */
    public void create() throws Exception
    {
 
@@ -531,7 +891,7 @@
       
       try
       {
-         super.create();
+         createService();
          state = CREATED;
       }
       catch (Exception e)
@@ -543,7 +903,13 @@
       log.debug("Created JChannelFactory");
    }
 
-   @Override
+   /**
+    * {@inheritDoc}
+    * <p>
+    * This method largely directly concerns itself with the {@link #getStateString() state}
+    * field, delegating the real work to {@link #startService()}.
+    * </p>
+    */
    public void start() throws Exception
    {
       if (state == STARTING || state == STARTED || state == STOPPING)
@@ -563,7 +929,7 @@
 
       try
       {
-         super.start();
+         startService();
       }
       catch (Exception e)
       {
@@ -577,7 +943,13 @@
       
    }
 
-   @Override
+   /**
+    * {@inheritDoc}
+    * <p>
+    * This method largely directly concerns itself with the {@link #getStateString() state}
+    * field, delegating the real work to {@link #stopService()}.
+    * </p>
+    */
    public void stop()
    {
       if (state != STARTED)
@@ -591,7 +963,7 @@
 
       try
       {
-         super.stop();
+         stopService();
       }
       catch (Throwable e)
       {
@@ -604,7 +976,13 @@
       log.debug("Stopped JChannelFactory");
    }
 
-   @Override
+   /**
+    * {@inheritDoc}
+    * <p>
+    * This method largely directly concerns itself with the {@link #getStateString() state}
+    * field, delegating the real work to {@link #destroyService()}.
+    * </p>
+    */
    public void destroy()
    {
       if (state == DESTROYED)
@@ -621,21 +999,9 @@
       
       log.debug("Destroying JChannelFactory");
       
-      // DON'T call super.destroy() as that may deregister the JMX proxy
-      // to this pojo service, leading to ugliness when the proxy is destroyed
       try
-      {
-         
-         Set<String> toUnregister = null;
-         synchronized (registeredChannels)
-         {
-            toUnregister = new HashSet<String>(registeredChannels);
-         }
-         
-         for (String channelId : toUnregister)
-         {
-            unregister(channelId);
-         }
+      {         
+         destroyService();
       }
       catch (Throwable t)
       {
@@ -650,14 +1016,13 @@
    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception
    {
       setServer(server);
-      if (!domainSet || getDomain() == null)
+      if (!this.domainSet || this.domain == null)
       {
          setDomain(name.getDomain());
       }
       return name;
    }
 
-
    public void postRegister(Boolean registrationDone)
    {
       if (registrationDone != null && registrationDone.booleanValue()
@@ -667,7 +1032,6 @@
       }
    }
 
-
    public void preDeregister() throws Exception
    { 
    }
@@ -678,6 +1042,8 @@
       if (state == ServiceMBean.DESTROYED)
          state = ServiceMBean.UNREGISTERED;
    }
+
+   // --------------------------------------------------------------- Protected
    
    /**
     * Gets the classloader that channel threads should be set to if
@@ -693,6 +1059,57 @@
       return getClass().getClassLoader();
    }
 
+   protected void createService() throws Exception
+   {
+      if(expose_channels) 
+      {
+         if(server == null)
+         {
+            throw new Exception("No MBeanServer found; JChannelFactory needs to " +
+            		"be run with an MBeanServer present, or with ExposeChannels " +
+            		"set to false");
+         }
+         
+         if(domain == null)
+         {
+            domain= DEFAULT_JMX_DOMAIN;
+         }
+      }
+   }
+
+   /**
+    * The actual startup work.
+    * 
+    * @throws Exception
+    */
+   protected void startService() throws Exception
+   {
+      // If the ProfileService injected stacks, process them now
+      processInjectedStacks();
+   }
+
+   /**
+    * The actual service stop work. This base implementation does nothing.
+    * 
+    * @throws Exception
+    */
+   protected void stopService() throws Exception
+   {
+      // no-op
+   }
+
+   /**
+    * The actual service destruction work.
+    *
+    */
+   protected void destroyService()
+   {  
+      for (Channel ch : registeredChannels.keySet())
+      {
+         unregisterChannel(ch);
+      }
+   }
+
    // ----------------------------------------------------------------- Private
 
 
@@ -702,6 +1119,160 @@
          throw new IllegalStateException("Cannot use factory; state is " + getStateString());
    }
    
+   private void addConfigs(InputStream input, String source, boolean replace) throws Exception
+   {
+      if(input == null)
+      {
+         throw new FileNotFoundException(source);
+      }
+      
+      Map<String, ProtocolStackConfigInfo> map = null;
+      try 
+      {
+          map = ProtocolStackUtil.parse(input);
+      }
+      catch(Exception ex) 
+      {
+          throw new Exception("failed parsing " + source, ex);
+      }
+      finally 
+      {
+          Util.close(input);
+      }
+      
+      for (Map.Entry<String, ProtocolStackConfigInfo> entry : map.entrySet())
+      {
+         addConfig(entry.getKey(), entry.getValue(), replace);
+      }
+   }
+
+   private boolean addConfig(String st_name, ProtocolStackConfigInfo val, boolean replace)
+   {
+      boolean added = replace;
+      if (replace)
+      {
+         stacks.put(st_name, val);
+         if (log.isTraceEnabled())
+            log.trace("added config '" + st_name + "'");
+      }
+      else
+      {
+         if (!stacks.containsKey(st_name))
+         {
+            stacks.put(st_name, val);
+            if (log.isTraceEnabled())
+               log.trace("added config '" + st_name + "'");
+            added = true;
+         }
+         else
+         {
+            if (log.isTraceEnabled())
+               log.trace("didn't add config '" + st_name + " because one of the same name already existed");
+         }
+      }
+      return added;      
+   }
+   
+   private synchronized void processInjectedStacks()
+   {
+      if (injectedStacks != null)
+      {
+         clearConfigurations();
+         stacks.putAll(injectedStacks);
+         injectedStacks = null;
+      }      
+   }
+
+   /**
+    * Creates a channel from one of the known stack configurations.
+    * 
+    * @param stack_name the name of the stack config
+    * @param id optional id for the channel
+    * @param forceSingletonStack <code>true</code> if a singleton_name must be
+    *             either configured, or addMissingSingletonName must be true
+    *             
+    * @return the channel
+    * 
+    * @throws IllegalArgumentException if stack_name is unknown
+    * @throws IllegalStateException if forceSingletonStack is <code>true</code>
+    *                               but a singleton_name couldn't be configured
+    *           
+    * @throws Exception
+    */
+   private Channel createChannelFromRegisteredStack(String stack_name, String id, boolean forceSingletonStack) throws Exception
+   {
+      checkStarted();
+      
+      ProtocolStackConfigInfo config = stacks.get(stack_name);
+      
+      if (config == null)
+         throw new IllegalArgumentException("Unknown stack_name " + stack_name);
+      
+      JChannel channel = initializeChannel(config.getConfigurator(), stack_name, forceSingletonStack);
+      
+      registerChannel(channel, id, stack_name, ProtocolStackUtil.getProtocolData(config.getConfigurator()));      
+      
+      return channel;
+   }
+
+   /**
+    * Construct a JChannel from the given config and then do post-construction
+    * processing like fixing up thread managment or setting a unique id.
+    * 
+    * @param config the config
+    * 
+    * @return the channel
+    * 
+    * @throws ChannelException
+    */
+   private JChannel initializeChannel(ProtocolStackConfigurator config, String stack_name,
+         boolean forceSingletonStack) throws ChannelException
+   {  
+      Map<String, String> tpProps = getTransportProperties(config);
+   
+      if (!tpProps.containsKey(Global.SINGLETON_NAME))
+      {
+         if (addMissingSingletonName && stack_name != null)
+         {
+            String singletonName = UNSHARED_TRANSPORT_NAME_BASE + stack_name;
+            
+            log.warn("Config for " + stack_name + " does not include " +
+                      "singleton_name; adding a name of " + singletonName +
+                      ". You should configure a singleton_name for this stack.");
+            
+            config = addSingletonName(config, singletonName);
+            log.debug("Stack config after adding singleton_name is " + config.getProtocolStackString());
+            tpProps = getTransportProperties(config);                       
+         }
+         else if (forceSingletonStack)
+         {
+            throw new IllegalStateException("Config for " + stack_name + " does not include " +
+                      "singleton_name and MuxChannels are not supported.");
+         }
+      }
+      JChannel channel = new JChannel(config);
+      
+      if (manageNewThreadClassLoader || manageReleasedThreadClassLoader)
+      {
+         fixChannelThreadManagement(channel);
+      }
+      
+      if (assignLogicalAddresses)
+      {
+         setChannelUniqueId(channel);
+      }
+      
+      return channel;
+   }
+   
+   /**
+    * Gets the current runtime lifecycle state (e.g. CREATED, STARTED).
+    */
+   private String getStateString()
+   {
+      return ServiceMBean.states[state];
+   }
+   
    private void setChannelUniqueId(Channel channel)
    {
       IpAddress address = (IpAddress) channel.getLocalAddress();
@@ -734,11 +1305,6 @@
                 "additional data -- setting nodeName to " + nodeName);
       }
    }
-   
-   private String getStateString()
-   {
-      return ServiceMBean.states[state];
-   }
 
    private String generateUniqueNodeName ()
    {
@@ -776,9 +1342,9 @@
       else
       {
          log.warn("JNDI has been found but the service wasn't started. Most likely, " +
-               "HAPartition bean is missing dependency on JBoss Naming. " +
-               "Instead using host based UID strategy for defining a node " +
-               "GUID for the cluster.");
+         		    "HAPartition bean is missing dependency on JBoss Naming. " +
+         		    "Instead using host based UID strategy for defining a node " +
+         		    "GUID for the cluster.");
       }
 
       // 2nd: host-GUID strategy
@@ -790,28 +1356,15 @@
    private Map<String, String> getTransportProperties(ProtocolStackConfigurator config)
    {
       Map<String, String> tpProps = null;
-      try
+      ProtocolData[] protocols= ProtocolStackUtil.getProtocolData(config);
+      ProtocolData transport=protocols[0];
+      @SuppressWarnings("unchecked")
+      Map<String,ProtocolParameter> tmp=transport.getParameters();
+      tpProps = new HashMap<String,String>();
+      for(Map.Entry<String,ProtocolParameter> entry: tmp.entrySet())
       {
-         ProtocolData[] protocols=config.getProtocolStack();
-         ProtocolData transport=protocols[0];
-         tpProps = transport.getParameters();
+          tpProps.put(entry.getKey(), entry.getValue().getValue());
       }
-      catch (UnsupportedOperationException uoe)
-      {
-         // JGroups version hasn't implemented ProtocolStackConfigurator.getProtocolStack()
-         // So we do it ourselves
-         String configStr = config.getProtocolStackString();
-         String tpConfigStr = configStr.substring(configStr.indexOf('(') + 1, configStr.indexOf(')'));
-         String[] params = tpConfigStr.split(";");
-         tpProps = new HashMap<String, String>();
-         for (String param : params)
-         {
-            String[] keyVal = param.split("=");
-            if (keyVal.length != 2)
-               throw new IllegalStateException("Invalid parameter " + param + " in stack " + configStr);
-            tpProps.put(keyVal[0], keyVal[1]);
-         }
-      }
       
       return tpProps;
    }
@@ -824,9 +1377,8 @@
       {
          ProtocolData[] protocols=orig.getProtocolStack();
          ProtocolData transport=protocols[0];
-         Map<String, String> tpProps = transport.getParameters();
-         tpProps.put(Global.SINGLETON_NAME, singletonName);
-         // we've now updated the state of orig; just return it
+         ProtocolParameter singletonParam = new ProtocolParameter(Global.SINGLETON_NAME, singletonName);
+         transport.override(new ProtocolParameter[]{ singletonParam});
          result = orig;
       }
       catch (UnsupportedOperationException uoe)
@@ -1009,40 +1561,124 @@
       classLoaderSwitcher.setContextClassLoader(thread, classLoader);
    }
    
-   private void registerChannel(JChannel ch, String channelId) throws Exception 
+   private void registerChannel(JChannel ch, String channelId, String stackName, ProtocolData[] config) throws Exception
    {
-      if(getServer() != null)
+      // Register for channel closed notification so we can unregister
+      ch.addChannelListener(closeListener);
+      
+      ObjectName chName = null;
+      List<ObjectName> protNames = null;
+      List<ObjectName> allNames = registerInJmx(ch, channelId);
+      if (allNames != null && allNames.size() > 0)
       {
-         // Register for channel closed notification so we can unregister
-         JmxDeregistrationChannelListener listener = new JmxDeregistrationChannelListener(channelId);
-         ch.addChannelListener(listener);
-         JmxConfigurator.registerChannel(ch, getServer(), getDomain(), channelId, isExposeProtocols());
-         synchronized (registeredChannels)
+         chName = allNames.get(0);
+         if (allNames.size() > 1)
          {
-            registeredChannels.add(channelId);
+            protNames = allNames.subList(1, allNames.size());
          }
       }
+      
+      ChannelInfo info = new ChannelInfo(channelId, stackName, ch, config, chName, protNames);
+      registeredChannels.put(ch, info);
    }
    
-   private void unregister(String channelId) 
+   private List<ObjectName> registerInJmx(JChannel ch, String channelId) throws Exception 
    {
-      if(getServer() != null && registeredChannels.contains(channelId))
+      List<ObjectName> allNames = null;
+      
+      if(isExposeChannels() && getServer() != null && channelId != null && channelId.length() > 0)
       {
-         String oname = getDomain() + ":type=channel,cluster=" + channelId;
-         try
+         allNames = new ArrayList<ObjectName>();
+         ObjectName channelName = new ObjectName(getDomain() + ":type=channel,cluster=" + channelId);
+         getServer().registerMBean(new org.jgroups.jmx.JChannel(ch), channelName);
+         allNames.add(channelName);
+         if (isExposeProtocols())
          {
-            getServer().unregisterMBean(new ObjectName(oname));
-            oname = getDomain() + ":type=protocol,cluster=" + channelId + ",*";
-            JmxConfigurator.unregister(getServer(), oname);
-            synchronized (registeredChannels)
+            String baseName = getDomain() + ":type=protocol,cluster=" + channelId;
+            ProtocolStack stack=ch.getProtocolStack();
+            List<Protocol> protocols=stack.getProtocols();
+            
+            for(Protocol prot : protocols)
             {
-               registeredChannels.remove(channelId);
+                org.jgroups.jmx.Protocol p=null;
+                try {
+                   String prot_name = prot.getClass().getName();
+                   String clname = prot_name.replaceFirst("org.jgroups.", "org.jgroups.jmx.");
+                   Class<?> cl = Util.loadClass(clname, JmxConfigurator.class);
+                   if (cl != null)
+                   {
+                      p = (org.jgroups.jmx.Protocol) cl.newInstance();
+                   }
+                }
+                catch(ClassNotFoundException e) 
+                {
+                   // ignore;
+                }
+                catch(Throwable e) {
+                    log.error("failed creating a JMX wrapper instance for " + prot, e);
+                    p = null;
+                }
+                if(p == null)
+                {
+                   // Use default
+                   p = new org.jgroups.jmx.Protocol(prot);
+                }
+                ObjectName prot_name=new ObjectName(baseName + ",protocol=" + prot.getName());
+                server.registerMBean(p, prot_name);
+                allNames.add(prot_name);
             }
          }
+      }
+      
+      return allNames;
+   }
+   
+   private void unregisterChannel(Channel ch)
+   {
+      ChannelInfo info = registeredChannels.remove(ch);
+      if (info == null)
+      {
+         log.warn("Unknown channel " + ch.getClusterName());
+      }
+      else
+      {
+         unregisterFromJmx(info);
+      }
+      
+      ch.removeChannelListener(closeListener);
+   }
+   
+   private void unregisterFromJmx(ChannelInfo info) 
+   {
+      ObjectName oname = info.getChannelObjectName();
+      MBeanServer mbs = getServer();
+      if(info != null && mbs != null)
+      {
+         try
+         {
+            mbs.unregisterMBean(oname);
+         }
          catch(Exception e)
          {
             log.error("failed unregistering " + oname, e);
          }
+         
+         List<ObjectName> onames = info.getProtocolObjectNames();
+         if (onames != null)
+         {
+            for (ObjectName protName : onames)
+            {
+               try
+               {
+                  mbs.unregisterMBean(protName);
+               }
+               catch(Exception e)
+               {
+                  log.error("failed unregistering " + protName, e);
+               }
+               
+            }
+         }
       }
    }
    
@@ -1082,18 +1718,11 @@
       
    }
 
-   private class JmxDeregistrationChannelListener extends ChannelListenerAdapter
+   private class ChannelCloseListener extends ChannelListenerAdapter
    {
-      private final String channelId;
-      
-      JmxDeregistrationChannelListener(String channelId)
-      {
-         this.channelId = channelId;
-      }
-      
       public void channelClosed(Channel channel) 
       {
-         unregister(channelId);
+         unregisterChannel(channel);
       }            
    }
    

Modified: branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/JChannelFactoryMBean.java
===================================================================
--- branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/JChannelFactoryMBean.java	2009-06-22 17:04:50 UTC (rev 90502)
+++ branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/JChannelFactoryMBean.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -27,9 +27,7 @@
 import org.jgroups.ChannelException;
 
 /**
- * StandardMBean interface for {@link JChannelFactory}. Based on the 
- * <code>org.jgroups.jmx.JChannelFactoryMBean</code> interface, which
- * is scheduled to be removed.
+ * StandardMBean interface for {@link JChannelFactory}.
  * <p>
  * The plain-old-java-interface for the channel factory is 
  * <code>org.jgroups.ChannelFactory</code>; users are encouraged to dependency
@@ -130,7 +128,7 @@
    void setExposeProtocols(boolean f);
 
    /**
-    * Returns the stack configuration as a string (valid to be fed into new JChannel()). Throws an exception
+    * Returns the stack configuration as a string (valid to be fed into new JChannel(String)). Throws an exception
     * if the stack_name is not found. One of the setMultiplexerConfig() methods had to be called beforehand.
     * 
     * @return The protocol stack config as a plain string
@@ -154,9 +152,19 @@
     * shared transport if the <code>singleton-name</code> attribute is
     * set on the stack's transport protocol.
     * 
-    * @param stack_name the name of the stack
+    * @param stack_name 
+    *            The name of the stack to be used. All stacks are defined in
+    *            the configuration with which the factory is configured (see
+    *            {@link #setMultiplexerConfig(Object)} for example. If
+    *            clients attempt to create a Channel for an undefined stack 
+    *            name an exception will be thrown.
+    * 
     * @return the channel
     * 
+    * @throws IllegalArgumentException if <code>stack_name</code> is 
+    * <code>null</code> or {@link #getConfig(String)} returns <code>null</code>
+    * when <code>stack_name</code> is used.
+    * 
     * @throws Exception
     */
    Channel createChannel(String stack_name) throws Exception;

Copied: branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackConfigInfo.java (from rev 90500, trunk/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackConfigInfo.java)
===================================================================
--- branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackConfigInfo.java	                        (rev 0)
+++ branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackConfigInfo.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -0,0 +1,75 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.ha.framework.server;
+
+import org.jgroups.conf.ProtocolData;
+import org.jgroups.conf.ProtocolStackConfigurator;
+
+/**
+ *
+ *
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class ProtocolStackConfigInfo
+{
+   private final String name;
+   private final String description;
+   private final ProtocolStackConfigurator configurator;
+   
+   public ProtocolStackConfigInfo(String name, String description, ProtocolStackConfigurator configurator)
+   {
+      if (name == null)
+      {
+         throw new IllegalArgumentException("null name");
+      }
+      if (configurator == null)
+      {
+         throw new IllegalArgumentException("null configurator");
+      }
+      this.name = name;
+      this.description = description;
+      this.configurator = configurator;
+   }
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public String getDescription()
+   {
+      return description;
+   }
+
+   ProtocolStackConfigurator getConfigurator()
+   {
+      return configurator;
+   }
+
+   public ProtocolData[] getConfiguration()
+   {
+      return ProtocolStackUtil.getProtocolData(configurator);
+   }
+}

Copied: branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackUtil.java (from rev 90500, trunk/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackUtil.java)
===================================================================
--- branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackUtil.java	                        (rev 0)
+++ branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/ProtocolStackUtil.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -0,0 +1,217 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.ha.framework.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.jboss.logging.Logger;
+import org.jgroups.conf.ConfiguratorFactory;
+import org.jgroups.conf.ProtocolData;
+import org.jgroups.conf.ProtocolParameter;
+import org.jgroups.conf.ProtocolStackConfigurator;
+import org.jgroups.conf.XmlConfigurator;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Utilities related to JGroups protocol stack manipulation.
+ *
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public final class ProtocolStackUtil
+{  
+   private static final Logger log = Logger.getLogger(ProtocolStackUtil.class);
+   
+   private static final String PROTOCOL_STACKS="protocol_stacks";
+   private static final String STACK="stack";
+   private static final String NAME="name";
+   private static final String DESCR="description";
+   private static final String CONFIG="config";
+
+   /**
+    * Parses the contents of <code>input</code> into a map of the
+    * protocol stack configurations contained in the XML.
+    * 
+    * @param input stream which must contain XML content in the JGroups 
+    *              <code>stacks.xml</code> format
+    *              
+    * @return a map of the protocol stack configurations contained in the XML
+    * 
+    * @throws IllegalArgumentException if <code>input</code> is <code>null</code>
+    * @throws Exception
+    */
+   public static Map<String, ProtocolStackConfigInfo> parse(InputStream input) throws Exception 
+   {
+      if (input == null)
+      {
+         throw new IllegalArgumentException("null input");
+      }
+      
+      DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
+      factory.setValidating(false); //for now
+      DocumentBuilder builder=factory.newDocumentBuilder();
+      Document document=builder.parse(input);
+
+      // The root element of the document should be the "config" element,
+      // but the parser(Element) method checks this so a check is not
+      // needed here.
+      Element configElement = document.getDocumentElement();
+      return parse(configElement);
+   }
+   
+   /**
+    * Parses the contents of <code>root</code> into a map of the
+    * protocol stack configurations contained in the XML.
+    * 
+    * @param root document root node for XML content in the JGroups 
+    *              <code>stacks.xml</code> format
+    *              
+    * @return a map of the protocol stack configurations contained in the XML
+    * 
+    * @throws IllegalArgumentException if <code>input</code> is <code>null</code>
+    * @throws Exception
+    */
+   public static Map<String, ProtocolStackConfigInfo> parse(Element root) throws Exception 
+   {
+      if (root == null)
+      {
+         throw new IllegalArgumentException("null root");
+      }
+      
+      String root_name = root.getNodeName();
+      if (!PROTOCOL_STACKS.equals(root_name.trim().toLowerCase()))
+      {
+         throw new IOException("Invalid XML configuration: configuration does not start with a '" + 
+                        PROTOCOL_STACKS + "' element");
+      }
+
+      Map<String, ProtocolStackConfigInfo> result = new HashMap<String, ProtocolStackConfigInfo>();
+
+      NodeList tmp_stacks = root.getChildNodes();
+      for (int i = 0; i < tmp_stacks.getLength(); i++)
+      {
+         Node node = tmp_stacks.item(i);
+         if (node.getNodeType() != Node.ELEMENT_NODE)
+            continue;
+
+         Element stack = (Element) node;
+         String tmp = stack.getNodeName();
+         if (!STACK.equals(tmp.trim().toLowerCase()))
+         {
+            throw new IOException("Invalid configuration: didn't find a \"" + STACK + "\" element under \""
+                  + PROTOCOL_STACKS + "\"");
+         }
+
+         NamedNodeMap attrs = stack.getAttributes();
+         Node name = attrs.getNamedItem(NAME);
+         String st_name = name.getNodeValue();
+         Node descr=attrs.getNamedItem(DESCR);
+         String stack_descr=descr.getNodeValue();
+         if (log.isTraceEnabled())
+         {
+            log.trace("Parsing \"" + st_name + "\" (" + stack_descr + ")");
+         }
+         NodeList configs = stack.getChildNodes();
+         for (int j = 0; j < configs.getLength(); j++)
+         {
+            Node tmp_config = configs.item(j);
+            if (tmp_config.getNodeType() != Node.ELEMENT_NODE)
+               continue;
+            Element cfg = (Element) tmp_config;
+            tmp = cfg.getNodeName();
+            if (!CONFIG.equals(tmp))
+            {
+               throw new IOException("Invalid configuration: didn't find a \"" + 
+                     CONFIG + "\" element under \"" + STACK + "\"");
+            }
+
+            XmlConfigurator conf = XmlConfigurator.getInstance(cfg);
+            // fixes http://jira.jboss.com/jira/browse/JGRP-290
+            ConfiguratorFactory.substituteVariables(conf); // replace vars with system props
+
+            result.put(st_name, new ProtocolStackConfigInfo(st_name, stack_descr, conf));
+         }
+      }
+
+      return result;
+   }
+   
+   public static ProtocolData[] getProtocolData(ProtocolStackConfigurator config)
+   {
+      ProtocolData[] result = null;
+      try
+      {
+         result = config.getProtocolStack();
+      }
+      catch (UnsupportedOperationException e)
+      {
+         String s = config.getProtocolStackString();
+         String[] prots = s.split(":");
+         result = new ProtocolData[prots.length];
+         for (int i = 0; i < prots.length; i++)
+         {
+            ProtocolParameter[] params = null;
+            int paren = prots[i].indexOf('(');
+            String name = paren > - 1 ? prots[i].substring(0, paren) : prots[1];
+            if (paren > -1 && paren < prots[1].length() - 2)
+            {
+               String unsplit = prots[i].substring(paren + 1, prots[i].length() -1);
+               String[] split = unsplit.split(";");
+                params = new ProtocolParameter[split.length];
+               for (int j = 0; j < split.length; j++)
+               {
+                  String[] keyVal = split[j].split("=");
+                  params[j] = new ProtocolParameter(keyVal[0], keyVal[1]);
+               }
+            }
+            else
+            {
+               params = new ProtocolParameter[0];
+            }
+            
+            result[i] = new ProtocolData(name, null, name, params);
+         }
+      }
+      
+      return result == null ? new ProtocolData[0] : result;
+   }   
+   
+   /**
+    * Prevent instantiation.
+    */
+   private ProtocolStackUtil()
+   {
+   }
+
+}

Copied: branches/Branch_5_x/cluster/src/main/org/jboss/ha/framework/server/managed (from rev 90500, trunk/cluster/src/main/org/jboss/ha/framework/server/managed)

Copied: branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/channelfactory (from rev 90500, trunk/testsuite/src/main/org/jboss/test/cluster/channelfactory)

Copied: branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ChannelFactoryManagedObjectsTestCase.java (from rev 90500, trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ChannelFactoryManagedObjectsTestCase.java)
===================================================================
--- branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ChannelFactoryManagedObjectsTestCase.java	                        (rev 0)
+++ branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ChannelFactoryManagedObjectsTestCase.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -0,0 +1,317 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. 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.test.cluster.defaultcfg.test;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.jboss.deployers.spi.management.ManagementView;
+import org.jboss.managed.api.ComponentType;
+import org.jboss.managed.api.ManagedComponent;
+import org.jboss.managed.api.ManagedObject;
+import org.jboss.managed.api.ManagedProperty;
+import org.jboss.metatype.api.types.CompositeMetaType;
+import org.jboss.metatype.api.values.CollectionValue;
+import org.jboss.metatype.api.values.CollectionValueSupport;
+import org.jboss.metatype.api.values.CompositeValue;
+import org.jboss.metatype.api.values.MapCompositeValueSupport;
+import org.jboss.metatype.api.values.MetaValue;
+import org.jboss.metatype.api.values.SimpleValue;
+import org.jboss.metatype.api.values.SimpleValueSupport;
+import org.jboss.profileservice.spi.ProfileService;
+import org.jboss.test.JBossClusteredTestCase;
+import org.jboss.test.cluster.channelfactory.managed.ManagedObjectTestUtil;
+import org.jboss.virtual.VFS;
+
+/**
+ * Validates the expected ChannelFactory-related ManagedObjects are there
+ * 
+ * @author Brian Stansberry
+ * @version $Revision: 90011 $
+ */
+public class ChannelFactoryManagedObjectsTestCase
+   extends JBossClusteredTestCase
+{
+   protected ManagementView activeView;
+
+   public ChannelFactoryManagedObjectsTestCase(String name)
+   {
+      super(name);
+   }
+   
+   /**
+    * Look at the JGroups ChannelFactory ManagedComponent
+    * @throws Exception
+    */
+   public void testChannelFactory()
+      throws Exception
+   {
+      ManagedComponent mc = getChannelFactoryManagedComponent();
+      assertNotNull(mc);
+      assertEquals("JChannelFactory", mc.getNameType());
+      assertEquals("JChannelFactory", mc.getName());
+      
+      for (Map.Entry<String, ManagedProperty> entry : mc.getProperties().entrySet())
+      {
+         getLog().debug(entry.getKey() + " == " + entry.getValue());
+         ManagedObject mo = entry.getValue().getTargetManagedObject();
+         if (mo != null)
+         {
+            getLog().debug(entry.getKey() + " -- ManagedObject == " + mo);
+         }
+      }
+      
+      ManagedProperty prop = mc.getProperty("domain");
+      assertNotNull("ChannelFactory has property domain", prop);
+      MetaValue metaVal = prop.getValue();
+      assertTrue(metaVal instanceof SimpleValue);
+      Object val = ((SimpleValue) metaVal).getValue();
+      assertEquals("jboss.jgroups", val);
+      
+      prop = mc.getProperty("exposeChannels");
+      assertNotNull("ChannelFactory has property exposeChannels", prop);
+      metaVal = prop.getValue();
+      assertTrue(metaVal instanceof SimpleValue);
+      val = ((SimpleValue) metaVal).getValue();
+      assertEquals(Boolean.TRUE, val);
+      
+      prop = mc.getProperty("exposeProtocols");
+      assertNotNull("ChannelFactory has property exposeProtocols", prop);
+      metaVal = prop.getValue();
+      assertTrue(metaVal instanceof SimpleValue);
+      val = ((SimpleValue) metaVal).getValue();
+      assertEquals(Boolean.TRUE, val);
+      
+      prop = mc.getProperty("nodeName");
+      assertNotNull("ChannelFactory has property nodeName", prop);
+      metaVal = prop.getValue();
+      assertTrue(metaVal instanceof SimpleValue);
+      val = ((SimpleValue) metaVal).getValue();
+      assertNotNull(val);
+      assertTrue(val instanceof String);
+      
+      prop = mc.getProperty("assignLogicalAddresses");
+      assertNotNull("ChannelFactory has property assignLogicalAddresses", prop);
+      metaVal = prop.getValue();
+      assertTrue(metaVal instanceof SimpleValue);
+      val = ((SimpleValue) metaVal).getValue();
+      assertEquals(Boolean.TRUE, val);
+      
+      prop = mc.getProperty("manageNewThreadClassLoader");
+      assertNotNull("ChannelFactory has property manageNewThreadClassLoader", prop);
+      metaVal = prop.getValue();
+      assertTrue(metaVal instanceof SimpleValue);
+      val = ((SimpleValue) metaVal).getValue();
+      assertEquals(Boolean.TRUE, val);
+      
+      prop = mc.getProperty("manageReleasedThreadClassLoader");
+      assertNotNull("ChannelFactory has property manageReleasedThreadClassLoader", prop);
+      metaVal = prop.getValue();
+      assertTrue(metaVal instanceof SimpleValue);
+      val = ((SimpleValue) metaVal).getValue();
+      assertTrue(val instanceof Boolean);
+      
+      prop = mc.getProperty("addMissingSingletonName");
+      assertNotNull("ChannelFactory has property addMissingSingletonName", prop);
+      metaVal = prop.getValue();
+      assertTrue(metaVal instanceof SimpleValue);
+      val = ((SimpleValue) metaVal).getValue();
+      assertEquals(Boolean.TRUE, val);
+      
+      prop = mc.getProperty("state");
+      assertNotNull("ChannelFactory has property state", prop);
+
+      // FIXME ProfileService messes with this prop -- figure out how to validate
+//      metaVal = prop.getValue();      
+//      assertNotNull(metaVal);
+//      assertTrue(metaVal instanceof SimpleValue);
+//      val = ((SimpleValue) metaVal).getValue();
+//      assertEquals(ServiceMBean.states[ServiceMBean.STARTED], val);
+      
+      prop = mc.getProperty("protocolStackConfigurations");
+      assertNotNull("ChannelFactory has property protocolStackConfigurations", prop);
+      metaVal = prop.getValue();
+      ManagedObjectTestUtil.validateProtocolStackConfigurations(metaVal, new String[]{"udp", "tcp"});
+      
+      prop = mc.getProperty("openChannels");
+      assertNotNull("ChannelFactory has property openChannels", prop);
+      try
+      {
+         metaVal = prop.getValue();
+      }
+      catch (UndeclaredThrowableException ute)
+      {
+         log.error("Undeclared throwable: ", ute.getUndeclaredThrowable());
+      }
+      ManagedObjectTestUtil.validateOpenChannels(metaVal);
+   }
+
+   public void testUpdateProtocolStackConfigurations() throws Exception
+   {
+      ManagedComponent component = getChannelFactoryManagedComponent();
+      ManagedProperty prop = component.getProperty("protocolStackConfigurations");
+      MetaValue mapValue = prop.getValue();
+      assertTrue(mapValue instanceof CompositeValue);
+      MetaValue stackValue = ((CompositeValue) mapValue).get("udp-async");
+      assertTrue(stackValue instanceof CompositeValue);
+      MetaValue configurationValue = ((CompositeValue) stackValue).get("configuration");
+      assertTrue(configurationValue instanceof CollectionValue);
+      MetaValue[] protocols = ((CollectionValue) configurationValue).getElements();
+      MetaValue udp = protocols[0];
+      assertTrue(udp instanceof CompositeValue);
+      MetaValue parametersValue = ((CompositeValue) udp).get("protocolParameters");
+      assertTrue(parametersValue instanceof CompositeValue);
+      Set<String> params = ((CompositeValue) parametersValue).getMetaType().keySet();
+      int maxThreads = -1;
+      MapCompositeValueSupport newVal = null;
+      for (String name : params)
+      {         
+         if ("oob_thread_pool.max_threads".equals(name))
+         {
+            CompositeValue param = (CompositeValue) ((CompositeValue) parametersValue).get(name);
+            String value = (String) ((SimpleValue) param.get("value")).getValue();
+            maxThreads = Integer.parseInt(value);
+            newVal = cloneCompositeValue(param);
+            newVal.put("value", SimpleValueSupport.wrap(String.valueOf(maxThreads + 1)));
+            break;
+         }
+      }
+      assertNotNull("updated max_threads config", newVal);
+      
+      MapCompositeValueSupport newParametersValue = cloneCompositeValue((CompositeValue) parametersValue);
+      newParametersValue.put("oob_thread_pool.max_threads", newVal);
+      MapCompositeValueSupport newUdp = cloneCompositeValue((CompositeValue) udp);
+      newUdp.put("protocolParameters", newParametersValue);
+      protocols[0] = newUdp;
+      CollectionValue newConfigurationValue = 
+         new CollectionValueSupport(((CollectionValue) configurationValue).getMetaType(), protocols);
+      MapCompositeValueSupport updatedStack = cloneCompositeValue((CompositeValue) stackValue);
+      updatedStack.put("configuration", newConfigurationValue);
+      MapCompositeValueSupport newMapValue = cloneCompositeValue((CompositeValue) mapValue);
+      newMapValue.put("udp-async", updatedStack);
+      
+      // Add a stack
+      MapCompositeValueSupport newStack = cloneCompositeValue((CompositeValue) stackValue);
+      newStack.put("name", SimpleValueSupport.wrap("new-stack"));
+      newMapValue.put("new-stack", newStack);
+      
+      // Remove a stack
+      newMapValue.remove("tcp-async");
+      
+      // Store the updates
+      prop.setValue(newMapValue);
+      getManagementView().updateComponent(component);
+      
+      // Re-read the component and validate the changes took
+      
+      component = getChannelFactoryManagedComponent();
+      prop = component.getProperty("protocolStackConfigurations");
+      mapValue = prop.getValue();
+      assertTrue(mapValue instanceof CompositeValue);
+      stackValue = ((CompositeValue) mapValue).get("udp-async");
+      assertTrue(stackValue instanceof CompositeValue);
+      configurationValue = ((CompositeValue) stackValue).get("configuration");
+      assertTrue(configurationValue instanceof CollectionValue);
+      protocols = ((CollectionValue) configurationValue).getElements();
+      udp = protocols[0];
+      assertTrue(udp instanceof CompositeValue);
+      parametersValue = ((CompositeValue) udp).get("protocolParameters");
+      assertTrue(parametersValue instanceof CompositeValue);
+      params = ((CompositeValue) parametersValue).getMetaType().keySet();
+      boolean sawIt = false;
+      for (String name : params)
+      {
+         if ("oob_thread_pool.max_threads".equals(name))
+         {
+            CompositeValue param = (CompositeValue) ((CompositeValue) parametersValue).get(name);
+            
+            String value = (String) ((SimpleValue) param.get("value")).getValue();
+            assertEquals(String.valueOf(maxThreads + 1), value);
+            sawIt = true;
+            break;
+         }
+      }
+      assertTrue(sawIt);
+      
+      assertTrue(((CompositeValue) mapValue).containsKey("new-stack"));      
+      assertFalse(((CompositeValue) mapValue).containsKey("tcp-async"));
+   }
+
+   private ManagedComponent getChannelFactoryManagedComponent() throws Exception
+   {
+      ManagementView mgtView = getManagementView(); 
+      ComponentType type = new ComponentType("MCBean", "JGroupsChannelFactory");
+      ManagedComponent mc = mgtView.getComponent("JChannelFactory", type);
+      return mc;
+   }
+   
+   /**
+    * Obtain the ProfileService.ManagementView
+    * @return
+    * @throws Exception
+    */
+   protected ManagementView getManagementView()
+      throws Exception
+   {
+      if( activeView == null )
+      {
+         String[] urls = getNamingURLs();
+         Properties env = new Properties();
+         env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
+            "org.jnp.interfaces.NamingContextFactory");
+         env.setProperty(Context.PROVIDER_URL, urls[0]);
+         Context ctx = new InitialContext(env);
+         
+         ProfileService ps = (ProfileService) ctx.lookup("ProfileService");
+         activeView = ps.getViewManager();
+         // Init the VFS to setup the vfs* protocol handlers
+         VFS.init();
+      }
+      activeView.load();
+      return activeView;
+   }
+   
+   private static MapCompositeValueSupport cloneCompositeValue(CompositeValue toClone)
+   {
+      if (toClone instanceof MapCompositeValueSupport)
+      {
+         return (MapCompositeValueSupport) toClone.clone();
+      }
+      else
+      {
+         CompositeMetaType type = toClone.getMetaType();
+         Map<String, MetaValue> map = new HashMap<String, MetaValue>();
+         for (String key : type.keySet())
+         {
+            map.put(key, toClone.get(key));
+         }
+         return new MapCompositeValueSupport(map, type);
+      }
+   }
+
+}

Modified: branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAInvokerUnitTestCase.java
===================================================================
--- branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAInvokerUnitTestCase.java	2009-06-22 17:04:50 UTC (rev 90502)
+++ branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HAInvokerUnitTestCase.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -69,6 +69,12 @@
       haProxyFailoverTest("jmx/HAServicePooled");
    }
 
+   public void testHttpHAProxyFailover()
+      throws Exception
+   {
+      haProxyFailoverTest("jmx/HAServiceHttp");
+   }
+
    public void testJRMPHAProxyFailover()
       throws Exception
    {

Copied: branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/JChannelFactoryOverrideUnitTestCase.java (from rev 90501, trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/JChannelFactoryOverrideUnitTestCase.java)
===================================================================
--- branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/JChannelFactoryOverrideUnitTestCase.java	                        (rev 0)
+++ branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/JChannelFactoryOverrideUnitTestCase.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -0,0 +1,231 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.test.cluster.defaultcfg.test;
+
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.jboss.ha.framework.server.JChannelFactory;
+import org.jboss.ha.framework.server.ProtocolStackConfigInfo;
+import org.jboss.ha.framework.server.managed.ProtocolDataProtocolStackConfigurator;
+import org.jboss.logging.Logger;
+import org.jgroups.Channel;
+import org.jgroups.JChannel;
+import org.jgroups.conf.ProtocolData;
+import org.jgroups.conf.ProtocolParameter;
+
+/**
+ * Tests JChannelFactory's handling of configuration overrides via
+ * @[link {@link JChannelFactory#setProtocolStackConfigurations(java.util.Map)}}
+ * 
+ * @author Brian Stansberry
+ */
+public class JChannelFactoryOverrideUnitTestCase extends TestCase
+{
+   private static final Logger log = Logger.getLogger(JChannelFactoryOverrideUnitTestCase.class);
+   
+   private JChannelFactory factory;
+   private Channel channel1;
+   private Channel channel2;
+   private String jgroups_bind_addr;
+   
+   /**
+    * Create a new JChannelFactoryUnitTestCase.
+    * 
+    * @param name
+    */
+   public JChannelFactoryOverrideUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      jgroups_bind_addr = System.getProperty("jgroups.bind_addr");
+      if (jgroups_bind_addr == null)
+      {
+         System.setProperty("jbosstest.cluster.node0", System.getProperty("jbosstest.cluster.node0", "localhost"));
+      }
+      
+      factory = new JChannelFactory();
+      factory.setAssignLogicalAddresses(false);
+      factory.setNodeAddress(InetAddress.getByName("localhost"));
+      factory.setNamingServicePort(123);
+      factory.setExposeChannels(false);
+      factory.setManageReleasedThreadClassLoader(true);
+   }
+
+   protected void tearDown() throws Exception
+   {
+      super.tearDown();
+      
+      if (jgroups_bind_addr == null)
+         System.clearProperty("jgroups.bind_addr");
+      
+      if (channel1 != null && channel1.isOpen())
+         channel1.close();
+      
+      if (channel2 != null && channel2.isOpen())
+         channel2.close();
+      
+      if (factory != null)
+      {
+         factory.stop();
+         factory.destroy();
+      }
+   }
+   
+   public void testOverrideAfterStart() throws Exception
+   {
+      overrideTest(true);
+   }
+   
+   public void testOverrideBeforeStart() throws Exception
+   {
+      overrideTest(false);
+   }
+   
+   private void overrideTest(boolean startBeforeOverride) throws Exception
+   {
+      factory.setMultiplexerConfig("cluster/channelfactory/stacks.xml");  
+      if (startBeforeOverride)
+      {
+         factory.create();
+         factory.start();
+      }
+      
+      Map<String, ProtocolStackConfigInfo> origMap = factory.getProtocolStackConfigurations();
+      Set<String> origKeys = new HashSet<String>(origMap.keySet());
+      ProtocolStackConfigInfo unshared1 = origMap.get("unshared1");
+      assertNotNull(unshared1);
+      ProtocolData[] origConfig = unshared1.getConfiguration();
+      assertNotNull(origConfig);
+      // Copy it off so we know it's unchanged for later assertion comparisons
+      origConfig = origConfig.clone();
+      ProtocolData origTransport = origConfig[0];
+      assertNotNull(origTransport);
+      ProtocolParameter[] origParams = origTransport.getParametersAsArray();
+      ProtocolParameter[] newParams = origParams.clone();      
+      ProtocolData newTransport = new ProtocolData(origTransport.getProtocolName(), origTransport.getDescription(), origTransport.getClassName(), newParams);
+      ProtocolParameter overrideParam = new ProtocolParameter("max_bundle_size", "50000");
+      newTransport.override(new ProtocolParameter[]{overrideParam});
+      ProtocolData[] newConfig = origConfig.clone();
+      newConfig[0] = newTransport;
+      
+      ProtocolStackConfigInfo updated = new ProtocolStackConfigInfo(unshared1.getName(), unshared1.getDescription(), new ProtocolDataProtocolStackConfigurator(newConfig));
+      
+      Map<String, ProtocolStackConfigInfo> newMap = new HashMap<String, ProtocolStackConfigInfo>(origMap);
+      newMap.put("unshared1", updated);
+    
+      ProtocolData[] addedConfig = origConfig.clone();
+      ProtocolStackConfigInfo added = new ProtocolStackConfigInfo("added", "added", new ProtocolDataProtocolStackConfigurator(addedConfig));
+      newMap.put("added", added);
+      
+      assertTrue(newMap.containsKey("shared2"));
+      newMap.remove("shared2");
+      
+      factory.setProtocolStackConfigurations(newMap);
+      
+      if (startBeforeOverride == false)
+      {
+         factory.create();
+         factory.start();
+      }
+      
+      Map<String, ProtocolStackConfigInfo> reread = factory.getProtocolStackConfigurations();
+      origKeys.remove("shared2");
+      origKeys.add("added");
+      assertEquals(origKeys, reread.keySet());
+      
+      ProtocolStackConfigInfo addedInfo = reread.get("added");
+      assertEquals("added", addedInfo.getName());
+      assertEquals("added", addedInfo.getDescription());
+      ProtocolData[] readAdded = addedInfo.getConfiguration();
+      assertEquals(addedConfig.length, readAdded.length);
+      for (int i = 0; i < readAdded.length; i++)
+      {
+         assertEquals(addedConfig[i], readAdded[i]);
+         ProtocolParameter[] inputParams = addedConfig[i].getParametersAsArray();
+         ProtocolParameter[] outputParams = readAdded[i].getParametersAsArray();
+         assertEquals(inputParams.length, outputParams.length);
+         @SuppressWarnings("unchecked")
+         Map<String, ProtocolParameter> paramMap = readAdded[i].getParameters();
+         for (int j = 0; j < inputParams.length; j++)
+         {
+            ProtocolParameter param = paramMap.get(inputParams[j].getName());
+            assertNotNull(param);
+            assertEquals(inputParams[j].getValue(), param.getValue());
+         }
+      }
+      
+      ProtocolStackConfigInfo updatedInfo = reread.get("unshared1");
+      assertEquals("unshared1", updatedInfo.getName());
+      ProtocolData[] readUpdated = updatedInfo.getConfiguration();
+      assertEquals(origConfig.length, readUpdated.length);
+      for (int i = 0; i < readUpdated.length; i++)
+      {
+         assertEquals(origConfig[i], readUpdated[i]);
+         ProtocolParameter[] inputParams = origConfig[i].getParametersAsArray();
+         ProtocolParameter[] outputParams = readUpdated[i].getParametersAsArray();
+         assertEquals(inputParams.length, outputParams.length);
+         @SuppressWarnings("unchecked")
+         Map<String, ProtocolParameter> paramMap = readUpdated[i].getParameters();
+         for (int j = 0; j < inputParams.length; j++)
+         {
+            String name = inputParams[j].getName();
+            ProtocolParameter param = paramMap.get(name);
+            assertNotNull(param);
+            if ("max_bundle_size".equals(name))
+            {
+               assertEquals("50000", param.getValue());
+            }
+            else
+            {
+               assertEquals(inputParams[j].getValue(), param.getValue());
+            }
+         }
+      }
+      
+      // Validate that the overrides actuall affect created channels
+      channel1 = factory.createChannel("unshared1");
+      assertEquals("50000", ((JChannel) channel1).getProtocolStack().findProtocol("UDP").getProperties().get("max_bundle_size"));
+      channel2 = factory.createChannel("added");   
+      assertEquals("64000", ((JChannel) channel2).getProtocolStack().findProtocol("UDP").getProperties().get("max_bundle_size"));
+      try
+      {
+         factory.createChannel("shared2");
+         fail("should not be able to create a channel for 'shared2'");
+      }
+      catch (IllegalArgumentException good) {}
+      
+   }
+   
+   
+}

Modified: branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/JChannelFactoryUnitTestCase.java
===================================================================
--- branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/JChannelFactoryUnitTestCase.java	2009-06-22 17:04:50 UTC (rev 90502)
+++ branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/JChannelFactoryUnitTestCase.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -73,7 +73,7 @@
    {
       super.setUp();
       
-      String jgroups_bind_addr = System.getProperty("jgroups.bind_addr");
+      jgroups_bind_addr = System.getProperty("jgroups.bind_addr");
       if (jgroups_bind_addr == null)
       {
          System.setProperty("jbosstest.cluster.node0", System.getProperty("jbosstest.cluster.node0", "localhost"));
@@ -158,15 +158,19 @@
       
       channel3 = factory1.createMultiplexerChannel("unshared1", "test");
       assertFalse(channel3 instanceof MuxChannel);
-      channel3.connect("test");
+      // JBAS-7015 use unique name
+      //channel3.connect("test");
+      channel3.connect("test3");
       TP tp3 = getTP((JChannel) channel3);
       
-      assertNotSame(tp1, tp3);
+      //JBAS-7015 -- change assert
+      //assertNotSame(tp1, tp3);
+      assertSame(tp1, tp3);
       assertNotSame(tp2, tp3);
       
       channel4 = factory1.createMultiplexerChannel("unshared1", "test2");
       assertFalse(channel4 instanceof MuxChannel);
-      channel4.connect("test2");
+      channel4.connect("test4");
       TP tp4 = getTP((JChannel) channel4);
       
       assertSame(tp3, tp4);

Copied: branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/OpenChannelsMapperUnitTestCase.java (from rev 90500, trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/OpenChannelsMapperUnitTestCase.java)
===================================================================
--- branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/OpenChannelsMapperUnitTestCase.java	                        (rev 0)
+++ branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/OpenChannelsMapperUnitTestCase.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -0,0 +1,155 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.test.cluster.defaultcfg.test;
+
+import java.net.InetAddress;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+
+import junit.framework.TestCase;
+
+import org.jboss.ha.framework.server.ChannelInfo;
+import org.jboss.ha.framework.server.JChannelFactory;
+import org.jboss.ha.framework.server.managed.OpenChannelsMapper;
+import org.jboss.logging.Logger;
+import org.jboss.metatype.api.values.MetaValue;
+import org.jboss.test.cluster.channelfactory.managed.ManagedObjectTestUtil;
+import org.jboss.test.cluster.channelfactory.managed.ManagedObjectTestUtil.ChannelIds;
+import org.jgroups.Channel;
+
+/**
+ * Unit tests for OpenChannelsMapper
+ *
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class OpenChannelsMapperUnitTestCase extends TestCase
+{
+
+   private static final Logger log = Logger.getLogger(OpenChannelsMapperUnitTestCase.class);
+   
+   private JChannelFactory factory;
+   private Channel channel1;
+   private Channel channel2;
+   private Channel channel3;
+   private Channel channel4;
+   private String jgroups_bind_addr;
+   private MBeanServer mbeanServer;
+   
+   /**
+    * Create a new ProtocolStackConfigurationsMapperUnitTestCase.
+    * 
+    * @param name
+    */
+   public OpenChannelsMapperUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      String jgroups_bind_addr = System.getProperty("jgroups.bind_addr");
+      if (jgroups_bind_addr == null)
+      {
+         System.setProperty("jbosstest.cluster.node0", System.getProperty("jbosstest.cluster.node0", "localhost"));
+      }
+      
+      mbeanServer = MBeanServerFactory.createMBeanServer("jchannelfactorytest");
+      
+      factory = new JChannelFactory();
+      factory.setMultiplexerConfig("cluster/channelfactory/stacks.xml");
+      factory.setAssignLogicalAddresses(false);
+      factory.setNodeAddress(InetAddress.getByName("localhost"));
+      factory.setNamingServicePort(123);
+      factory.setExposeChannels(true);
+      factory.setServer(mbeanServer);
+      factory.setManageReleasedThreadClassLoader(true);
+      factory.create();
+      factory.start();
+   }
+
+   protected void tearDown() throws Exception
+   {
+      super.tearDown();
+      
+      if (mbeanServer != null)
+         MBeanServerFactory.releaseMBeanServer(mbeanServer);
+      
+      if (jgroups_bind_addr == null)
+         System.clearProperty("jgroups.bind_addr");
+      
+      if (channel1 != null && channel1.isOpen())
+         channel1.close();
+      
+      if (channel2 != null && channel2.isOpen())
+         channel2.close();
+      
+      if (channel3 != null && channel3.isOpen())
+         channel3.close();
+      
+      if (channel4 != null && channel4.isOpen())
+         channel4.close();
+      
+      if (factory != null)
+      {
+         factory.stop();
+         factory.destroy();
+      }
+   }
+   
+   public void testCreateMetaValue() throws Exception
+   {
+      channel1 = factory.createMultiplexerChannel("unshared1", "no1");
+      channel1.connect("channel1");
+      channel2 = factory.createMultiplexerChannel("shared1", "no2");
+      channel2.connect("channel2");
+      
+      Set<ChannelInfo> channels = factory.getOpenChannels();
+      OpenChannelsMapper testee = new OpenChannelsMapper();
+      MetaValue val = testee.createMetaValue(testee.getMetaType(), channels);
+      Set<ChannelIds> ids = ManagedObjectTestUtil.validateOpenChannels(val);
+      
+      for (ChannelIds cid : ids)
+      {
+         if ("no1".equals(cid.id))
+         {
+            assertEquals("unshared1", cid.stackName);
+            assertEquals("channel1", cid.clusterName);
+         }
+         else if ("no2".equals(cid.id))
+         {
+            assertEquals("shared1", cid.stackName);
+            assertEquals("channel2", cid.clusterName);            
+         }
+         else
+         {
+            fail("unknown id " + cid.id);
+         }
+      }
+   }
+}

Copied: branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ProtocolStackConfigurationsMapperUnitTestCase.java (from rev 90500, trunk/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ProtocolStackConfigurationsMapperUnitTestCase.java)
===================================================================
--- branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ProtocolStackConfigurationsMapperUnitTestCase.java	                        (rev 0)
+++ branches/Branch_5_x/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/ProtocolStackConfigurationsMapperUnitTestCase.java	2009-06-22 17:15:13 UTC (rev 90503)
@@ -0,0 +1,123 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.test.cluster.defaultcfg.test;
+
+import java.net.InetAddress;
+import java.util.Map;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+
+import junit.framework.TestCase;
+
+import org.jboss.ha.framework.server.JChannelFactory;
+import org.jboss.ha.framework.server.ProtocolStackConfigInfo;
+import org.jboss.ha.framework.server.managed.ProtocolStackConfigurationsMapper;
+import org.jboss.logging.Logger;
+import org.jboss.metatype.api.values.MetaValue;
+import org.jboss.test.cluster.channelfactory.managed.ManagedObjectTestUtil;
+import org.jgroups.Channel;
+
+/**
+ * Unit tests for ProtocolStackConfigurationsMapper
+ *
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class ProtocolStackConfigurationsMapperUnitTestCase extends TestCase
+{
+
+   private static final Logger log = Logger.getLogger(ProtocolStackConfigurationsMapper.class);
+   
+   private JChannelFactory factory;
+   private String jgroups_bind_addr;
+   private MBeanServer mbeanServer;
+   
+   /**
+    * Create a new ProtocolStackConfigurationsMapperUnitTestCase.
+    * 
+    * @param name
+    */
+   public ProtocolStackConfigurationsMapperUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      String jgroups_bind_addr = System.getProperty("jgroups.bind_addr");
+      if (jgroups_bind_addr == null)
+      {
+         System.setProperty("jbosstest.cluster.node0", System.getProperty("jbosstest.cluster.node0", "localhost"));
+      }
+      
+      mbeanServer = MBeanServerFactory.createMBeanServer("jchannelfactorytest");
+      
+      factory = new JChannelFactory();
+      factory.setMultiplexerConfig("cluster/channelfactory/stacks.xml");
+      factory.setAssignLogicalAddresses(false);
+      factory.setNodeAddress(InetAddress.getByName("localhost"));
+      factory.setNamingServicePort(123);
+      factory.setExposeChannels(true);
+      factory.setServer(mbeanServer);
+      factory.setManageReleasedThreadClassLoader(true);
+      factory.create();
+      factory.start();
+   }
+
+   protected void tearDown() throws Exception
+   {
+      super.tearDown();
+      
+      if (mbeanServer != null)
+         MBeanServerFactory.releaseMBeanServer(mbeanServer);
+      
+      if (jgroups_bind_addr == null)
+         System.clearProperty("jgroups.bind_addr");
+      
+      if (factory != null)
+      {
+         factory.stop();
+         factory.destroy();
+      }
+   }
+   
+   public void testRoundTrip() throws Exception
+   {
+      Map<String, ProtocolStackConfigInfo> map = factory.getProtocolStackConfigurations();
+      
+      ProtocolStackConfigurationsMapper testee = new ProtocolStackConfigurationsMapper();
+      
+      MetaValue metaValue = testee.createMetaValue(ProtocolStackConfigurationsMapper.TYPE, map);
+      ManagedObjectTestUtil.validateProtocolStackConfigurations(metaValue, new String[]{"unshared1", "shared1"});
+      
+      Map<String, ProtocolStackConfigInfo> restored = testee.unwrapMetaValue(metaValue);
+      assertEquals(map.keySet(), restored.keySet());
+      
+      // FIXME go deeper
+   }
+
+}




More information about the jboss-cvs-commits mailing list