[KARAF-4619] Add CellarHttpMBean
diff --git a/http/balancer/pom.xml b/http/balancer/pom.xml
index a14b254..6663f9f 100644
--- a/http/balancer/pom.xml
+++ b/http/balancer/pom.xml
@@ -99,6 +99,7 @@
                     <instructions>
                         <Export-Package>
                             !org.apache.karaf.cellar.http.balancer.internal.osgi,
+                            !org.apache.karaf.cellar.http.balancer.management.internal,
                             org.apache.karaf.cellar.http.balancer*
                         </Export-Package>
                         <Import-Package>
@@ -110,6 +111,7 @@
                         </Import-Package>
                         <Private-Package>
                             org.apache.karaf.cellar.http.balancer.internal.osgi,
+                            org.apache.karaf.cellar.http.balancer.management.internal,
                             org.apache.http*,
                             org.apache.commons.codec*
                         </Private-Package>
diff --git a/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/internal/osgi/Activator.java b/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/internal/osgi/Activator.java
index 219e284..ee3c8f2 100644
--- a/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/internal/osgi/Activator.java
+++ b/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/internal/osgi/Activator.java
@@ -22,11 +22,13 @@
 import org.apache.karaf.cellar.http.balancer.LocalServletListener;
 import org.apache.karaf.cellar.http.balancer.ProxyServletRegistry;
 import org.apache.karaf.cellar.http.balancer.ServletSynchronizer;
+import org.apache.karaf.cellar.http.balancer.management.internal.CellarHttpMBeanImpl;
 import org.apache.karaf.util.tracker.BaseActivator;
 import org.apache.karaf.util.tracker.annotation.ProvideService;
 import org.apache.karaf.util.tracker.annotation.RequireService;
 import org.apache.karaf.util.tracker.annotation.Services;
 import org.ops4j.pax.web.service.spi.ServletListener;
+import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,6 +54,8 @@
 
     private ProxyServletRegistry proxyRegistry;
 
+    private ServiceRegistration mbeanRegistration;
+
     @Override
     public void doStart() throws Exception {
         ClusterManager clusterManager = getTrackedService(ClusterManager.class);
@@ -106,6 +110,14 @@
         servletListener.setConfigurationAdmin(configurationAdmin);
         servletListener.setEventProducer(eventProducer);
         register(ServletListener.class, servletListener);
+
+        LOGGER.debug("CELLAR HTTP BALANCER: register MBean");
+        CellarHttpMBeanImpl mbean = new CellarHttpMBeanImpl();
+        mbean.setClusterManager(clusterManager);
+        mbean.setGroupManager(groupManager);
+        props = new Hashtable();
+        props.put("jmx.objectname", "org.apache.karaf.cellar:type=http,name=" + System.getProperty("karaf.name"));
+        mbeanRegistration = bundleContext.registerService(getInterfaceNames(mbean), mbean, props);
     }
 
     @Override
@@ -116,6 +128,11 @@
             proxyRegistry.destroy();
             proxyRegistry = null;
         }
+
+        if (mbeanRegistration != null) {
+            mbeanRegistration.unregister();
+            mbeanRegistration = null;
+        }
     }
 
 }
diff --git a/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/management/CellarHttpMBean.java b/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/management/CellarHttpMBean.java
new file mode 100644
index 0000000..b8d6274
--- /dev/null
+++ b/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/management/CellarHttpMBean.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.cellar.http.balancer.management;
+
+import java.util.Map;
+
+public interface CellarHttpMBean {
+
+    /**
+     * List the HTTP servlets on a cluster group.
+     *
+     * @param group The cluster group name.
+     * @return A map with HTTP servlet aliases and locations.
+     * @throws Exception
+     */
+    Map<String, String> listHttp(String group) throws Exception;
+
+}
diff --git a/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/management/internal/CellarHttpMBeanImpl.java b/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/management/internal/CellarHttpMBeanImpl.java
new file mode 100644
index 0000000..f32df69
--- /dev/null
+++ b/http/balancer/src/main/java/org/apache/karaf/cellar/http/balancer/management/internal/CellarHttpMBeanImpl.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.cellar.http.balancer.management.internal;
+
+import org.apache.karaf.cellar.core.ClusterManager;
+import org.apache.karaf.cellar.core.Configurations;
+import org.apache.karaf.cellar.core.Group;
+import org.apache.karaf.cellar.core.GroupManager;
+import org.apache.karaf.cellar.http.balancer.Constants;
+import org.apache.karaf.cellar.http.balancer.management.CellarHttpMBean;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CellarHttpMBeanImpl extends StandardMBean implements CellarHttpMBean {
+
+    private GroupManager groupManager;
+    private ClusterManager clusterManager;
+
+    public CellarHttpMBeanImpl() throws NotCompliantMBeanException {
+        super(CellarHttpMBean.class);
+    }
+
+    public GroupManager getGroupManager() {
+        return groupManager;
+    }
+
+    public void setGroupManager(GroupManager groupManager) {
+        this.groupManager = groupManager;
+    }
+
+    public ClusterManager getClusterManager() {
+        return clusterManager;
+    }
+
+    public void setClusterManager(ClusterManager clusterManager) {
+        this.clusterManager = clusterManager;
+    }
+
+    @Override
+    public Map<String, String> listHttp(String groupName) throws Exception {
+        Map<String, String> result = new HashMap<String, String>();
+        Group group = groupManager.findGroupByName(groupName);
+        if (group == null) {
+            throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
+        }
+
+        Map<String, List<String>> clusterServlets = clusterManager.getMap(Constants.BALANCER_MAP + Configurations.SEPARATOR + groupName);
+
+
+        for (String alias : clusterServlets.keySet()) {
+            List<String> locations = clusterServlets.get(alias);
+            StringBuilder builder = new StringBuilder();
+            for (String location : locations) {
+                builder.append(location).append(" ");
+            }
+            result.put(alias, builder.toString());
+        }
+
+        return result;
+    }
+}