You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rg...@apache.org on 2016/12/03 22:11:17 UTC

svn commit: r1772491 [1/2] - in /qpid/java/trunk: broker-core/src/main/java/org/apache/qpid/server/model/ broker-core/src/main/java/org/apache/qpid/server/model/port/ broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin...

Author: rgodfrey
Date: Sat Dec  3 22:11:17 2016
New Revision: 1772491

URL: http://svn.apache.org/viewvc?rev=1772491&view=rev
Log:
QPID-7563 : Add the ability to serve a REST API for an individual virtual host

Modified:
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/SystemAddressSpaceAlias.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/JsonValueServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/TimeZoneServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostQueryServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RestUserPreferenceHandlerTest.java

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java Sat Dec  3 22:11:17 2016
@@ -34,6 +34,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Pattern;
 
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
@@ -81,6 +82,12 @@ public class ConfiguredObjectFinder
             }
         }
     }
+
+    public Collection<Class<? extends ConfiguredObject>> getManagedCategories()
+    {
+        return Collections.unmodifiableCollection(_hierarchies.keySet());
+    }
+
     private String[] getPathElements(final String path)
     {
         String[] pathElements = path.split("(?<!\\\\)" + Pattern.quote("/"));
@@ -113,10 +120,27 @@ public class ConfiguredObjectFinder
         }
     }
 
+    public Class<? extends ConfiguredObject>[] getHierarchy(String categoryName)
+    {
+        for(Class<? extends ConfiguredObject> category : _model.getSupportedCategories())
+        {
+            if(category.getSimpleName().toLowerCase().equals(categoryName))
+            {
+                return getHierarchy(category);
+            }
+        }
+        return null;
+    }
+
     public Class<? extends ConfiguredObject>[] getHierarchy(final Class<? extends ConfiguredObject> category)
     {
-        List<Class<? extends ConfiguredObject>> hierarchy = _hierarchies.get(_model.getTypeRegistry().getCategory(category));
-        return hierarchy.toArray(new Class[hierarchy.size()]);
+        List<Class<? extends ConfiguredObject>> hierarchy = _hierarchies.get(ConfiguredObjectTypeRegistry.getCategory(category));
+        return hierarchy == null ? null : hierarchy.toArray(new Class[hierarchy.size()]);
+    }
+
+    public Set<Class<? extends ConfiguredObject>> getAssociatedChildCategories()
+    {
+        return Collections.unmodifiableSet(_associatedChildrenOperations.keySet());
     }
 
     public Collection<ConfiguredObject<?>> findObjectsFromPath(List<String> path,
@@ -477,4 +501,20 @@ public class ConfiguredObjectFinder
         }
         throw new ServerScopedRuntimeException("Unable to process type when constructing configuration model: " + t);
     }
+
+    public Collection<? extends ConfiguredObject> getAssociatedChildren(final Class<? extends ConfiguredObject> childClass)
+    {
+        final ConfiguredObjectOperation<ConfiguredObject<?>> op =
+                _associatedChildrenOperations.get(childClass);
+        if (op != null)
+        {
+
+            return Collections.unmodifiableCollection((Collection<? extends ConfiguredObject<?>>) op.perform(_root,
+                                                                                                             Collections.<String, Object>emptyMap()));
+        }
+        else
+        {
+            return Collections.emptySet();
+        }
+    }
 }

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/PatternMatchingAlias.java Sat Dec  3 22:11:17 2016
@@ -31,6 +31,6 @@ public interface PatternMatchingAlias<X
     @ManagedAttribute( defaultValue = "200" )
     int getPriority();
 
-    @ManagedAttribute( mandatory = true)
+    @ManagedAttribute( defaultValue = ".*")
     public String getPattern();
 }

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Port.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Port.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Port.java Sat Dec  3 22:11:17 2016
@@ -92,4 +92,5 @@ public interface Port<X extends Port<X>>
 
     ListenableFuture<Void> startAsync();
 
+    NamedAddressSpace getAddressSpace(String name);
 }

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/SystemAddressSpaceAlias.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/SystemAddressSpaceAlias.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/SystemAddressSpaceAlias.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/SystemAddressSpaceAlias.java Sat Dec  3 22:11:17 2016
@@ -27,11 +27,12 @@ public interface SystemAddressSpaceAlias
     String TYPE_NAME = "systemAddressAlias";
 
     String PATTERN = "pattern";
+    String SYSTEM_ADDRESS_SPACE = "systemAddressSpace";
 
     @ManagedAttribute( defaultValue = "200" )
     int getPriority();
 
-    @ManagedAttribute( mandatory = true)
+    @ManagedAttribute( defaultValue = ".*")
     String getPattern();
 
     @ManagedAttribute( mandatory = true)

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java Sat Dec  3 22:11:17 2016
@@ -20,11 +20,36 @@
  */
 package org.apache.qpid.server.model;
 
-@ManagedObject
+import java.util.Comparator;
+
+@ManagedObject( creatable = false )
 public interface VirtualHostAlias<X extends VirtualHostAlias<X>> extends ConfiguredObject<X>
 {
-    String PRIORITY = "priority";
+    Comparator<VirtualHostAlias> COMPARATOR = new Comparator<VirtualHostAlias>()
+    {
+        @Override
+        public int compare(final VirtualHostAlias left, final VirtualHostAlias right)
+        {
+            int comparison = left.getPriority() - right.getPriority();
+            if (comparison == 0)
+            {
+                long leftTime = left.getCreatedTime() == null ? 0 : left.getCreatedTime().getTime();
+                long rightTime = right.getCreatedTime() == null ? 0 : right.getCreatedTime().getTime();
+                long createCompare = leftTime - rightTime;
+                if (createCompare == 0)
+                {
+                    comparison = left.getName().compareTo(right.getName());
+                }
+                else
+                {
+                    comparison = createCompare < 0L ? -1 : 1;
+                }
+            }
+            return comparison;
+        }
+    };
 
+    String PRIORITY = "priority";
     // parents
     Port getPort();
 

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java Sat Dec  3 22:11:17 2016
@@ -25,6 +25,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -42,12 +43,14 @@ import org.apache.qpid.server.model.Conn
 import org.apache.qpid.server.model.Container;
 import org.apache.qpid.server.model.KeyStore;
 import org.apache.qpid.server.model.ManagedAttributeField;
+import org.apache.qpid.server.model.NamedAddressSpace;
 import org.apache.qpid.server.model.Port;
 import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.StateTransition;
 import org.apache.qpid.server.model.Transport;
 import org.apache.qpid.server.model.TrustStore;
+import org.apache.qpid.server.model.VirtualHostAlias;
 import org.apache.qpid.server.util.ParameterizedTypes;
 
 public abstract class AbstractPort<X extends AbstractPort<X>> extends AbstractConfiguredObject<X> implements Port<X>
@@ -274,6 +277,36 @@ public abstract class AbstractPort<X ext
     }
 
 
+    @Override
+    public NamedAddressSpace getAddressSpace(String name)
+    {
+        Collection<VirtualHostAlias> aliases = new TreeSet<>(VirtualHostAlias.COMPARATOR);
+
+        aliases.addAll(getChildren(VirtualHostAlias.class));
+
+        for(VirtualHostAlias alias : aliases)
+        {
+            NamedAddressSpace addressSpace = alias.getAddressSpace(name);
+            if (addressSpace != null)
+            {
+                return addressSpace;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public <C extends ConfiguredObject> ListenableFuture<C> addChildAsync(final Class<C> childClass,
+                                                                          final Map<String, Object> attributes,
+                                                                          final ConfiguredObject... otherParents)
+    {
+        if (VirtualHostAlias.class.isAssignableFrom(childClass))
+        {
+            return getObjectFactory().createAsync(childClass, attributes, this);
+        }
+        return super.addChildAsync(childClass, attributes, otherParents);
+    }
+
     protected State onActivate()
     {
         // no-op: expected to be overridden by subclass

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java Sat Dec  3 22:11:17 2016
@@ -143,8 +143,6 @@ public interface AmqpPort<X extends Amqp
                                     + " the connection will be aborted.")
     long getProtocolHandshakeTimeout();
 
-    NamedAddressSpace getAddressSpace(String name);
-
     boolean canAcceptNewConnection(final SocketAddress remoteSocketAddress);
 
     int incrementConnectionCount();

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java Sat Dec  3 22:11:17 2016
@@ -27,7 +27,6 @@ import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -87,29 +86,6 @@ public class AmqpPortImpl extends Abstra
     public static final String DEFAULT_BINDING_ADDRESS = "*";
 
 
-    private static final Comparator<VirtualHostAlias> VIRTUAL_HOST_ALIAS_COMPARATOR = new Comparator<VirtualHostAlias>()
-    {
-        @Override
-        public int compare(final VirtualHostAlias left, final VirtualHostAlias right)
-        {
-            int comparison = left.getPriority() - right.getPriority();
-            if (comparison == 0)
-            {
-                long leftTime = left.getCreatedTime() == null ? 0 : left.getCreatedTime().getTime();
-                long rightTime = right.getCreatedTime() == null ? 0 : right.getCreatedTime().getTime();
-                long createCompare = leftTime - rightTime;
-                if (createCompare == 0)
-                {
-                    comparison = left.getName().compareTo(right.getName());
-                }
-                else
-                {
-                    comparison = createCompare < 0l ? -1 : 1;
-                }
-            }
-            return comparison;
-        }
-    };
     @ManagedAttributeField
     private boolean _tcpNoDelay;
 
@@ -223,36 +199,6 @@ public class AmqpPortImpl extends Abstra
     }
 
     @Override
-    public <C extends ConfiguredObject> ListenableFuture<C> addChildAsync(final Class<C> childClass,
-                                                                          final Map<String, Object> attributes,
-                                                                          final ConfiguredObject... otherParents)
-    {
-        if (VirtualHostAlias.class.isAssignableFrom(childClass))
-        {
-            return getObjectFactory().createAsync(childClass, attributes, this);
-        }
-        return super.addChildAsync(childClass, attributes, otherParents);
-    }
-
-    @Override
-    public NamedAddressSpace getAddressSpace(String name)
-    {
-        Collection<VirtualHostAlias> aliases = new TreeSet<>(VIRTUAL_HOST_ALIAS_COMPARATOR);
-
-        aliases.addAll(getChildren(VirtualHostAlias.class));
-
-        for(VirtualHostAlias alias : aliases)
-        {
-            NamedAddressSpace addressSpace = alias.getAddressSpace(name);
-            if (addressSpace != null)
-            {
-                return addressSpace;
-            }
-        }
-        return null;
-    }
-
-    @Override
     protected State onActivate()
     {
         if(getAncestor(SystemConfig.class).isManagementMode())

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java Sat Dec  3 22:11:17 2016
@@ -30,9 +30,7 @@ import org.apache.qpid.server.model.Prot
 import org.apache.qpid.server.model.Transport;
 import org.apache.qpid.server.model.TrustStore;
 
-@ManagedObject( category = false, type = "HTTP",
-        validChildTypes = "org.apache.qpid.server.model.port.HttpPortImpl#getSupportedChildTypes()",
-        amqpName = "org.apache.qpid.HttpPort")
+@ManagedObject( category = false, type = "HTTP", amqpName = "org.apache.qpid.HttpPort")
 public interface HttpPort<X extends HttpPort<X>> extends ClientAuthCapablePort<X>
 {
     String DEFAULT_HTTP_NEED_CLIENT_AUTH = "false";
@@ -95,4 +93,9 @@ public interface HttpPort<X extends Http
     @ManagedAttribute( defaultValue = "false", description = "If true allow operations which may return confidential "
                                                              + "information to be executed on insecure connections")
     boolean isAllowConfidentialOperationsOnInsecureChannels();
+
+    @ManagedAttribute( defaultValue = "true", description = "If true then this port will provide HTTP management "
+                                                            + "services for the broker, if no virtualhostalaias "
+                                                            + "matches the HTTP Host in the request")
+    boolean isManageBrokerOnNoAliasMatch();
 }

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java Sat Dec  3 22:11:17 2016
@@ -20,17 +20,24 @@
  */
 package org.apache.qpid.server.model.port;
 
+import java.security.PrivilegedAction;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
+import javax.security.auth.Subject;
+
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.Container;
+import org.apache.qpid.server.model.HostNameAlias;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.PatternMatchingAlias;
 import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.SystemAddressSpaceAlias;
 import org.apache.qpid.server.model.VirtualHostAlias;
 import org.apache.qpid.server.util.PortUtil;
 
@@ -50,6 +57,9 @@ public class HttpPortImpl extends Abstra
     @ManagedAttributeField
     private boolean _allowConfidentialOperationsOnInsecureChannels;
 
+    @ManagedAttributeField
+    private boolean _manageBrokerOnNoAliasMatch;
+
     @ManagedObjectFactoryConstructor
     public HttpPortImpl(final Map<String, Object> attributes,
                         final Container<?> container)
@@ -88,6 +98,12 @@ public class HttpPortImpl extends Abstra
     }
 
     @Override
+    public boolean isManageBrokerOnNoAliasMatch()
+    {
+        return _manageBrokerOnNoAliasMatch;
+    }
+
+    @Override
     protected State onActivate()
     {
         if(_portManager != null && _portManager.isActivationAllowed(this))
@@ -158,8 +174,4 @@ public class HttpPortImpl extends Abstra
         }
     }
 
-    public static Map<String, Collection<String>> getSupportedChildTypes()
-    {
-        return Collections.singletonMap(VirtualHostAlias.class.getSimpleName(), (Collection<String>) Collections.<String>emptyList());
-    }
 }

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java Sat Dec  3 22:11:17 2016
@@ -346,7 +346,7 @@ public class HttpManagement extends Abst
             root.addFilter(RewriteRequestForUncompressedJavascript.class, "/dojo/dojox/*", EnumSet.of(DispatcherType.REQUEST));
         }
 
-        addRestServlet(root, Broker.class);
+        addRestServlet(root);
 
         ServletHolder queryServlet = new ServletHolder(new BrokerQueryServlet());
         root.addServlet(queryServlet, "/api/latest/querybroker/*");
@@ -357,7 +357,7 @@ public class HttpManagement extends Abst
         root.addServlet(vhQueryServlet, "/api/v" + BrokerModel.MODEL_VERSION + "/queryvhost/*");
 
 
-        ServletHolder apiDocsServlet = new ServletHolder(new ApiDocsServlet(getModel()));
+        ServletHolder apiDocsServlet = new ServletHolder(new ApiDocsServlet());
         final ServletHolder rewriteSerlvet = new ServletHolder(new RewriteServlet("^(.*)$", "$1/"));
         for(String path : new String[]{"/apidocs", "/apidocs/latest", "/apidocs/"+getLatestSupportedVersion()})
         {
@@ -368,7 +368,7 @@ public class HttpManagement extends Abst
         root.addServlet(new ServletHolder(new StructureServlet()), "/service/structure");
         root.addServlet(new ServletHolder(new QueueReportServlet()), "/service/queuereport/*");
 
-        root.addServlet(new ServletHolder(new MetaDataServlet(getModel())), "/service/metadata");
+        root.addServlet(new ServletHolder(new MetaDataServlet()), "/service/metadata");
 
         root.addServlet(new ServletHolder(new SaslServlet()), "/service/sasl");
 
@@ -635,55 +635,36 @@ public class HttpManagement extends Abst
         return connector;
     }
 
-    private void addRestServlet(ServletContextHandler root, final Class<? extends ConfiguredObject> rootClass)
+    private void addRestServlet(ServletContextHandler root)
     {
-        Set<Class<? extends ConfiguredObject>> categories = new HashSet<>(getModel().getDescendantCategories(rootClass));
-        categories.add(rootClass);
-        for(Class<? extends ConfiguredObject> category : categories)
-        {
-                String name = category.getSimpleName().toLowerCase();
-                List<Class<? extends ConfiguredObject>> hierarchyList = new ArrayList<>();
-
-                if(category != rootClass)
-                {
-                    Collection<Class<? extends ConfiguredObject>> parentCategories;
-
-                    hierarchyList.add(category);
+        Set<Class<? extends ConfiguredObject>> categories = new HashSet<>(getModel().getSupportedCategories());
+        final RestServlet restServlet = new RestServlet();
+        final ApiDocsServlet apiDocsServlet = new ApiDocsServlet();
+
+        for (Class<? extends ConfiguredObject> category : categories)
+        {
+            String name = category.getSimpleName().toLowerCase();
+
+            ServletHolder servletHolder = new ServletHolder(name, restServlet);
+            servletHolder.getRegistration().setMultipartConfig(
+                    new MultipartConfigElement("",
+                                               getContextValue(Long.class, MAX_HTTP_FILE_UPLOAD_SIZE_CONTEXT_NAME),
+                                               -1l,
+                                               getContextValue(Integer.class,
+                                                               MAX_HTTP_FILE_UPLOAD_SIZE_CONTEXT_NAME)));
 
-                    while (!(parentCategories = getModel().getParentTypes(category)).contains(rootClass))
-                    {
-                        hierarchyList.addAll(parentCategories);
-                        category = parentCategories.iterator().next();
-                    }
+            List<String> paths = Arrays.asList("/api/latest/" + name,
+                                               "/api/v" + BrokerModel.MODEL_VERSION + "/" + name);
 
-                    Collections.reverse(hierarchyList);
-
-                }
-                Class<? extends ConfiguredObject>[] hierarchyArray =
-                        hierarchyList.toArray(new Class[hierarchyList.size()]);
-
-                ServletHolder servletHolder = new ServletHolder(name, new RestServlet(hierarchyArray));
-                servletHolder.getRegistration().setMultipartConfig(
-                        new MultipartConfigElement("",
-                                                   getContextValue(Long.class, MAX_HTTP_FILE_UPLOAD_SIZE_CONTEXT_NAME),
-                                                   -1l,
-                                                   getContextValue(Integer.class,
-                                                                   MAX_HTTP_FILE_UPLOAD_SIZE_CONTEXT_NAME)));
-
-                List<String> paths = Arrays.asList("/api/latest/" + name,
-                                                   "/api/v" + BrokerModel.MODEL_VERSION + "/" + name);
-
-                for (String path : paths)
-                {
-                    root.addServlet(servletHolder, path + "/*");
-                }
-                ServletHolder docServletHolder = new ServletHolder(name + "docs", new ApiDocsServlet(getModel(),
-                                                                                                     paths,
-                                                                                                     hierarchyArray));
-                root.addServlet(docServletHolder, "/apidocs/latest/" + name + "/");
-                root.addServlet(docServletHolder, "/apidocs/v" + BrokerModel.MODEL_VERSION + "/" + name + "/");
-                root.addServlet(docServletHolder, "/apidocs/latest/" + name);
-                root.addServlet(docServletHolder, "/apidocs/v" + BrokerModel.MODEL_VERSION + "/" + name);
+            for (String path : paths)
+            {
+                root.addServlet(servletHolder, path + "/*");
+            }
+            ServletHolder docServletHolder = new ServletHolder(name + "docs", apiDocsServlet);
+            root.addServlet(docServletHolder, "/apidocs/latest/" + name + "/");
+            root.addServlet(docServletHolder, "/apidocs/v" + BrokerModel.MODEL_VERSION + "/" + name + "/");
+            root.addServlet(docServletHolder, "/apidocs/latest/" + name);
+            root.addServlet(docServletHolder, "/apidocs/v" + BrokerModel.MODEL_VERSION + "/" + name);
 
 
         }

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java Sat Dec  3 22:11:17 2016
@@ -32,6 +32,8 @@ import java.security.PrivilegedException
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.zip.GZIPOutputStream;
 
 import javax.security.auth.Subject;
@@ -48,13 +50,21 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.qpid.server.management.plugin.GunzipOutputStream;
+import org.apache.qpid.server.management.plugin.HttpManagement;
 import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
 import org.apache.qpid.server.management.plugin.HttpManagementUtil;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFinder;
 import org.apache.qpid.server.model.ConfiguredObjectJacksonModule;
 import org.apache.qpid.server.model.Content;
 import org.apache.qpid.server.model.CustomRestHeaders;
+import org.apache.qpid.server.model.NamedAddressSpace;
 import org.apache.qpid.server.model.RestContentHeader;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.port.HttpPort;
 import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
 
 public abstract class AbstractServlet extends HttpServlet
@@ -63,8 +73,10 @@ public abstract class AbstractServlet ex
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractServlet.class);
     public static final String CONTENT_DISPOSITION = "Content-disposition";
 
-    private Broker<?> _broker;
-    private HttpManagementConfiguration _managementConfiguration;
+    private transient Broker<?> _broker;
+    private transient HttpManagementConfiguration _managementConfiguration;
+    private transient final ConcurrentMap<ConfiguredObject<?>, ConfiguredObjectFinder> _configuredObjectFinders = new ConcurrentHashMap<>();
+
 
     protected AbstractServlet()
     {
@@ -90,7 +102,11 @@ public abstract class AbstractServlet ex
                 @Override
                 public Void run() throws Exception
                 {
-                    doGetWithSubjectAndActor(request, resp);
+                    ConfiguredObject<?> managedObject = getManagedObject(request, resp);
+                    if(managedObject != null)
+                    {
+                        doGetWithSubjectAndActor(request, resp, managedObject);
+                    }
                     return null;
                 }
             },
@@ -99,11 +115,37 @@ public abstract class AbstractServlet ex
         );
     }
 
+    private ConfiguredObject<?> getManagedObject(final HttpServletRequest request, final HttpServletResponse resp)
+    {
+        HttpPort<?> port =  HttpManagement.getPort(request);
+        final NamedAddressSpace addressSpace = port.getAddressSpace(request.getServerName());
+        if(addressSpace == null)
+        {
+            if(port.isManageBrokerOnNoAliasMatch())
+            {
+                return getBroker();
+            }
+            LOGGER.info("No HTTP Management alias mapping found for host '{}' on port {}", request.getServerName(), port);
+            sendError(resp, HttpServletResponse.SC_NOT_FOUND);
+            return null;
+        }
+        else if(addressSpace instanceof VirtualHost<?>)
+        {
+            return (VirtualHost<?>)addressSpace;
+        }
+        else
+        {
+            return getBroker();
+        }
+    }
+
     /**
      * Performs the GET action as the logged-in {@link Subject}.
      * Subclasses commonly override this method
      */
-    protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException
+    protected void doGetWithSubjectAndActor(HttpServletRequest request,
+                                            HttpServletResponse resp,
+                                            ConfiguredObject<?> managedObject) throws ServletException, IOException
     {
         throw new UnsupportedOperationException("GET not supported by this servlet");
     }
@@ -118,7 +160,11 @@ public abstract class AbstractServlet ex
                 @Override
                 public Void run()  throws Exception
                 {
-                    doPostWithSubjectAndActor(request, resp);
+                    ConfiguredObject<?> managedObject = getManagedObject(request, resp);
+                    if(managedObject != null)
+                    {
+                        doPostWithSubjectAndActor(request, resp, managedObject);
+                    }
                     return null;
                 }
             },
@@ -131,7 +177,9 @@ public abstract class AbstractServlet ex
      * Performs the POST action as the logged-in {@link Subject}.
      * Subclasses commonly override this method
      */
-    protected void doPostWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+    protected void doPostWithSubjectAndActor(HttpServletRequest req,
+                                             HttpServletResponse resp,
+                                             ConfiguredObject<?> managedObject) throws ServletException, IOException
     {
         throw new UnsupportedOperationException("POST not supported by this servlet");
     }
@@ -145,7 +193,11 @@ public abstract class AbstractServlet ex
                 @Override
                 public Void run() throws Exception
                 {
-                    doPutWithSubjectAndActor(request, resp);
+                    ConfiguredObject<?> managedObject = getManagedObject(request, resp);
+                    if(managedObject != null)
+                    {
+                        doPutWithSubjectAndActor(request, resp, managedObject);
+                    }
                     return null;
                 }
             },
@@ -164,7 +216,9 @@ public abstract class AbstractServlet ex
      * Performs the PUT action as the logged-in {@link Subject}.
      * Subclasses commonly override this method
      */
-    protected void doPutWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+    protected void doPutWithSubjectAndActor(HttpServletRequest req,
+                                            HttpServletResponse resp,
+                                            final ConfiguredObject<?> managedObject) throws ServletException, IOException
     {
         throw new UnsupportedOperationException("PUT not supported by this servlet");
     }
@@ -179,7 +233,11 @@ public abstract class AbstractServlet ex
                 @Override
                 public Void run() throws Exception
                 {
-                    doDeleteWithSubjectAndActor(request, resp);
+                    ConfiguredObject<?> managedObject = getManagedObject(request, resp);
+                    if(managedObject != null)
+                    {
+                        doDeleteWithSubjectAndActor(request, resp, managedObject);
+                    }
                     return null;
                 }
             },
@@ -192,7 +250,9 @@ public abstract class AbstractServlet ex
      * Performs the PUT action as the logged-in {@link Subject}.
      * Subclasses commonly override this method
      */
-    protected void doDeleteWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+    protected void doDeleteWithSubjectAndActor(HttpServletRequest req,
+                                               HttpServletResponse resp,
+                                               ConfiguredObject<?> managedObject) throws ServletException, IOException
     {
         throw new UnsupportedOperationException("DELETE not supported by this servlet");
     }
@@ -437,4 +497,44 @@ public abstract class AbstractServlet ex
         return results;
     }
 
+
+    protected final ConfiguredObjectFinder getConfiguredObjectFinder(final ConfiguredObject<?> root)
+    {
+        ConfiguredObjectFinder finder = _configuredObjectFinders.get(root);
+        if(finder == null)
+        {
+            finder = new ConfiguredObjectFinder(root);
+            final ConfiguredObjectFinder existingValue = _configuredObjectFinders.putIfAbsent(root, finder);
+            if(existingValue != null)
+            {
+                finder = existingValue;
+            }
+            else
+            {
+                final AbstractConfigurationChangeListener deletionListener =
+                        new AbstractConfigurationChangeListener()
+                        {
+                            @Override
+                            public void stateChanged(final ConfiguredObject<?> object,
+                                                     final State oldState,
+                                                     final State newState)
+                            {
+                                if (newState == State.DELETED)
+                                {
+                                    _configuredObjectFinders.remove(root);
+                                }
+                            }
+                        };
+                root.addChangeListener(deletionListener);
+                if(root.getState() == State.DELETED)
+                {
+                    _configuredObjectFinders.remove(root);
+                    root.removeChangeListener(deletionListener);
+                }
+            }
+        }
+        return finder;
+    }
+
+
 }

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java Sat Dec  3 22:11:17 2016
@@ -19,6 +19,8 @@ package org.apache.qpid.server.managemen
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -27,9 +29,9 @@ import javax.servlet.http.HttpServletRes
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.ConfiguredObjectAttribute;
+import org.apache.qpid.server.model.ConfiguredObjectFinder;
 import org.apache.qpid.server.model.ConfiguredObjectOperation;
 import org.apache.qpid.server.model.ConfiguredSettableAttribute;
 import org.apache.qpid.server.model.ManagedContextDefault;
@@ -42,10 +44,6 @@ public class ApiDocsServlet extends Abst
     private static final long serialVersionUID = 1L;
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ApiDocsServlet.class);
-    private final Model _model;
-    private final List<Class<? extends ConfiguredObject>> _types;
-
-    private Class<? extends ConfiguredObject>[] _hierarchy;
 
     private static final Set<Character> VOWELS = new HashSet<>(Arrays.asList('a','e','i','o','u'));
 
@@ -60,36 +58,53 @@ public class ApiDocsServlet extends Abst
                 }
 
             };
-    private static final Map<Class<? extends ConfiguredObject>, List<String>> REGISTERED_CLASSES = new TreeMap<>(CLASS_COMPARATOR);
 
+    private transient final ConcurrentMap<Class<? extends ConfiguredObject>, List<Class<? extends ConfiguredObject>>> _typeSpecialisations = new ConcurrentHashMap<>();
 
-    public ApiDocsServlet(final Model model)
+    public ApiDocsServlet()
     {
         super();
-        _model = model;
-        _hierarchy = null;
-        _types = null;
     }
 
-    public ApiDocsServlet(final Model model, final List<String> registeredPaths, Class<? extends ConfiguredObject>... hierarchy)
+    @Override
+    protected void doGetWithSubjectAndActor(HttpServletRequest request,
+                                            HttpServletResponse response,
+                                            final ConfiguredObject<?> managedObject) throws ServletException, IOException
     {
-        super();
-        _model = model;
-        _hierarchy = hierarchy;
-        _types = new ArrayList<>(_model.getTypeRegistry().getTypeSpecialisations(getConfiguredClass()));
-        Collections.sort(_types, CLASS_COMPARATOR);
-        List<String> paths = REGISTERED_CLASSES.get(getConfiguredClass());
-        if (paths == null)
+        ConfiguredObjectFinder finder = getConfiguredObjectFinder(managedObject);
+
+        final Class<? extends ConfiguredObject> configuredClass;
+
+        final Class<? extends ConfiguredObject>[] hierarchy;
+
+        final String[] servletPathParts = request.getServletPath().split("/");
+        final Model model = managedObject.getModel();
+        if(servletPathParts.length < 4)
         {
-            paths = new ArrayList<>();
-            REGISTERED_CLASSES.put(getConfiguredClass(), paths);
+            configuredClass = null;
+            hierarchy = null;
+        }
+        else
+        {
+            configuredClass = getConfiguredClass(request, managedObject);
+            if (configuredClass == null)
+            {
+                sendError(response, HttpServletResponse.SC_NOT_FOUND);
+                return;
+            }
+            hierarchy = finder.getHierarchy(configuredClass);
+            if (hierarchy == null)
+            {
+                sendError(response, HttpServletResponse.SC_NOT_FOUND);
+                return;
+            }
+            if(!_typeSpecialisations.containsKey(configuredClass))
+            {
+                List<Class<? extends ConfiguredObject>> types = new ArrayList<>(model
+                                                                                        .getTypeRegistry().getTypeSpecialisations(configuredClass));
+                _typeSpecialisations.putIfAbsent(configuredClass, types);
+            }
         }
-        paths.addAll(registeredPaths);
-    }
-
-    @Override
-    protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
-    {
         response.setContentType("text/html");
         response.setStatus(HttpServletResponse.SC_OK);
 
@@ -97,9 +112,9 @@ public class ApiDocsServlet extends Abst
         PrintWriter writer = response.getWriter();
 
         writePreamble(writer);
-        writeHead(writer);
+        writeHead(writer, hierarchy, configuredClass);
 
-        if(_hierarchy == null)
+        if(hierarchy == null)
         {
             writer.println("<table class=\"api\">");
             writer.println("<thead>");
@@ -110,23 +125,19 @@ public class ApiDocsServlet extends Abst
             writer.println("</tr>");
             writer.println("</thead>");
             writer.println("<tbody>");
-            for(Map.Entry<Class<? extends ConfiguredObject>, List<String>> entry : REGISTERED_CLASSES.entrySet())
+            SortedSet<Class<? extends ConfiguredObject>> managedCategories = new TreeSet<>(CLASS_COMPARATOR);
+            managedCategories.addAll(finder.getManagedCategories());
+            String pathStem = "/" + servletPathParts[1] + "/" + (servletPathParts.length == 2 ? "latest" : servletPathParts[2]) + "/";
+            for(Class<? extends ConfiguredObject> category : managedCategories)
             {
-                List<String> paths = entry.getValue();
-                Class<? extends ConfiguredObject> objClass = entry.getKey();
+                Class<? extends ConfiguredObject> objClass = category;
+                String path = pathStem + category.getSimpleName().toLowerCase();
                 writer.println("<tr>");
-                writer.println("<td class=\"type\" rowspan=\""+ paths.size()+"\"><a href=\"latest/"+ objClass.getSimpleName().toLowerCase()+"\">"+objClass.getSimpleName()+"</a></td>");
-                writer.println("<td class=\"path\">" + paths.get(0) + "</td>");
-                writer.println("<td class=\"description\" rowspan=\""+ paths.size()+"\">"+
+                writer.println("<td class=\"type\"><a href=\"latest/"+ objClass.getSimpleName().toLowerCase()+"\">"+objClass.getSimpleName()+"</a></td>");
+                writer.println("<td class=\"path\">" + path + "</td>");
+                writer.println("<td class=\"description\">"+
                                objClass.getAnnotation(ManagedObject.class).description()+"</td>");
                 writer.println("</tr>");
-                for(int i = 1; i < paths.size(); i++)
-                {
-                    writer.println("<tr>");
-                    writer.println("<td class=\"path\">" + paths.get(i) + "</td>");
-                    writer.println("</tr>");
-                }
-
             }
             writer.println("</tbody>");
             writer.println("</table>");
@@ -134,12 +145,13 @@ public class ApiDocsServlet extends Abst
         }
         else
         {
-            writeCategoryDescription(writer);
-            writeUsage(writer, request);
-            writeTypes(writer);
-            writeAttributes(writer);
-            writeOperations(writer);
-            writeContext(writer);
+            final List<Class<? extends ConfiguredObject>> types = _typeSpecialisations.get(configuredClass);
+            writeCategoryDescription(writer, hierarchy, configuredClass);
+            writeUsage(writer, request, hierarchy, configuredClass);
+            writeTypes(writer, model, types);
+            writeAttributes(writer, configuredClass, model, types);
+            writeOperations(writer, configuredClass, model, types);
+            writeContext(writer, configuredClass, model, types);
         }
 
         writeFoot(writer);
@@ -154,38 +166,47 @@ public class ApiDocsServlet extends Abst
 
     }
 
-    private void writeHead(final PrintWriter writer)
+    private void writeHead(final PrintWriter writer,
+                           final Class<? extends ConfiguredObject>[] hierarchy,
+                           final Class<? extends ConfiguredObject> configuredClass)
     {
         writer.println("<head>");
         writer.println("<link rel=\"icon\" type=\"image/png\" href=\"/images/qpid-favicon.png\">");
         writer.println("<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/apidocs.css\">");
-        writeTitle(writer);
+        writeTitle(writer, hierarchy, configuredClass);
 
         writer.println("</head>");
         writer.println("<body>");
     }
 
-    private void writeTitle(final PrintWriter writer)
+    private void writeTitle(final PrintWriter writer,
+                            final Class<? extends ConfiguredObject>[] hierarchy,
+                            final Class<? extends ConfiguredObject> configuredClass)
     {
         writer.print("<title>");
-        if(_hierarchy == null)
+        if(hierarchy == null)
         {
             writer.print("Qpid API");
         }
         else
         {
-            writer.print("Qpid API: " + getConfiguredClass().getSimpleName());
+            writer.print("Qpid API: " + configuredClass.getSimpleName());
         }
         writer.println("</title>");
     }
 
-    private void writeCategoryDescription(PrintWriter writer)
-    {
-        writer.println("<h1>"+getConfiguredClass().getSimpleName()+"</h1>");
-        writer.println(getConfiguredClass().getAnnotation(ManagedObject.class).description());
+    private void writeCategoryDescription(PrintWriter writer,
+                                          final Class<? extends ConfiguredObject>[] hierarchy,
+                                          final Class<? extends ConfiguredObject> configuredClass)
+    {
+        writer.println("<h1>"+configuredClass.getSimpleName()+"</h1>");
+        writer.println(configuredClass.getAnnotation(ManagedObject.class).description());
     }
 
-    private void writeUsage(final PrintWriter writer, final HttpServletRequest request)
+    private void writeUsage(final PrintWriter writer,
+                            final HttpServletRequest request,
+                            final Class<? extends ConfiguredObject>[] hierarchy,
+                            final Class<? extends ConfiguredObject> configuredClass)
     {
         writer.println("<a name=\"usage\"><h2>Usage</h2></a>");
         writer.println("<table class=\"usage\">");
@@ -193,11 +214,11 @@ public class ApiDocsServlet extends Abst
         writer.print("<tr><th class=\"operation\">Read</th><td class=\"method\">GET</td><td class=\"path\">" + request.getServletPath()
                 .replace("apidocs", "api"));
 
-        for (final Class<? extends ConfiguredObject> category : _hierarchy)
+        for (final Class<? extends ConfiguredObject> category : hierarchy)
         {
             writer.print("[/&lt;" + category.getSimpleName().toLowerCase() + " name or id&gt;");
         }
-        for(int i = 0; i < _hierarchy.length; i++)
+        for(int i = 0; i < hierarchy.length; i++)
         {
             writer.print("] ");
         }
@@ -205,7 +226,7 @@ public class ApiDocsServlet extends Abst
 
         writer.print("<tr><th class=\"operation\">Update</th><td class=\"method\">PUT or POST</td><td class=\"path\">"
                      + request.getServletPath().replace("apidocs", "api"));
-        for (final Class<? extends ConfiguredObject> category : _hierarchy)
+        for (final Class<? extends ConfiguredObject> category : hierarchy)
         {
             writer.print("/&lt;" + category.getSimpleName().toLowerCase() + " name or id&gt;");
         }
@@ -213,14 +234,14 @@ public class ApiDocsServlet extends Abst
         writer.print(
                 "<tr><th class=\"operation\">Create</th><td class=\"method\">PUT or POST</td><td class=\"path\">"
                 + request.getServletPath().replace("apidocs", "api"));
-        for (int i = 0; i < _hierarchy.length - 1; i++)
+        for (int i = 0; i < hierarchy.length - 1; i++)
         {
-            writer.print("/&lt;" + _hierarchy[i].getSimpleName().toLowerCase() + " name or id&gt;");
+            writer.print("/&lt;" + hierarchy[i].getSimpleName().toLowerCase() + " name or id&gt;");
         }
 
         writer.print("<tr><th class=\"operation\">Delete</th><td class=\"method\">DELETE</td><td class=\"path\">"
                      + request.getServletPath().replace("apidocs", "api"));
-        for (final Class<? extends ConfiguredObject> category : _hierarchy)
+        for (final Class<? extends ConfiguredObject> category : hierarchy)
         {
             writer.print("/&lt;" + category.getSimpleName().toLowerCase() + " name or id&gt;");
         }
@@ -231,9 +252,11 @@ public class ApiDocsServlet extends Abst
     }
 
 
-    private void writeTypes(final PrintWriter writer)
+    private void writeTypes(final PrintWriter writer,
+                            final Model model,
+                            final List<Class<? extends ConfiguredObject>> types)
     {
-        if(!_types.isEmpty() && !(_types.size() == 1 && getTypeName(_types.iterator().next()).trim().equals("")))
+        if(!types.isEmpty() && !(types.size() == 1 && getTypeName(types.iterator().next(), model).trim().equals("")))
         {
             writer.println("<a name=\"types\"><h2>Types</h2></a>");
             writer.println("<table class=\"types\">");
@@ -242,10 +265,10 @@ public class ApiDocsServlet extends Abst
             writer.println("</thead>");
 
             writer.println("<tbody>");
-            for (Class<? extends ConfiguredObject> type : _types)
+            for (Class<? extends ConfiguredObject> type : types)
             {
                 writer.print("<tr><td class=\"type\">");
-                writer.print(getTypeName(type));
+                writer.print(getTypeName(type, model));
                 writer.print("</td><td class=\"description\">");
                 writer.print(type.getAnnotation(ManagedObject.class).description());
                 writer.println("</td></tr>");
@@ -257,25 +280,27 @@ public class ApiDocsServlet extends Abst
         writer.println("</table>");
     }
 
-    private String getTypeName(final Class<? extends ConfiguredObject> type)
+    private String getTypeName(final Class<? extends ConfiguredObject> type, Model model)
     {
         return type.getAnnotation(ManagedObject.class).type() == null
-                            ? _model.getTypeRegistry().getTypeClass(type).getSimpleName()
+                            ? model.getTypeRegistry().getTypeClass(type).getSimpleName()
                             : type.getAnnotation(ManagedObject.class).type();
     }
 
-    private void writeAttributes(final PrintWriter writer)
+    private void writeAttributes(final PrintWriter writer,
+                                 final Class<? extends ConfiguredObject> configuredClass, final Model model,
+                                 final List<Class<? extends ConfiguredObject>> types)
     {
         writer.println("<a name=\"types\"><h2>Attributes</h2></a>");
         writer.println("<h2>Common Attributes</h2>");
 
-        writeAttributesTable(writer, _model.getTypeRegistry().getAttributeTypes(getConfiguredClass()).values());
+        writeAttributesTable(writer, model.getTypeRegistry().getAttributeTypes(configuredClass).values());
 
-        for(Class<? extends ConfiguredObject> type : _types)
+        for(Class<? extends ConfiguredObject> type : types)
         {
-            String typeName = getTypeName(type);
+            String typeName = getTypeName(type, model);
             Collection<ConfiguredObjectAttribute<?, ?>> typeSpecificAttributes =
-                    _model.getTypeRegistry().getTypeSpecificAttributes(type);
+                    model.getTypeRegistry().getTypeSpecificAttributes(type);
             if(!typeSpecificAttributes.isEmpty())
             {
                 writer.println("<h2><span class=\"type\">"+typeName+"</span> Specific Attributes</h2>");
@@ -331,21 +356,23 @@ public class ApiDocsServlet extends Abst
 
     }
 
-    private void writeOperations(final PrintWriter writer)
+    private void writeOperations(final PrintWriter writer,
+                                 final Class<? extends ConfiguredObject> configuredClass, final Model model,
+                                 final List<Class<? extends ConfiguredObject>> types)
     {
         writer.println("<a name=\"types\"><h2>Operations</h2></a>");
         writer.println("<h2>Common Operations</h2>");
 
         Collection<ConfiguredObjectOperation<?>> categoryOperations =
-                _model.getTypeRegistry().getOperations(getConfiguredClass()).values();
+                model.getTypeRegistry().getOperations(configuredClass).values();
         writeOperationsTables(writer, categoryOperations);
-        for(Class<? extends ConfiguredObject> type : _types)
+        for(Class<? extends ConfiguredObject> type : types)
         {
-            String typeName = getTypeName(type);
-            Set<ConfiguredObjectOperation<?>> typeSpecificOperations = new HashSet<>(_model.getTypeRegistry().getOperations(type).values());
+            String typeName = getTypeName(type, model);
+            Set<ConfiguredObjectOperation<?>> typeSpecificOperations = new HashSet<>(model.getTypeRegistry().getOperations(type).values());
             typeSpecificOperations.removeAll(categoryOperations);
 
-            if(!typeSpecificOperations.isEmpty() && type != getConfiguredClass())
+            if(!typeSpecificOperations.isEmpty() && type != configuredClass)
             {
                 writer.println("<h2><span class=\"type\">"+typeName+"</span> Specific Operations</h2>");
                 writeOperationsTables(writer, typeSpecificOperations);
@@ -510,20 +537,22 @@ public class ApiDocsServlet extends Abst
                 operation.getGenericReturnType().toString();
     }
 
-    private void writeContext(final PrintWriter writer)
+    private void writeContext(final PrintWriter writer,
+                              final Class<? extends ConfiguredObject> configuredClass,
+                              final Model model, final List<Class<? extends ConfiguredObject>> types)
     {
         writer.println("<a name=\"types\"><h2>Context Variables</h2></a>");
         writer.println("<h2>Common Context Variables</h2>");
 
         Collection<ManagedContextDefault> defaultContexts =
-                _model.getTypeRegistry().getContextDependencies(getConfiguredClass());
+                model.getTypeRegistry().getContextDependencies(configuredClass);
         writeContextDefaults(writer, defaultContexts);
-        for(Class<? extends ConfiguredObject> type : _types)
+        for(Class<? extends ConfiguredObject> type : types)
         {
-            String typeName = getTypeName(type);
-            Collection<ManagedContextDefault> typeSpecificDefaults = _model.getTypeRegistry().getTypeSpecificContextDependencies(type);
+            String typeName = getTypeName(type, model);
+            Collection<ManagedContextDefault> typeSpecificDefaults = model.getTypeRegistry().getTypeSpecificContextDependencies(type);
 
-            if(!typeSpecificDefaults.isEmpty() && type != getConfiguredClass())
+            if(!typeSpecificDefaults.isEmpty() && type != configuredClass)
             {
                 writer.println("<h2><span class=\"type\">"+typeName+"</span> Specific Context Variables</h2>");
                 writeContextDefaults(writer, typeSpecificDefaults);
@@ -561,8 +590,19 @@ public class ApiDocsServlet extends Abst
         writer.println("</body>");
         writer.println("</html>");
     }
-    private Class<? extends ConfiguredObject> getConfiguredClass()
+
+    private Class<? extends ConfiguredObject> getConfiguredClass(HttpServletRequest request, ConfiguredObject<?> managedObject)
     {
-        return _hierarchy.length == 0 ? Broker.class : _hierarchy[_hierarchy.length-1];
+        final String[] servletPathElements = request.getServletPath().split("/");
+        String categoryName = servletPathElements[servletPathElements.length-1];
+        Model model = managedObject.getModel();
+        for(Class<? extends ConfiguredObject> category : model.getSupportedCategories())
+        {
+            if(category.getSimpleName().toLowerCase().equals(categoryName))
+            {
+                return category;
+            }
+        }
+        return null;
     }
 }

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java Sat Dec  3 22:11:17 2016
@@ -37,9 +37,9 @@ public class BrokerQueryServlet extends
 {
     private static final long serialVersionUID = 1L;
 
-    protected Broker<?> getParent(final HttpServletRequest request)
+    protected Broker<?> getParent(final HttpServletRequest request, final ConfiguredObject<?> managedObject)
     {
-        return HttpManagementUtil.getBroker(request.getServletContext());
+        return managedObject instanceof Broker ? HttpManagementUtil.getBroker(request.getServletContext()) : null;
     }
 
 
@@ -59,7 +59,7 @@ public class BrokerQueryServlet extends
         return category;
     }
 
-    protected String getRequestedCategory(final HttpServletRequest request)
+    protected String getRequestedCategory(final HttpServletRequest request, final ConfiguredObject<?> managedObject)
     {
         List<String> pathInfoElements =
                 HttpManagementUtil.getPathInfoElements(request.getServletPath(), request.getPathInfo());

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/JsonValueServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/JsonValueServlet.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/JsonValueServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/JsonValueServlet.java Sat Dec  3 22:11:17 2016
@@ -25,6 +25,8 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.qpid.server.model.ConfiguredObject;
+
 public class JsonValueServlet extends AbstractServlet
 {
     private static final long serialVersionUID = 1L;
@@ -37,7 +39,9 @@ public class JsonValueServlet extends Ab
     }
 
     @Override
-    protected void doGetWithSubjectAndActor(final HttpServletRequest request, final HttpServletResponse resp)
+    protected void doGetWithSubjectAndActor(final HttpServletRequest request,
+                                            final HttpServletResponse resp,
+                                            final ConfiguredObject<?> managedObject)
             throws ServletException, IOException
     {
         sendJsonResponse(_value, request, resp);

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java Sat Dec  3 22:11:17 2016
@@ -31,6 +31,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -41,6 +43,7 @@ import com.fasterxml.jackson.databind.Se
 
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.ConfiguredObjectAttribute;
+import org.apache.qpid.server.model.ConfiguredObjectFinder;
 import org.apache.qpid.server.model.ConfiguredObjectOperation;
 import org.apache.qpid.server.model.ConfiguredObjectStatistic;
 import org.apache.qpid.server.model.ConfiguredObjectTypeRegistry;
@@ -54,11 +57,9 @@ public class MetaDataServlet extends Abs
 {
     private static final long serialVersionUID = 1L;
 
-    private Model _instance;
 
-    public MetaDataServlet(final Model model)
+    public MetaDataServlet()
     {
-        _instance = model;
     }
 
     @Override
@@ -68,18 +69,22 @@ public class MetaDataServlet extends Abs
     }
 
     @Override
-    protected void doGetWithSubjectAndActor(final HttpServletRequest request, final HttpServletResponse response)
+    protected void doGetWithSubjectAndActor(final HttpServletRequest request,
+                                            final HttpServletResponse response,
+                                            final ConfiguredObject<?> managedObject)
             throws ServletException, IOException
     {
         response.setContentType("application/json");
         sendCachingHeadersOnResponse(response);
         response.setStatus(HttpServletResponse.SC_OK);
+        ConfiguredObjectFinder finder = getConfiguredObjectFinder(managedObject);
+
 
         Map<String, Map> classToDataMap = new TreeMap<>();
 
-        for (Class<? extends ConfiguredObject> clazz : _instance.getSupportedCategories())
+        for (Class<? extends ConfiguredObject> clazz : finder.getManagedCategories())
         {
-            classToDataMap.put(clazz.getSimpleName(), processCategory(clazz));
+            classToDataMap.put(clazz.getSimpleName(), processCategory(clazz, managedObject.getModel()));
         }
 
         final OutputStream stream = getOutputStream(request, response);
@@ -92,27 +97,27 @@ public class MetaDataServlet extends Abs
 
     }
 
-    private Map<String, Map> processCategory(final Class<? extends ConfiguredObject> clazz)
+    private Map<String, Map> processCategory(final Class<? extends ConfiguredObject> clazz, final Model model)
     {
         Map<String, Map> typeToDataMap = new TreeMap<>();
-        ConfiguredObjectTypeRegistry typeRegistry = _instance.getTypeRegistry();
+        ConfiguredObjectTypeRegistry typeRegistry = model.getTypeRegistry();
         for (Class<? extends ConfiguredObject> type : typeRegistry.getTypeSpecialisations(clazz))
         {
-            typeToDataMap.put(ConfiguredObjectTypeRegistry.getType(type), processType(type));
+            typeToDataMap.put(ConfiguredObjectTypeRegistry.getType(type), processType(type, model));
         }
         return typeToDataMap;
     }
 
-    private Map<String, Object> processType(final Class<? extends ConfiguredObject> type)
+    private Map<String, Object> processType(final Class<? extends ConfiguredObject> type, final Model model)
     {
         Map<String, Object> typeDetails = new LinkedHashMap<>();
-        typeDetails.put("attributes", processAttributes(type));
-        typeDetails.put("statistics", processStatistics(type));
+        typeDetails.put("attributes", processAttributes(type, model));
+        typeDetails.put("statistics", processStatistics(type, model));
 
-        typeDetails.put("operations", processOperations(type));
-        typeDetails.put("managedInterfaces", getManagedInterfaces(type));
-        typeDetails.put("validChildTypes", getValidChildTypes(type));
-        typeDetails.put("contextDependencies", getContextDependencies(type));
+        typeDetails.put("operations", processOperations(type, model));
+        typeDetails.put("managedInterfaces", getManagedInterfaces(type, model));
+        typeDetails.put("validChildTypes", getValidChildTypes(type, model));
+        typeDetails.put("contextDependencies", getContextDependencies(type, model));
         ManagedObject annotation = type.getAnnotation(ManagedObject.class);
         if (annotation != null)
         {
@@ -128,10 +133,10 @@ public class MetaDataServlet extends Abs
         return typeDetails;
     }
 
-    private Map<String, String> getContextDependencies(final Class<? extends ConfiguredObject> type)
+    private Map<String, String> getContextDependencies(final Class<? extends ConfiguredObject> type, final Model model)
     {
         final Collection<ManagedContextDefault> contextDependencies =
-                _instance.getTypeRegistry().getContextDependencies(type);
+                model.getTypeRegistry().getContextDependencies(type);
         Map<String,String> result = new TreeMap<>();
 
         if(contextDependencies != null)
@@ -144,13 +149,14 @@ public class MetaDataServlet extends Abs
         return result;
     }
 
-    private Map<String, Collection<String>> getValidChildTypes(final Class<? extends ConfiguredObject> type)
+    private Map<String, Collection<String>> getValidChildTypes(final Class<? extends ConfiguredObject> type,
+                                                               final Model model)
     {
         Map<String, Collection<String>> validChildTypes = new HashMap<>();
-        for (Class<? extends ConfiguredObject> childType : _instance.getChildTypes(ConfiguredObjectTypeRegistry.getCategory(
+        for (Class<? extends ConfiguredObject> childType : model.getChildTypes(ConfiguredObjectTypeRegistry.getCategory(
                 type)))
         {
-            Collection<String> validValues = _instance.getTypeRegistry().getValidChildTypes(type, childType);
+            Collection<String> validValues = model.getTypeRegistry().getValidChildTypes(type, childType);
             if (validValues != null)
             {
                 validChildTypes.put(childType.getSimpleName(), validValues);
@@ -159,20 +165,20 @@ public class MetaDataServlet extends Abs
         return validChildTypes;
     }
 
-    private Set<String> getManagedInterfaces(Class<? extends ConfiguredObject> type)
+    private Set<String> getManagedInterfaces(Class<? extends ConfiguredObject> type, final Model model)
     {
         Set<String> interfaces = new HashSet<>();
-        for (Class<?> classObject : _instance.getTypeRegistry().getManagedInterfaces(type))
+        for (Class<?> classObject : model.getTypeRegistry().getManagedInterfaces(type))
         {
             interfaces.add(classObject.getSimpleName());
         }
         return interfaces;
     }
 
-    private Map<String, Map> processAttributes(final Class<? extends ConfiguredObject> type)
+    private Map<String, Map> processAttributes(final Class<? extends ConfiguredObject> type, final Model model)
     {
         Collection<ConfiguredObjectAttribute<?, ?>> attributes =
-                _instance.getTypeRegistry().getAttributeTypes(type).values();
+                model.getTypeRegistry().getAttributeTypes(type).values();
 
         Map<String, Map> attributeDetails = new LinkedHashMap<>();
         for (ConfiguredObjectAttribute<?, ?> attribute : attributes)
@@ -232,10 +238,10 @@ public class MetaDataServlet extends Abs
         return attributeDetails;
     }
 
-    private Map<String, Map> processOperations(final Class<? extends ConfiguredObject> type)
+    private Map<String, Map> processOperations(final Class<? extends ConfiguredObject> type, final Model model)
     {
         Collection<ConfiguredObjectOperation<?>> operations =
-                _instance.getTypeRegistry().getOperations(type).values();
+                model.getTypeRegistry().getOperations(type).values();
 
         Map<String, Map> attributeDetails = new LinkedHashMap<>();
         for (ConfiguredObjectOperation<?> operation : operations)
@@ -273,10 +279,10 @@ public class MetaDataServlet extends Abs
     }
 
 
-    private Map<String, Map> processStatistics(final Class<? extends ConfiguredObject> type)
+    private Map<String, Map> processStatistics(final Class<? extends ConfiguredObject> type, final Model model)
     {
         Collection<ConfiguredObjectStatistic> statistics =
-                _instance.getTypeRegistry().getStatistics(type);
+                model.getTypeRegistry().getStatistics(type);
 
         Map<String, Map> allStatisticsDetails = new LinkedHashMap<>();
         for (ConfiguredObjectStatistic<?, ?> statistic : statistics)

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java Sat Dec  3 22:11:17 2016
@@ -44,26 +44,32 @@ public abstract class QueryServlet<X ext
 
 
     @Override
-    protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response)
+    protected void doGetWithSubjectAndActor(HttpServletRequest request,
+                                            HttpServletResponse response,
+                                            final ConfiguredObject<?> managedObject)
             throws IOException, ServletException
     {
-        performQuery(request, response);
+        performQuery(request, response, managedObject);
     }
 
 
     @Override
-    protected void doPostWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response)
+    protected void doPostWithSubjectAndActor(HttpServletRequest request,
+                                             HttpServletResponse response,
+                                             final ConfiguredObject<?> managedObject)
             throws IOException, ServletException
     {
-        performQuery(request, response);
+        performQuery(request, response, managedObject);
     }
 
-    private void performQuery(final HttpServletRequest request, final HttpServletResponse response)
+    private void performQuery(final HttpServletRequest request,
+                              final HttpServletResponse response,
+                              final ConfiguredObject<?> managedObject)
             throws IOException, ServletException
     {
         String categoryName;
-        X parent = getParent(request);
-        if (parent != null && ((categoryName = getRequestedCategory(request)) != null))
+        X parent = getParent(request, managedObject);
+        if (parent != null && ((categoryName = getRequestedCategory(request, managedObject)) != null))
         {
             Model model = parent.getModel();
 
@@ -119,12 +125,13 @@ public abstract class QueryServlet<X ext
 
     }
 
-    abstract protected X getParent(final HttpServletRequest request);
+    abstract protected X getParent(final HttpServletRequest request, final ConfiguredObject<?> managedObject);
 
     abstract protected Class<? extends ConfiguredObject> getSupportedCategory(final String categoryName,
                                                                    final Model brokerModel);
 
-    abstract protected String getRequestedCategory(final HttpServletRequest request);
+    abstract protected String getRequestedCategory(final HttpServletRequest request,
+                                                   final ConfiguredObject<?> managedObject);
 
     abstract protected List<ConfiguredObject<?>> getAllObjects(final X parent,
                                                                final Class<? extends ConfiguredObject> category,

Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java?rev=1772491&r1=1772490&r2=1772491&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java Sat Dec  3 22:11:17 2016
@@ -29,6 +29,8 @@ import javax.servlet.http.HttpServletRes
 
 import org.apache.qpid.server.management.plugin.HttpManagementUtil;
 import org.apache.qpid.server.management.plugin.report.ReportRunner;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.Queue;
 import org.apache.qpid.server.model.VirtualHost;
 
@@ -37,16 +39,35 @@ public class QueueReportServlet extends
     private static final long serialVersionUID = 1L;
 
     @Override
-    protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws
-                                                                                                      IOException,
-                                                                                                      ServletException
+    protected void doGetWithSubjectAndActor(HttpServletRequest request,
+                                            HttpServletResponse response,
+                                            final ConfiguredObject<?> managedObject)
+            throws IOException, ServletException
     {
         List<String> pathInfoElements =
                 HttpManagementUtil.getPathInfoElements(request.getServletPath(), request.getPathInfo());
-        if (pathInfoElements.size() == 3)
+        Queue<?> queue;
+        String reportName;
+        if (managedObject instanceof Broker && pathInfoElements.size() == 3)
         {
-            Queue<?> queue = getQueueFromRequest(pathInfoElements);
-            ReportRunner<?> reportRunner = ReportRunner.createRunner(pathInfoElements.get(2),request.getParameterMap());
+            queue = getQueueFromRequest(pathInfoElements);
+            reportName = pathInfoElements.get(2);
+
+        }
+        else if(managedObject instanceof VirtualHost && pathInfoElements.size() == 2)
+        {
+            queue = getQueueFromVirtualHost(pathInfoElements.get(0), (VirtualHost<?>)managedObject);
+            reportName = pathInfoElements.get(1);
+        }
+        else
+        {
+            queue = null;
+            reportName = null;
+        }
+
+        if(queue != null)
+        {
+            ReportRunner<?> reportRunner = ReportRunner.createRunner(reportName,request.getParameterMap());
             Object output = reportRunner.runReport(queue);
             response.setContentType(reportRunner.getContentType());
             if(reportRunner.isBinaryReport())



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org