You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2018/12/18 18:23:54 UTC
[qpid-broker-j] 02/03: QPID-6948: [Broker-J] Introduce base classes
for implementation of legacy management REST API and add 7.0 REST API
support
This is an automated email from the ASF dual-hosted git repository.
orudyy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git
commit 359b9a3fc513062aed2ef0e74edd7321e43eb76b
Author: Alex Rudyy <or...@apache.org>
AuthorDate: Tue Dec 18 17:19:59 2018 +0000
QPID-6948: [Broker-J] Introduce base classes for implementation of legacy management REST API and add 7.0 REST API support
---
.../AbstractLegacyConfiguredObjectController.java | 560 +++++++++++++++++++++
.../plugin/controller/CategoryController.java | 78 +++
.../controller/CategoryControllerFactory.java | 48 ++
.../controller/ControllerManagementResponse.java | 82 +++
.../controller/GenericCategoryController.java | 266 ++++++++++
.../controller/GenericLegacyConfiguredObject.java | 195 +++++++
.../plugin/controller/LegacyConfiguredObject.java | 90 ++++
.../LegacyConfiguredObjectToMapConverter.java | 251 +++++++++
.../controller/LegacyManagementController.java | 44 ++
.../plugin/controller/TypeController.java | 39 ++
.../plugin/controller/TypeControllerFactory.java | 51 ++
.../latest/LatestManagementControllerAdapter.java | 489 ++++++++++++++++++
.../v7_0/LegacyManagementController.java | 80 +++
.../v7_0/LegacyManagementControllerFactory.java | 62 +++
.../v7_0/category/ContainerController.java | 80 +++
.../v7_0/category/LegacyCategoryController.java | 63 +++
.../category/LegacyCategoryControllerFactory.java | 154 ++++++
...stractLegacyConfiguredObjectControllerTest.java | 292 +++++++++++
.../controller/GenericCategoryControllerTest.java | 247 +++++++++
.../GenericLegacyConfiguredObjectTest.java | 212 ++++++++
.../LatestManagementControllerAdapterTest.java | 395 +++++++++++++++
.../v7_0/LegacyManagementControllerTest.java | 105 ++++
.../v7_0/category/ContainerControllerTest.java | 83 +++
.../LegacyCategoryControllerFactoryTest.java | 58 +++
24 files changed, 4024 insertions(+)
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/AbstractLegacyConfiguredObjectController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/AbstractLegacyConfiguredObjectController.java
new file mode 100644
index 0000000..131beb8
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/AbstractLegacyConfiguredObjectController.java
@@ -0,0 +1,560 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import static org.apache.qpid.server.management.plugin.ManagementException.createBadRequestManagementException;
+import static org.apache.qpid.server.management.plugin.ManagementException.createInternalServerErrorManagementException;
+import static org.apache.qpid.server.management.plugin.ManagementException.createNotFoundManagementException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+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.stream.Collectors;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.management.plugin.ManagementRequest;
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.RequestType;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public abstract class AbstractLegacyConfiguredObjectController extends AbstractManagementController
+ implements LegacyManagementController
+{
+ private final ManagementController _nextVersionManagementController;
+ private final String _modelVersion;
+
+ private final Map<String, String> _categoryNames = new HashMap<>();
+ private final Map<String, List<String>> _parents = new HashMap<>();
+ private final Map<String, List<String>> _children = new HashMap<>();
+
+ private final Map<String, CategoryController> _categoryConverters = new HashMap<>();
+ private final Map<String, Set<TypeController>> _typeControllers = new HashMap<>();
+ private volatile LegacyConfiguredObjectToMapConverter _legacyConfiguredObjectToMapConverter;
+
+ public AbstractLegacyConfiguredObjectController(final String modelVersion,
+ final ManagementController nextVersionManagementController)
+ {
+ _modelVersion = modelVersion;
+ _nextVersionManagementController = nextVersionManagementController;
+ }
+
+ @Override
+ public String getVersion()
+ {
+ return _modelVersion;
+ }
+
+ @Override
+ public Collection<String> getCategories()
+ {
+ return Collections.unmodifiableCollection(_categoryNames.values());
+ }
+
+ @Override
+ public String getCategoryMapping(final String category)
+ {
+ return String.format("/api/v%s/%s/", getVersion(), category.toLowerCase());
+ }
+
+ @Override
+ public String getCategory(final ConfiguredObject<?> managedObject)
+ {
+ return _nextVersionManagementController.getCategory(managedObject);
+ }
+
+ @Override
+ public List<String> getCategoryHierarchy(final ConfiguredObject<?> root, final String categoryName)
+ {
+ return getCategoryHierarchy(getCategory(root), categoryName);
+ }
+
+ @Override
+ public ManagementController getNextVersionManagementController()
+ {
+ return _nextVersionManagementController;
+ }
+
+
+ @Override
+ public LegacyConfiguredObject createOrUpdate(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, Object> attributes,
+ final boolean isPost) throws ManagementException
+ {
+ return getCategoryController(category).createOrUpdate(root, path, attributes, isPost);
+ }
+
+
+ @Override
+ public Object get(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ return getCategoryController(category).get(root, path, convertQueryParameters(parameters));
+ }
+
+ @Override
+ public int delete(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ return getCategoryController(category).delete(root, path, convertQueryParameters(parameters));
+ }
+
+ @Override
+ public ManagementResponse invoke(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final String operation,
+ final Map<String, Object> parameters,
+ final boolean isPost,
+ final boolean isSecureOrAllowedOnInsecureChannel) throws ManagementException
+ {
+ return getCategoryController(category).invoke(root, path, operation, parameters, isPost,
+ isSecureOrAllowedOnInsecureChannel);
+ }
+
+ @Override
+ public Object getPreferences(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ return getCategoryController(category).getPreferences(root, path, convertQueryParameters(parameters));
+ }
+
+ @Override
+ public void setPreferences(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Object preferences,
+ final Map<String, List<String>> parameters,
+ final boolean isPost) throws ManagementException
+ {
+ getCategoryController(category).setPreferences(root, path, preferences, parameters, isPost);
+ }
+
+ @Override
+ public int deletePreferences(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+
+ return getCategoryController(category).deletePreferences(root, path, convertQueryParameters(parameters));
+ }
+
+ @Override
+ public CategoryController getCategoryController(final String category)
+ {
+ CategoryController converter = _categoryConverters.get(category.toLowerCase());
+ if (converter == null)
+ {
+ throw createInternalServerErrorManagementException(String.format("Converter for type '%s' cannot be found ",
+ category));
+ }
+ return converter;
+ }
+
+ @Override
+ public Set<TypeController> getTypeControllersByCategory(final String name)
+ {
+ Set<TypeController> typeControllers = _typeControllers.get(name.toLowerCase());
+ if (typeControllers == null)
+ {
+ return Collections.emptySet();
+ }
+ return Collections.unmodifiableSet(typeControllers);
+ }
+
+ @Override
+ public List<String> getCategoryHierarchy(final String rootCategory,
+ final String categoryName)
+ {
+ if (!_categoryNames.containsKey(rootCategory.toLowerCase()))
+ {
+ throw createInternalServerErrorManagementException(String.format("Unsupported root category '%s'",
+ rootCategory));
+ }
+ if (!_categoryNames.containsKey(categoryName.toLowerCase()))
+ {
+ throw createInternalServerErrorManagementException(String.format("Unsupported category '%s'",
+ categoryName));
+ }
+ final List<String> hierarchyList = new ArrayList<>();
+
+ String category = _categoryNames.get(categoryName.toLowerCase());
+ if (!category.equals(rootCategory))
+ {
+ Collection<String> parentCategories;
+
+ hierarchyList.add(category);
+
+ while (!(parentCategories = _parents.get(category)).contains(rootCategory))
+ {
+ hierarchyList.addAll(parentCategories);
+ category = parentCategories.iterator().next();
+ }
+
+ Collections.reverse(hierarchyList);
+ }
+ return Collections.unmodifiableList(hierarchyList);
+ }
+
+ @Override
+ public Collection<String> getChildrenCategories(String category)
+ {
+ List<String> children = _children.get(_categoryNames.get(category.toLowerCase()));
+ if (children == null)
+ {
+ return Collections.emptyList();
+ }
+ return Collections.unmodifiableList(children);
+ }
+
+ @Override
+ public Collection<String> getParentTypes(final String category)
+ {
+ return _parents.get(category);
+ }
+
+ public void initialize()
+ {
+ initialize(CategoryControllerFactory.findFactories(getVersion()),
+ TypeControllerFactory.findFactories(getVersion()));
+ }
+
+ protected void initialize(final Set<CategoryControllerFactory> categoryFactories,
+ final Set<TypeControllerFactory> typeFactories)
+ {
+ createTypeControllers(typeFactories);
+ createCategoryControllers(categoryFactories);
+ _legacyConfiguredObjectToMapConverter = new LegacyConfiguredObjectToMapConverter(this);
+ }
+
+
+ @Override
+ protected RequestType getRequestType(final ManagementRequest managementRequest) throws ManagementException
+ {
+ final List<String> path = managementRequest.getPath();
+ final String category = managementRequest.getCategory();
+ if (category == null)
+ {
+ throw createNotFoundManagementException(String.format("Category is not found for path '%s%s'",
+ getCategoryMapping(category),
+ buildPath(path)));
+ }
+
+ final List<String> hierarchy = getCategoryHierarchy(managementRequest.getRoot(), category);
+ return getManagementRequestType(managementRequest.getMethod(), category, path, hierarchy);
+ }
+
+ @Override
+ public LegacyConfiguredObject convertFromNextVersion(final LegacyConfiguredObject nextVersionObject)
+ {
+ return getCategoryController(nextVersionObject.getCategory()).convertFromNextVersion(nextVersionObject);
+ }
+
+ protected abstract Map<String, List<String>> convertQueryParameters(final Map<String, List<String>> parameters);
+
+ private void addRelationship(String parentCategory, String childCategory)
+ {
+ Collection<String> parents = _parents.computeIfAbsent(childCategory, k -> new ArrayList<>());
+ parents.add(parentCategory);
+
+ Collection<String> children = _children.computeIfAbsent(parentCategory, k -> new ArrayList<>());
+ children.add(childCategory);
+
+ _categoryNames.put(childCategory.toLowerCase(), childCategory);
+ }
+
+
+ private void createCategoryControllers(final Set<CategoryControllerFactory> factories)
+ {
+ factories.stream()
+ .map(this::create)
+ .flatMap(Collection::stream)
+ .peek(this::register)
+ .forEach(c -> {
+ if (_categoryConverters.put(c.getCategory().toLowerCase(), c) != null)
+ {
+ throw new IllegalStateException(String.format(
+ "Category converter for category '%s' is already registered",
+ c.getCategory()));
+ }
+ });
+ }
+
+ private Set<CategoryController> create(final CategoryControllerFactory factory)
+ {
+ return factory.getSupportedCategories()
+ .stream()
+ .map(type -> factory.createController(type, this))
+ .collect(Collectors.toSet());
+ }
+
+ private void register(final CategoryController converter)
+ {
+ String type = converter.getCategory();
+ for (String category : converter.getParentCategories())
+ {
+ addRelationship(category, type);
+ }
+ _categoryNames.put(type.toLowerCase(), type);
+ }
+
+ private void createTypeControllers(Set<TypeControllerFactory> typeFactories)
+ {
+ for (TypeControllerFactory factory : typeFactories)
+ {
+ TypeController controller = factory.createController(this);
+ Set<TypeController> categoryTypeConverters =
+ _typeControllers.computeIfAbsent(factory.getCategory().toLowerCase(), k -> new HashSet<>());
+
+ categoryTypeConverters.add(controller);
+ }
+ }
+
+ protected LegacyConfiguredObjectToMapConverter getLegacyConfiguredObjectToMapConverter()
+ {
+ return _legacyConfiguredObjectToMapConverter;
+ }
+
+
+ private RequestType getManagementRequestType(final String method,
+ final String category,
+ final List<String> parts,
+ final List<String> hierarchy)
+ {
+ if ("POST".equals(method))
+ {
+ return getPostRequestType(category, parts, hierarchy);
+ }
+ else if ("PUT".equals(method))
+ {
+ return getPutRequestType(category, parts, hierarchy);
+ }
+ else if ("GET".equals(method))
+ {
+ return getGetRequestType(category, parts, hierarchy);
+ }
+ else if ("DELETE".equals(method))
+ {
+ return getDeleteRequestType(category, parts, hierarchy);
+ }
+ else
+ {
+ throw createBadRequestManagementException(String.format("Unexpected method type '%s' for path '%s%s'",
+ method,
+ getCategoryMapping(category),
+ buildPath(parts)));
+ }
+ }
+
+ private RequestType getDeleteRequestType(final String category,
+ final List<String> parts,
+ final List<String> hierarchy)
+ {
+ if (parts.size() <= hierarchy.size())
+ {
+ return RequestType.MODEL_OBJECT;
+ }
+ else
+ {
+ if (USER_PREFERENCES.equals(parts.get(hierarchy.size())))
+ {
+ return RequestType.USER_PREFERENCES;
+ }
+ }
+ final String categoryMapping = getCategoryMapping(category);
+ final String expectedPath = buildExpectedPath(categoryMapping, hierarchy);
+ throw createBadRequestManagementException(String.format(
+ "Invalid DELETE path '%s%s'. Expected: '%s' or '%s/userpreferences[/<preference type>[/<preference name>]]'",
+ categoryMapping,
+ buildPath(parts),
+ expectedPath,
+ expectedPath));
+ }
+
+ private RequestType getGetRequestType(final String category,
+ final List<String> parts,
+ final List<String> hierarchy)
+ {
+ if (parts.size() <= hierarchy.size())
+ {
+ return RequestType.MODEL_OBJECT;
+ }
+ else
+ {
+ if (USER_PREFERENCES.equals(parts.get(hierarchy.size())))
+ {
+ return RequestType.USER_PREFERENCES;
+ }
+ else if (VISIBLE_USER_PREFERENCES.equals(parts.get(hierarchy.size())))
+ {
+ return RequestType.VISIBLE_PREFERENCES;
+ }
+ else if (parts.size() == hierarchy.size() + 1)
+ {
+ return RequestType.OPERATION;
+ }
+ }
+
+ final String categoryMapping = getCategoryMapping(category);
+ throw createBadRequestManagementException(String.format(
+ "Invalid GET path '%s%s'. Expected: '%s[/<operation name>]'",
+ categoryMapping,
+ buildPath(parts),
+ buildExpectedPath(categoryMapping, hierarchy)));
+ }
+
+ private RequestType getPutRequestType(final String category,
+ final List<String> parts,
+ final List<String> hierarchy)
+ {
+ if (parts.size() == hierarchy.size() || parts.size() == hierarchy.size() - 1)
+ {
+ return RequestType.MODEL_OBJECT;
+ }
+ else if (parts.size() > hierarchy.size() && USER_PREFERENCES.equals(parts.get(hierarchy.size())))
+ {
+ return RequestType.USER_PREFERENCES;
+ }
+ else
+ {
+ final String categoryMapping = getCategoryMapping(category);
+ throw createBadRequestManagementException(String.format("Invalid PUT path '%s%s'. Expected: '%s'",
+ categoryMapping, buildPath(parts),
+ buildExpectedPath(categoryMapping, hierarchy)));
+ }
+ }
+
+ private RequestType getPostRequestType(final String category,
+ final List<String> parts,
+ final List<String> hierarchy)
+ {
+ if (parts.size() == hierarchy.size() || parts.size() == hierarchy.size() - 1)
+ {
+ return RequestType.MODEL_OBJECT;
+ }
+ else if (parts.size() > hierarchy.size())
+ {
+ if (USER_PREFERENCES.equals(parts.get(hierarchy.size())))
+ {
+ return RequestType.USER_PREFERENCES;
+ }
+ else if (parts.size() == hierarchy.size() + 1
+ && !VISIBLE_USER_PREFERENCES.equals(parts.get(hierarchy.size())))
+ {
+ return RequestType.OPERATION;
+ }
+ }
+
+ final String categoryMapping = getCategoryMapping(category);
+ final String expectedFullPath = buildExpectedPath(categoryMapping, hierarchy);
+ final String expectedParentPath =
+ buildExpectedPath(categoryMapping, hierarchy.subList(0, hierarchy.size() - 1));
+
+ throw createBadRequestManagementException(String.format(
+ "Invalid POST path '%s%s'. Expected: '%s/<operation name>'"
+ + " or '%s'"
+ + " or '%s/userpreferences[/<preference type>]'",
+ categoryMapping,
+ buildPath(parts),
+ expectedFullPath,
+ expectedParentPath,
+ expectedFullPath));
+ }
+
+ private String buildExpectedPath(final String servletPath, final List<String> hierarchy)
+ {
+ return hierarchy.stream()
+ .map(h -> String.format("/<%s name>", h))
+ .collect((Collectors.joining("", servletPath, "")));
+ }
+
+ private String buildPath(final List<String> path)
+ {
+ return path.isEmpty() ? "" : "/" + String.join("/", path);
+ }
+
+ protected Object formatConfiguredObject(final Object content,
+ final boolean isSecureOrAllowedOnInsecureChannel,
+ final int depth,
+ final int oversizeThreshold,
+ final boolean actuals,
+ final boolean excludeInheritedContext, final boolean responseAsList)
+ {
+ if (content instanceof LegacyConfiguredObject)
+ {
+ Object object = convertObject(
+ (LegacyConfiguredObject) content,
+ depth,
+ actuals,
+ oversizeThreshold,
+ isSecureOrAllowedOnInsecureChannel,
+ excludeInheritedContext);
+ return responseAsList ? Collections.singletonList(object) : object;
+ }
+ else if (content instanceof Collection)
+ {
+ Collection<Map<String, Object>> results = ((Collection<?>) content).stream()
+ .filter(o -> o instanceof LegacyConfiguredObject)
+ .map(LegacyConfiguredObject.class::cast)
+ .map(o -> convertObject(
+ o,
+ depth,
+ actuals,
+ oversizeThreshold,
+ isSecureOrAllowedOnInsecureChannel,
+ excludeInheritedContext))
+ .collect(Collectors.toSet());
+ if (!results.isEmpty())
+ {
+ return results;
+ }
+ }
+ return content;
+ }
+
+ protected Map<String, Object> convertObject(final LegacyConfiguredObject legacyConfiguredObjectObject,
+ final int depth,
+ final boolean actuals,
+ final int oversizeThreshold,
+ final boolean isSecureOrConfidentialOperationAllowedOnInsecureChannel,
+ final boolean excludeInheritedContext)
+ {
+ return getLegacyConfiguredObjectToMapConverter().convertManageableToMap(legacyConfiguredObjectObject,
+ depth,
+ actuals,
+ oversizeThreshold,
+ excludeInheritedContext);
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/CategoryController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/CategoryController.java
new file mode 100644
index 0000000..9e2c011
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/CategoryController.java
@@ -0,0 +1,78 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public interface CategoryController
+{
+ String getCategory();
+
+ String getNextVersionCategory();
+
+ String getDefaultType();
+
+ String[] getParentCategories();
+
+ LegacyManagementController getManagementController();
+
+ Object get(ConfiguredObject<?> root,
+ List<String> path,
+ Map<String, List<String>> parameters) throws ManagementException;
+
+ LegacyConfiguredObject createOrUpdate(ConfiguredObject<?> root,
+ List<String> path,
+ Map<String, Object> attributes,
+ boolean isPost) throws ManagementException;
+
+ int delete(ConfiguredObject<?> root,
+ List<String> path,
+ Map<String, List<String>> parameters) throws ManagementException;
+
+ ManagementResponse invoke(ConfiguredObject<?> root,
+ List<String> path,
+ String operation,
+ Map<String, Object> parameters,
+ boolean isPost,
+ final boolean isSecure) throws ManagementException;
+
+ Object getPreferences(ConfiguredObject<?> root,
+ List<String> path,
+ Map<String, List<String>> parameters) throws ManagementException;
+
+ void setPreferences(ConfiguredObject<?> root,
+ List<String> path,
+ Object preferences,
+ Map<String, List<String>> parameters,
+ boolean isPost) throws ManagementException;
+
+ int deletePreferences(ConfiguredObject<?> root,
+ List<String> path,
+ Map<String, List<String>> parameters) throws ManagementException;
+
+ LegacyConfiguredObject convertFromNextVersion(LegacyConfiguredObject nextVersionObject);
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/CategoryControllerFactory.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/CategoryControllerFactory.java
new file mode 100644
index 0000000..552b2cd
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/CategoryControllerFactory.java
@@ -0,0 +1,48 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.plugin.Pluggable;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+
+public interface CategoryControllerFactory extends Pluggable
+{
+ CategoryController createController(String type, LegacyManagementController managementController);
+
+ Set<String> getSupportedCategories();
+
+ String getModelVersion();
+
+ static Set<CategoryControllerFactory> findFactories(String version)
+ {
+ final Iterable<CategoryControllerFactory> factories =
+ new QpidServiceLoader().atLeastOneInstanceOf(CategoryControllerFactory.class);
+
+ return StreamSupport.stream(factories.spliterator(), false)
+ .filter(f -> version.equals(f.getModelVersion()))
+ .collect(Collectors.toSet());
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/ControllerManagementResponse.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/ControllerManagementResponse.java
new file mode 100644
index 0000000..ff3061f
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/ControllerManagementResponse.java
@@ -0,0 +1,82 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import java.util.Collections;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.ResponseType;
+
+public class ControllerManagementResponse implements ManagementResponse
+{
+ private final ResponseType _type;
+ private final Object _body;
+ private final int _status;
+ private final Map<String, String> _headers;
+
+ public ControllerManagementResponse(final ResponseType type, final Object body)
+ {
+ this(type, body, HttpServletResponse.SC_OK, Collections.emptyMap());
+ }
+
+ public ControllerManagementResponse(final ResponseType type,
+ final Object body,
+ final int status,
+ final Map<String, String> headers)
+ {
+ _type = type;
+ _body = body;
+ _status = status;
+ _headers = headers;
+ }
+
+ @Override
+ public ResponseType getType()
+ {
+ return _type;
+ }
+
+ @Override
+ public Object getBody()
+ {
+ return _body;
+ }
+
+ public int getStatus()
+ {
+ return _status;
+ }
+
+ @Override
+ public Map<String, String> getHeaders()
+ {
+ return _headers;
+ }
+
+ @Override
+ public int getResponseCode()
+ {
+ return _status;
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/GenericCategoryController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/GenericCategoryController.java
new file mode 100644
index 0000000..35ff45b
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/GenericCategoryController.java
@@ -0,0 +1,266 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import static org.apache.qpid.server.management.plugin.ManagementException.createBadRequestManagementException;
+import static org.apache.qpid.server.management.plugin.ManagementException.createInternalServerErrorManagementException;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public abstract class GenericCategoryController implements CategoryController
+{
+ private final String _name;
+ private final LegacyManagementController _managementController;
+ private final ManagementController _nextVersionManagementController;
+ private final String _defaultType;
+ private final Map<String, TypeController> _typeControllers;
+ private final Map<String, TypeController> _nextVersionTypeControllers;
+
+ protected GenericCategoryController(final LegacyManagementController managementController,
+ final ManagementController nextVersionManagementController,
+ final String name,
+ final String defaultType,
+ final Set<TypeController> typeControllers)
+ {
+ _name = name;
+ _managementController = managementController;
+ _nextVersionManagementController = nextVersionManagementController;
+ _defaultType = defaultType;
+ _typeControllers = typeControllers.stream().collect(Collectors.toMap(TypeController::getTypeName, c -> c));
+ _nextVersionTypeControllers =
+ typeControllers.stream().collect(Collectors.toMap(TypeController::getNextVersionTypeName, c -> c));
+ }
+
+ @Override
+ public String getCategory()
+ {
+ return _name;
+ }
+
+ @Override
+ public String getNextVersionCategory()
+ {
+ return _name;
+ }
+
+ @Override
+ public String getDefaultType()
+ {
+ return _defaultType;
+ }
+
+ @Override
+ public LegacyManagementController getManagementController()
+ {
+ return _managementController;
+ }
+
+ @Override
+ public Object get(final ConfiguredObject<?> root,
+ final List<String> path,
+ final Map<String, List<String>> parameters)
+ throws ManagementException
+ {
+ final Object content =
+ _nextVersionManagementController.get(root,
+ getNextVersionCategory(),
+ path,
+ convertQueryParametersToNextVersion(parameters));
+ return convert(content);
+ }
+
+ @Override
+ public LegacyConfiguredObject createOrUpdate(ConfiguredObject<?> root,
+ List<String> path,
+ Map<String, Object> attributes,
+ boolean isPost) throws ManagementException
+ {
+ final Map<String, Object> body = convertAttributesToNextVersion(root, path, attributes);
+ final Object configuredObject =
+ _nextVersionManagementController.createOrUpdate(root, getNextVersionCategory(), path, body, isPost);
+ if (configuredObject instanceof LegacyConfiguredObject)
+ {
+ LegacyConfiguredObject object = (LegacyConfiguredObject) configuredObject;
+ return convertFromNextVersion(object);
+ }
+ return null;
+ }
+
+ @Override
+ public LegacyConfiguredObject convertFromNextVersion(final LegacyConfiguredObject object)
+ {
+ TypeController controller = getTypeController(object);
+ if (controller != null)
+ {
+ return controller.convertFromNextVersion(object);
+ }
+ return convertNextVersionLegacyConfiguredObject(object);
+ }
+
+ @Override
+ public int delete(final ConfiguredObject<?> root,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ return _nextVersionManagementController.delete(root,
+ getNextVersionCategory(),
+ path,
+ convertQueryParametersToNextVersion(parameters));
+ }
+
+ @Override
+ public ManagementResponse invoke(final ConfiguredObject<?> root,
+ final List<String> path,
+ final String operation,
+ final Map<String, Object> parameters,
+ final boolean isPost,
+ final boolean isSecure) throws ManagementException
+ {
+
+ Object result = get(root, path, Collections.emptyMap());
+ if (result instanceof LegacyConfiguredObject)
+ {
+ final LegacyConfiguredObject legacyConfiguredObject = (LegacyConfiguredObject) result;
+ return legacyConfiguredObject.invoke(operation, parameters, isSecure);
+ }
+ else
+ {
+ throw createBadRequestManagementException(String.format("Configured object %s/%s is not found",
+ getManagementController().getCategoryMapping(
+ getCategory()),
+ String.join("/", path)));
+ }
+ }
+
+ @Override
+ public Object getPreferences(final ConfiguredObject<?> root,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ return _nextVersionManagementController.getPreferences(root,
+ getNextVersionCategory(),
+ path,
+ parameters);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void setPreferences(final ConfiguredObject<?> root,
+ final List<String> path,
+ final Object preferences,
+ final Map<String, List<String>> parameters,
+ final boolean isPost) throws ManagementException
+ {
+ _nextVersionManagementController.setPreferences(root,
+ getNextVersionCategory(),
+ path,
+ preferences,
+ parameters,
+ isPost);
+ }
+
+ @Override
+ public int deletePreferences(final ConfiguredObject<?> root,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ return _nextVersionManagementController.deletePreferences(root,
+ getNextVersionCategory(),
+ path,
+ parameters);
+ }
+
+ protected abstract LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object);
+
+ protected Map<String, List<String>> convertQueryParametersToNextVersion(final Map<String, List<String>> parameters)
+ {
+ return parameters;
+ }
+
+ protected ManagementController getNextVersionManagementController()
+ {
+ return _nextVersionManagementController;
+ }
+
+ protected Map<String, Object> convertAttributesToNextVersion(final ConfiguredObject<?> root,
+ final List<String> path,
+ final Map<String, Object> attributes)
+ {
+ TypeController typeController = getTypeController(attributes);
+ if (typeController != null)
+ {
+ return typeController.convertAttributesToNextVersion(root, path, attributes);
+ }
+ return attributes;
+ }
+
+
+ private Object convert(final Object content)
+ {
+ if (content instanceof LegacyConfiguredObject)
+ {
+ return convertFromNextVersion((LegacyConfiguredObject) content);
+ }
+ else if (content instanceof Collection)
+ {
+ final Collection<?> items = (Collection<?>) content;
+ return items.stream()
+ .filter(LegacyConfiguredObject.class::isInstance)
+ .map(LegacyConfiguredObject.class::cast)
+ .map(this::convertFromNextVersion)
+ .collect(Collectors.toList());
+ }
+ else
+ {
+ throw createInternalServerErrorManagementException("Unexpected data format from next version");
+ }
+ }
+
+ private TypeController getTypeController(final Map<String, Object> attributes)
+ {
+ String type = (String) attributes.get(LegacyConfiguredObject.TYPE);
+ if (type == null)
+ {
+ type = getDefaultType();
+ }
+ if (type != null)
+ {
+ return _typeControllers.get(type);
+ }
+ return null;
+ }
+
+ protected TypeController getTypeController(final LegacyConfiguredObject object)
+ {
+ String type = (String) object.getAttribute(LegacyConfiguredObject.TYPE);
+ return _nextVersionTypeControllers.get(type);
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/GenericLegacyConfiguredObject.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/GenericLegacyConfiguredObject.java
new file mode 100644
index 0000000..678cef0
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/GenericLegacyConfiguredObject.java
@@ -0,0 +1,195 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.ResponseType;
+
+public class GenericLegacyConfiguredObject implements LegacyConfiguredObject
+{
+ private final LegacyManagementController _managementController;
+ private final LegacyConfiguredObject _nextVersionLegacyConfiguredObject;
+ private final String _category;
+
+ public GenericLegacyConfiguredObject(final LegacyManagementController managementController,
+ final LegacyConfiguredObject nextVersionLegacyConfiguredObject,
+ final String category)
+ {
+ _nextVersionLegacyConfiguredObject = nextVersionLegacyConfiguredObject;
+ _managementController = managementController;
+ _category = category;
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return _nextVersionLegacyConfiguredObject.getAttributeNames();
+ }
+
+ @Override
+ public Object getAttribute(final String name)
+ {
+ return convertLegacyConfiguredObjectIfRequired(_nextVersionLegacyConfiguredObject.getAttribute(name));
+ }
+
+ @Override
+ public Object getActualAttribute(final String name)
+ {
+ return _nextVersionLegacyConfiguredObject.getActualAttribute(name);
+ }
+
+ @Override
+ public Collection<LegacyConfiguredObject> getChildren(final String category)
+ {
+ final Collection<LegacyConfiguredObject> children =
+ _nextVersionLegacyConfiguredObject.getChildren(category);
+ if (children != null)
+ {
+ return children.stream().map(_managementController::convertFromNextVersion).collect(Collectors.toSet());
+ }
+ return Collections.emptySet();
+ }
+
+ @Override
+ public String getCategory()
+ {
+ return _category;
+ }
+
+ @Override
+ public ManagementResponse invoke(final String operation,
+ final Map<String, Object> parameters,
+ final boolean isSecure)
+ {
+ ManagementResponse result = _nextVersionLegacyConfiguredObject.invoke(operation, parameters, isSecure);
+
+ return convertLegacyConfiguredObjectIfRequired(result);
+ }
+
+ @Override
+ public LegacyConfiguredObject getNextVersionConfiguredObject()
+ {
+ return _nextVersionLegacyConfiguredObject;
+ }
+
+ @Override
+ public LegacyConfiguredObject getParent(final String category)
+ {
+ LegacyConfiguredObject parent = _nextVersionLegacyConfiguredObject.getParent(category);
+ return _managementController.convertFromNextVersion(parent);
+ }
+
+ @Override
+ public boolean isSecureAttribute(final String name)
+ {
+ return _nextVersionLegacyConfiguredObject.isSecureAttribute(name);
+ }
+
+ @Override
+ public boolean isOversizedAttribute(final String name)
+ {
+ return _nextVersionLegacyConfiguredObject.isOversizedAttribute(name);
+ }
+
+ @Override
+ public String getContextValue(final String contextKey)
+ {
+ return _nextVersionLegacyConfiguredObject.getContextValue(contextKey);
+ }
+
+ @Override
+ public Map<String, Object> getStatistics()
+ {
+ return _nextVersionLegacyConfiguredObject.getStatistics();
+ }
+
+ @Override
+ public boolean equals(final Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+ final GenericLegacyConfiguredObject
+ that = (GenericLegacyConfiguredObject) o;
+ return Objects.equals(_nextVersionLegacyConfiguredObject, that._nextVersionLegacyConfiguredObject);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(_nextVersionLegacyConfiguredObject);
+ }
+
+ public LegacyManagementController getManagementController()
+ {
+ return _managementController;
+ }
+
+ protected LegacyConfiguredObject getNextVersionLegacyConfiguredObject()
+ {
+ return _nextVersionLegacyConfiguredObject;
+ }
+
+ private Object convertLegacyConfiguredObjectIfRequired(final Object value)
+ {
+ if (value instanceof LegacyConfiguredObject)
+ {
+ return _managementController.convertFromNextVersion((LegacyConfiguredObject) value);
+ }
+ else if (value instanceof Collection)
+ {
+ Collection<?> collection = (Collection<?>) value;
+ if (collection.size() > 0 && collection.iterator().next() instanceof LegacyConfiguredObject)
+ {
+ return collection.stream()
+ .filter(o -> o instanceof LegacyConfiguredObject)
+ .map(LegacyConfiguredObject.class::cast)
+ .map(_managementController::convertFromNextVersion)
+ .collect(Collectors.toSet());
+ }
+ }
+ return value;
+ }
+
+ private ManagementResponse convertLegacyConfiguredObjectIfRequired(final ManagementResponse response)
+ {
+ if (response.getType() == ResponseType.MODEL_OBJECT)
+ {
+ Object body = convertLegacyConfiguredObjectIfRequired(response.getBody());
+ return new ControllerManagementResponse(response.getType(),
+ body,
+ response.getResponseCode(),
+ response.getHeaders());
+ }
+ return response;
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/LegacyConfiguredObject.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/LegacyConfiguredObject.java
new file mode 100644
index 0000000..47d293d
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/LegacyConfiguredObject.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+
+public interface LegacyConfiguredObject
+{
+ String ID = "id";
+ String NAME = "name";
+ String TYPE = "type";
+ String DESCRIPTION = "description";
+ String DURABLE = "durable";
+ String CONTEXT = "context";
+ String LIFETIME_POLICY = "lifetimePolicy";
+ String STATE = "state";
+ String DESIRED_STATE = "desiredState";
+
+ String LAST_UPDATED_BY = "lastUpdatedBy";
+ String LAST_UPDATED_TIME = "lastUpdatedTime";
+ String CREATED_BY = "createdBy";
+ String CREATED_TIME = "createdTime";
+ String LAST_OPENED_TIME = "lastOpenedTime";
+
+ Set<String> AVAILABLE_ATTRIBUTES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+ ID,
+ NAME,
+ TYPE,
+ DESCRIPTION,
+ DURABLE,
+ CONTEXT,
+ LIFETIME_POLICY,
+ STATE,
+ DESIRED_STATE,
+ LAST_OPENED_TIME,
+ LAST_UPDATED_BY,
+ LAST_UPDATED_TIME,
+ CREATED_BY,
+ CREATED_TIME)));
+
+ Collection<String> getAttributeNames();
+
+ Object getAttribute(String name);
+
+ Map<String, Object> getStatistics();
+
+ Object getActualAttribute(String name);
+
+ boolean isSecureAttribute(String name);
+
+ boolean isOversizedAttribute(String name);
+
+ String getCategory();
+
+ Collection<LegacyConfiguredObject> getChildren(String category);
+
+ LegacyConfiguredObject getParent(String category);
+
+ String getContextValue(String contextKey);
+
+ ManagementResponse invoke(String operation, Map<String, Object> parameters, boolean isSecure);
+
+ LegacyConfiguredObject getNextVersionConfiguredObject();
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/LegacyConfiguredObjectToMapConverter.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/LegacyConfiguredObjectToMapConverter.java
new file mode 100644
index 0000000..f340359
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/LegacyConfiguredObjectToMapConverter.java
@@ -0,0 +1,251 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+import org.apache.qpid.server.model.Named;
+
+class LegacyConfiguredObjectToMapConverter
+{
+ private static final String STATISTICS_MAP_KEY = "statistics";
+ private static final String NAME = "name";
+ private static final String CONTEXT = "context";
+
+ private final LegacyManagementController _managementMetadata;
+
+ LegacyConfiguredObjectToMapConverter(final LegacyManagementController managementMetadata)
+ {
+ _managementMetadata = managementMetadata;
+ }
+
+ Map<String, Object> convertManageableToMap(final LegacyConfiguredObject legacyConfiguredObjectObject,
+ final int depth,
+ final boolean actuals,
+ final int oversizeThreshold,
+ final boolean excludeInheritedContext)
+ {
+ final Map<String, Object> object = new LinkedHashMap<>();
+
+ incorporateAttributesIntoMap(legacyConfiguredObjectObject,
+ object,
+ actuals,
+ excludeInheritedContext,
+ oversizeThreshold);
+ incorporateStatisticsIntoMap(legacyConfiguredObjectObject, object);
+
+ if (depth > 0)
+ {
+ incorporateChildrenIntoMap(legacyConfiguredObjectObject,
+ object,
+ depth,
+ actuals,
+ oversizeThreshold,
+ excludeInheritedContext);
+ }
+ return object;
+ }
+
+ private void incorporateAttributesIntoMap(
+ final LegacyConfiguredObject confObject,
+ final Map<String, Object> object,
+ final boolean useActualValues,
+ final boolean excludeInheritedContext,
+ final int oversizeThreshold)
+ {
+
+ for (String name : confObject.getAttributeNames())
+ {
+ Object value = useActualValues ? confObject.getActualAttribute(name) : confObject.getAttribute(name);
+ if (value instanceof LegacyConfiguredObject)
+ {
+ object.put(name, ((LegacyConfiguredObject) value).getAttribute(NAME));
+ }
+ else if (CONTEXT.equals(name))
+ {
+ Map<String, Object> contextValues = collectContext(confObject,
+ excludeInheritedContext,
+ useActualValues);
+
+ if (!contextValues.isEmpty())
+ {
+ object.put(CONTEXT, contextValues);
+ }
+ }
+ else if (value instanceof Collection)
+ {
+ List<Object> converted = new ArrayList<>();
+ for (Object member : (Collection) value)
+ {
+ if (member instanceof LegacyConfiguredObject)
+ {
+ converted.add(((LegacyConfiguredObject) member).getAttribute(NAME));
+ }
+ else
+ {
+ converted.add(member);
+ }
+ }
+ object.put(name, converted);
+ }
+ else if (value instanceof Named)
+ {
+ object.put(name, ((Named) value).getName());
+ }
+ else if (value != null)
+ {
+ if (confObject.isSecureAttribute(name))
+ {
+ value = confObject.getAttribute(name);
+ }
+
+ if (confObject.isOversizedAttribute(name) && !useActualValues)
+ {
+ String valueString = String.valueOf(value);
+ if (valueString.length() > oversizeThreshold)
+ {
+ object.put(name, String.valueOf(value).substring(0, oversizeThreshold - 4) + "...");
+ }
+ else
+ {
+ object.put(name, value);
+ }
+ }
+ else
+ {
+ object.put(name, value);
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Map<String, Object> collectContext(final LegacyConfiguredObject configuredObject,
+ final boolean excludeInheritedContext,
+ final boolean useActualValues)
+ {
+ final Map<String, Object> actualContext = new HashMap<>();
+ if (excludeInheritedContext)
+ {
+ final Object value = configuredObject.getActualAttribute(CONTEXT);
+ if (value instanceof Map)
+ {
+ actualContext.putAll((Map<String, String>) value);
+ }
+ }
+ else
+ {
+ actualContext.putAll(System.getenv());
+ actualContext.putAll((Map) System.getProperties());
+ collectInheritedActualContext(configuredObject, actualContext);
+ }
+
+ if (useActualValues)
+ {
+ return actualContext;
+ }
+ else
+ {
+ final Map<String, Object> effectiveContext = new HashMap<>();
+ for (String contextKey : actualContext.keySet())
+ {
+ effectiveContext.put(contextKey, configuredObject.getContextValue(contextKey));
+ }
+ return effectiveContext;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void collectInheritedActualContext(final LegacyConfiguredObject confObject,
+ final Map<String, Object> contextValues)
+ {
+ final Collection<String> parents = _managementMetadata.getParentTypes(confObject.getCategory());
+ if (parents != null && !parents.isEmpty())
+ {
+ final LegacyConfiguredObject parent = confObject.getParent(parents.iterator().next());
+ if (parent != null)
+ {
+ collectInheritedActualContext(parent, contextValues);
+ }
+ }
+ final Object value = confObject.getActualAttribute(CONTEXT);
+ if (value instanceof Map)
+ {
+ contextValues.putAll((Map<String, Object>) value);
+ }
+ }
+
+ private void incorporateStatisticsIntoMap(final LegacyConfiguredObject confObject, final Map<String, Object> object)
+ {
+ final Map<String, Object> statMap = new TreeMap<>(confObject.getStatistics());
+ if (!statMap.isEmpty())
+ {
+ object.put(STATISTICS_MAP_KEY, statMap);
+ }
+ }
+
+ private void incorporateChildrenIntoMap(
+ final LegacyConfiguredObject confObject,
+ final Map<String, Object> object,
+ final int depth,
+ final boolean actuals,
+ final int oversizeThreshold,
+ final boolean excludeInheritedContext)
+ {
+ Collection<String> childTypes = _managementMetadata.getChildrenCategories(confObject.getCategory());
+ if (childTypes != null && !childTypes.isEmpty())
+ {
+ List<String> types = new ArrayList<>(childTypes);
+ Collections.sort(types);
+
+ for (String childType : types)
+ {
+ Collection<LegacyConfiguredObject> children = confObject.getChildren(childType);
+ if (children != null && !children.isEmpty())
+ {
+ List<LegacyConfiguredObject> sortedChildren = new ArrayList<>(children);
+ sortedChildren.sort(Comparator.comparing(o -> ((String) o.getAttribute(NAME))));
+
+ List<Map<String, Object>> childObjects = sortedChildren.stream()
+ .sorted(Comparator.comparing(o -> ((String) o.getAttribute(NAME))))
+ .map(child -> convertManageableToMap(child,
+ depth
+ - 1,
+ actuals,
+ oversizeThreshold,
+ excludeInheritedContext))
+ .collect(Collectors.toList());
+ String childTypeSingular = childType.toLowerCase();
+ object.put(childTypeSingular + (childTypeSingular.endsWith("s") ? "es" : "s"), childObjects);
+ }
+ }
+ }
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/LegacyManagementController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/LegacyManagementController.java
new file mode 100644
index 0000000..4c9f4206
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/LegacyManagementController.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+
+public interface LegacyManagementController extends ManagementController
+{
+ Collection<String> getParentTypes(String category);
+
+ Collection<String> getChildrenCategories(String category);
+
+ Collection<String> getCategories();
+
+ Collection<String> getCategoryHierarchy(String rootCategory, String category);
+
+ CategoryController getCategoryController(String category);
+
+ Set<TypeController> getTypeControllersByCategory(String name);
+
+ LegacyConfiguredObject convertFromNextVersion(LegacyConfiguredObject nextVersionObject);
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/TypeController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/TypeController.java
new file mode 100644
index 0000000..cce2eb7
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/TypeController.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public interface TypeController
+{
+ String getTypeName();
+
+ String getNextVersionTypeName();
+
+ Map<String, Object> convertAttributesToNextVersion(ConfiguredObject<?> root,
+ List<String> path,
+ Map<String, Object> attributes);
+
+ LegacyConfiguredObject convertFromNextVersion(LegacyConfiguredObject object);
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/TypeControllerFactory.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/TypeControllerFactory.java
new file mode 100644
index 0000000..2d3ec05
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/TypeControllerFactory.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.plugin.Pluggable;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+
+public interface TypeControllerFactory extends Pluggable
+{
+ TypeController createController(ManagementController managementController);
+
+ String getCategory();
+
+ String getNextVersionCategory();
+
+ String getModelVersion();
+
+ static Set<TypeControllerFactory> findFactories(String version)
+ {
+ final Iterable<TypeControllerFactory> factories =
+ new QpidServiceLoader().instancesOf(TypeControllerFactory.class);
+
+ return StreamSupport.stream(factories.spliterator(), false)
+ .filter(f -> version.equals(f.getModelVersion()))
+ .collect(Collectors.toSet());
+ }
+
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/latest/LatestManagementControllerAdapter.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/latest/LatestManagementControllerAdapter.java
new file mode 100644
index 0000000..e0da225
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/latest/LatestManagementControllerAdapter.java
@@ -0,0 +1,489 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.latest;
+
+import static org.apache.qpid.server.management.plugin.ManagementException.createNotFoundManagementException;
+import static org.apache.qpid.server.model.ConfiguredObjectTypeRegistry.getCollectionMemberType;
+import static org.apache.qpid.server.model.ConfiguredObjectTypeRegistry.returnsCollectionOfConfiguredObjects;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.management.plugin.ManagementRequest;
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.ResponseType;
+import org.apache.qpid.server.management.plugin.controller.ControllerManagementResponse;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectAttribute;
+import org.apache.qpid.server.model.ConfiguredObjectOperation;
+import org.apache.qpid.server.model.Model;
+
+public class LatestManagementControllerAdapter implements ManagementController
+{
+ private ManagementController _latestManagementController;
+
+ public LatestManagementControllerAdapter(final ManagementController latestManagementController)
+ {
+ _latestManagementController = latestManagementController;
+ }
+
+ @Override
+ public String getVersion()
+ {
+ return _latestManagementController.getVersion();
+ }
+
+ @Override
+ public Collection<String> getCategories()
+ {
+ return _latestManagementController.getCategories();
+ }
+
+ @Override
+ public String getCategoryMapping(final String category)
+ {
+ return _latestManagementController.getCategoryMapping(category);
+ }
+
+ @Override
+ public String getCategory(final ConfiguredObject<?> managedObject)
+ {
+ return _latestManagementController.getCategory(managedObject);
+ }
+
+ @Override
+ public Collection<String> getCategoryHierarchy(final ConfiguredObject<?> root, final String category)
+ {
+ return _latestManagementController.getCategoryHierarchy(root, category);
+ }
+
+ @Override
+ public ManagementController getNextVersionManagementController()
+ {
+ return _latestManagementController;
+ }
+
+ @Override
+ public ManagementResponse handleGet(final ManagementRequest request) throws ManagementException
+ {
+ ManagementResponse response = _latestManagementController.handleGet(request);
+ return new ControllerManagementResponse(response.getType(),
+ convertResponseObject(response.getBody()),
+ response.getResponseCode(),
+ response.getHeaders());
+ }
+
+ @Override
+ public ManagementResponse handlePut(final ManagementRequest request) throws ManagementException
+ {
+ ManagementResponse response = _latestManagementController.handlePut(request);
+ return new ControllerManagementResponse(response.getType(),
+ convertResponseObject(response.getBody()),
+ response.getResponseCode(),
+ response.getHeaders());
+ }
+
+ @Override
+ public ManagementResponse handlePost(final ManagementRequest request) throws ManagementException
+ {
+ ManagementResponse response = _latestManagementController.handlePost(request);
+ return new ControllerManagementResponse(response.getType(),
+ convertResponseObject(response.getBody()),
+ response.getResponseCode(),
+ response.getHeaders());
+ }
+
+ @Override
+ public ManagementResponse handleDelete(final ManagementRequest request) throws ManagementException
+ {
+ ManagementResponse response = _latestManagementController.handleDelete(request);
+ return new ControllerManagementResponse(response.getType(),
+ convertResponseObject(response.getBody()),
+ response.getResponseCode(),
+ response.getHeaders());
+ }
+
+
+ @Override
+ public Object get(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ Object result = _latestManagementController.get(root, category, path, parameters);
+ return convertResponseObject(result);
+ }
+
+
+ @Override
+ public Object createOrUpdate(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, Object> attributes,
+ final boolean isPost) throws ManagementException
+ {
+ Object result = _latestManagementController.createOrUpdate(root, category, path, attributes, isPost);
+ if (result instanceof ConfiguredObject)
+ {
+ return new LegacyConfiguredObjectObject((ConfiguredObject) result);
+ }
+ return null;
+ }
+
+ @Override
+ public int delete(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ return _latestManagementController.delete(root, category, path, parameters);
+ }
+
+ @Override
+ public ManagementResponse invoke(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final String operationName,
+ final Map<String, Object> parameters,
+ final boolean isPost,
+ final boolean isSecureOrAllowedOnInsecureChannel) throws ManagementException
+ {
+ ManagementResponse response =
+ _latestManagementController.invoke(root, category, path, operationName, parameters, isPost,
+ isSecureOrAllowedOnInsecureChannel);
+ if (response.getType() == ResponseType.MODEL_OBJECT)
+ {
+ Object result = response.getBody();
+
+ if (result instanceof ConfiguredObject)
+ {
+ result = new LegacyConfiguredObjectObject((ConfiguredObject<?>) result);
+ }
+ else if (result instanceof Collection)
+ {
+ result = ((Collection<?>) result).stream()
+ .map(o -> new LegacyConfiguredObjectObject((ConfiguredObject<?>) o))
+ .collect(Collectors.toSet());
+ }
+ return new ControllerManagementResponse(ResponseType.MODEL_OBJECT, result);
+ }
+ return response;
+ }
+
+ @Override
+ public Object getPreferences(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ return _latestManagementController.getPreferences(root, category, path, parameters);
+ }
+
+ @Override
+ public void setPreferences(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Object preferences,
+ final Map<String, List<String>> parameters,
+ final boolean isPost) throws ManagementException
+ {
+ _latestManagementController.setPreferences(root, category, path, preferences, parameters, isPost);
+ }
+
+ @Override
+ public int deletePreferences(final ConfiguredObject<?> root,
+ final String category,
+ final List<String> path,
+ final Map<String, List<String>> parameters) throws ManagementException
+ {
+ return _latestManagementController.delete(root, category, path, parameters);
+ }
+
+ @Override
+ public Object formatConfiguredObject(final Object data,
+ final Map<String, List<String>> parameters,
+ final boolean isSecureOrAllowedOnInsecureChannel)
+ {
+ Object content = data;
+ if (content instanceof LegacyConfiguredObjectObject)
+ {
+
+ content = ((LegacyConfiguredObjectObject) data).getConfiguredObject();
+ }
+ else if (data instanceof Collection)
+ {
+ content = ((Collection<?>) data).stream()
+ .filter(o -> o instanceof LegacyConfiguredObjectObject)
+ .map(LegacyConfiguredObjectObject.class::cast)
+ .map(LegacyConfiguredObjectObject::getConfiguredObject)
+ .collect(Collectors.toSet());
+ }
+
+ return _latestManagementController.formatConfiguredObject(content,
+ parameters,
+ isSecureOrAllowedOnInsecureChannel);
+ }
+
+ private Class<? extends ConfiguredObject> getRequestCategoryClass(final String categoryName,
+ final Model model)
+ {
+ for (Class<? extends ConfiguredObject> category : model.getSupportedCategories())
+ {
+ if (category.getSimpleName().toLowerCase().equals(categoryName))
+ {
+ return category;
+ }
+ }
+ throw createNotFoundManagementException(String.format("Category is not found for '%s'", categoryName));
+ }
+
+ private Object convertResponseObject(final Object result)
+ {
+ if (result instanceof ConfiguredObject)
+ {
+ return new LegacyConfiguredObjectObject((ConfiguredObject) result);
+ }
+ else if (result instanceof Collection)
+ {
+ return ((Collection<?>) result).stream().filter(o -> o instanceof ConfiguredObject)
+ .map(ConfiguredObject.class::cast)
+ .map(o -> new LegacyConfiguredObjectObject((ConfiguredObject<?>) o))
+ .collect(Collectors.toSet());
+ }
+ return result;
+ }
+
+ private class LegacyConfiguredObjectObject implements LegacyConfiguredObject
+ {
+ private final Map<String, Object> _actualAttributes;
+ private ConfiguredObject<?> _configuredObject;
+
+ LegacyConfiguredObjectObject(final ConfiguredObject<?> configuredObject)
+ {
+ _configuredObject = configuredObject;
+ _actualAttributes = configuredObject.getActualAttributes();
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return _configuredObject.getAttributeNames();
+ }
+
+ @Override
+ public Object getAttribute(final String name)
+ {
+ return convertIntoLegacyIfRequired(name, _configuredObject.getAttribute(name));
+ }
+
+ @Override
+ public Object getActualAttribute(final String name)
+ {
+ return _actualAttributes.get(name);
+ }
+
+ @Override
+ public Collection<LegacyConfiguredObject> getChildren(final String category)
+ {
+ Class<? extends ConfiguredObject> categoryClass =
+ getRequestCategoryClass(category.toLowerCase(), _configuredObject.getModel());
+ return _configuredObject.getChildren(categoryClass)
+ .stream()
+ .map(LegacyConfiguredObjectObject::new)
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public String getCategory()
+ {
+ return _configuredObject.getCategoryClass().getSimpleName();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public ManagementResponse invoke(final String operationName,
+ final Map<String, Object> parameters,
+ final boolean isSecure)
+ {
+ try
+ {
+ final Model model = _configuredObject.getModel();
+ final Map<String, ConfiguredObjectOperation<?>> availableOperations =
+ model.getTypeRegistry().getOperations(_configuredObject.getClass());
+ final ConfiguredObjectOperation operation = availableOperations.get(operationName);
+ if (operation == null)
+ {
+ throw createNotFoundManagementException(String.format("No such operation as '%s' in '%s'",
+ operationName,
+ getCategory()));
+ }
+
+ Object returnValue = operation.perform(_configuredObject, parameters);
+
+ final ResponseType responseType;
+ if (ConfiguredObject.class.isAssignableFrom(operation.getReturnType()))
+ {
+ returnValue = new LegacyConfiguredObjectObject((ConfiguredObject<?>) returnValue);
+ responseType = ResponseType.MODEL_OBJECT;
+ }
+ else if (returnsCollectionOfConfiguredObjects(operation))
+ {
+ returnValue = ((Collection) returnValue).stream()
+ .map(o -> new LegacyConfiguredObjectObject((ConfiguredObject<?>) o))
+ .collect(Collectors.toSet());
+ responseType = ResponseType.MODEL_OBJECT;
+ }
+ else
+ {
+ responseType = ResponseType.DATA;
+ }
+ return new ControllerManagementResponse(responseType, returnValue);
+ }
+ catch (RuntimeException e)
+ {
+ throw ManagementException.toManagementException(e,
+ getCategoryMapping(getCategory()),
+ Collections.emptyList());
+ }
+ catch (Error e)
+ {
+ throw ManagementException.handleError(e);
+ }
+ }
+
+ @Override
+ public LegacyConfiguredObject getNextVersionConfiguredObject()
+ {
+ return null;
+ }
+
+ @Override
+ public LegacyConfiguredObject getParent(final String category)
+ {
+ ConfiguredObject<?> parent = _configuredObject.getParent();
+ if (category != null && !parent.getCategoryClass().getSimpleName().equalsIgnoreCase(category))
+ {
+ throw new IllegalArgumentException(String.format(
+ "ConfiguredObject of category '%s' has no parent of category %s",
+ getCategory(),
+ category));
+ }
+ return new LegacyConfiguredObjectObject(parent);
+ }
+
+ @Override
+ public boolean isSecureAttribute(final String name)
+ {
+ ConfiguredObjectAttribute<?, ?> objectAttribute = getConfiguredObjectAttribute(name);
+ return objectAttribute != null && objectAttribute.isSecure();
+ }
+
+ @Override
+ public boolean isOversizedAttribute(final String name)
+ {
+ ConfiguredObjectAttribute<?, ?> objectAttribute = getConfiguredObjectAttribute(name);
+ return objectAttribute != null && objectAttribute.isOversized();
+ }
+
+ @Override
+ public String getContextValue(final String contextKey)
+ {
+ return _configuredObject.getContextValue(String.class, contextKey);
+ }
+
+ @Override
+ public Map<String, Object> getStatistics()
+ {
+ return _configuredObject.getStatistics();
+ }
+
+ @Override
+ public boolean equals(final Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+ final LegacyConfiguredObjectObject object = (LegacyConfiguredObjectObject) o;
+ return Objects.equals(_configuredObject, object._configuredObject);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return _configuredObject.hashCode();
+ }
+
+ ConfiguredObject<?> getConfiguredObject()
+ {
+ return _configuredObject;
+ }
+
+ private Object convertIntoLegacyIfRequired(final String name, final Object value)
+ {
+ if (value != null)
+ {
+ ConfiguredObjectAttribute<?, ?> attribute = getConfiguredObjectAttribute(name);
+
+ final Class<?> type = attribute.getType();
+ final Type genericType = attribute.getGenericType();
+ if (ConfiguredObject.class.isAssignableFrom(type))
+ {
+ return new LegacyConfiguredObjectObject((ConfiguredObject<?>) value);
+ }
+ else if (Collection.class.isAssignableFrom(type)
+ && genericType instanceof ParameterizedType
+ && ConfiguredObject.class.isAssignableFrom(getCollectionMemberType((ParameterizedType) genericType)))
+ {
+ Collection<?> collection = (Collection<?>) value;
+ return collection.stream()
+ .filter(o -> o instanceof LegacyConfiguredObjectObject)
+ .map(LegacyConfiguredObjectObject.class::cast)
+ .map(co -> new LegacyConfiguredObjectObject((ConfiguredObject<?>) co))
+ .collect(Collectors.toSet());
+ }
+ }
+ return value;
+ }
+
+
+ private ConfiguredObjectAttribute<?, ?> getConfiguredObjectAttribute(final String name)
+ {
+ return _configuredObject.getModel()
+ .getTypeRegistry()
+ .getAttributeTypes(_configuredObject.getClass())
+ .get(name);
+ }
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/LegacyManagementController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/LegacyManagementController.java
new file mode 100644
index 0000000..44ddf03
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/LegacyManagementController.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.v7_0;
+
+import static org.apache.qpid.server.management.plugin.controller.ConverterHelper.getIntParameterFromRequest;
+import static org.apache.qpid.server.management.plugin.controller.ConverterHelper.getParameter;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.AbstractLegacyConfiguredObjectController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+
+public class LegacyManagementController extends AbstractLegacyConfiguredObjectController
+{
+ private static final String DEPTH_PARAM = "depth";
+ private static final String OVERSIZE_PARAM = "oversize";
+ private static final String ACTUALS_PARAM = "actuals";
+ private static final String EXCLUDE_INHERITED_CONTEXT_PARAM = "excludeInheritedContext";
+ private static final String SINGLETON_MODEL_OBJECT_RESPONSE_AS_LIST = "singletonModelObjectResponseAsList";
+
+ private static final int DEFAULT_DEPTH = 0;
+ private static final int DEFAULT_OVERSIZE = 120;
+
+ public LegacyManagementController(final ManagementController nextVersionManagementController)
+ {
+ super(LegacyManagementControllerFactory.MODEL_VERSION, nextVersionManagementController);
+ }
+
+ @Override
+ protected Map<String, List<String>> convertQueryParameters(final Map<String, List<String>> parameters)
+ {
+ return parameters;
+ }
+
+ @Override
+ public Object formatConfiguredObject(final Object content,
+ final Map<String, List<String>> parameters,
+ final boolean isSecureOrAllowedOnInsecureChannel)
+ {
+ final int depth = getIntParameterFromRequest(parameters, DEPTH_PARAM, DEFAULT_DEPTH);
+ final int oversizeThreshold = getIntParameterFromRequest(parameters, OVERSIZE_PARAM, DEFAULT_OVERSIZE);
+ final boolean actuals = Boolean.parseBoolean(getParameter(ACTUALS_PARAM, parameters));
+ final String excludeInheritedContextParameter = getParameter(EXCLUDE_INHERITED_CONTEXT_PARAM, parameters);
+ final boolean excludeInheritedContext = excludeInheritedContextParameter == null
+ || Boolean.parseBoolean(excludeInheritedContextParameter);
+ final boolean responseAsList =
+ Boolean.parseBoolean(getParameter(SINGLETON_MODEL_OBJECT_RESPONSE_AS_LIST, parameters));
+
+ return formatConfiguredObject(content,
+ isSecureOrAllowedOnInsecureChannel,
+ depth,
+ oversizeThreshold,
+ actuals,
+ excludeInheritedContext,
+ responseAsList);
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/LegacyManagementControllerFactory.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/LegacyManagementControllerFactory.java
new file mode 100644
index 0000000..1b26e92
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/LegacyManagementControllerFactory.java
@@ -0,0 +1,62 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.v7_0;
+
+import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementControllerFactory;
+import org.apache.qpid.server.management.plugin.controller.CategoryControllerFactory;
+import org.apache.qpid.server.management.plugin.controller.TypeControllerFactory;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class LegacyManagementControllerFactory implements ManagementControllerFactory
+{
+ public static final String MODEL_VERSION = "7.0";
+
+ @Override
+ public String getType()
+ {
+ return "org.apache.qpid.server.management.plugin.model.v7_0";
+ }
+
+ @Override
+ public String getVersion()
+ {
+ return MODEL_VERSION;
+ }
+
+ @Override
+ public String getPreviousVersion()
+ {
+ return "6.1";
+ }
+
+ @Override
+ public ManagementController createManagementController(final HttpManagementConfiguration<?> httpManagement,
+ final ManagementController nextVersionManagementController)
+ {
+
+ LegacyManagementController controller = new LegacyManagementController(nextVersionManagementController);
+ controller.initialize();
+ return controller;
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/ContainerController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/ContainerController.java
new file mode 100644
index 0000000..44a34e5
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/ContainerController.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.v7_0.category;
+
+
+import java.util.Set;
+
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+
+
+class ContainerController extends LegacyCategoryController
+{
+ ContainerController(final LegacyManagementController legacyManagementController,
+ final String type,
+ final String parentType,
+ final String defaultType,
+ final Set<TypeController> typeControllers)
+ {
+ super(legacyManagementController, type, parentType, defaultType, typeControllers);
+ }
+
+ @Override
+ protected LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+ {
+ return new LegacyContainer(getManagementController(), object, getCategory());
+ }
+
+ static class LegacyContainer extends GenericLegacyConfiguredObject
+ {
+ private static final String MODEL_VERSION = "modelVersion";
+
+ LegacyContainer(final LegacyManagementController managementController,
+ final LegacyConfiguredObject nextVersionLegacyConfiguredObject,
+ final String category)
+ {
+ super(managementController, nextVersionLegacyConfiguredObject, category);
+ }
+
+ @Override
+ public Object getAttribute(final String name)
+ {
+ if (MODEL_VERSION.equals(name))
+ {
+ return getManagementController().getVersion();
+ }
+ return super.getAttribute(name);
+ }
+
+ @Override
+ public Object getActualAttribute(final String name)
+ {
+ if (MODEL_VERSION.equals(name))
+ {
+ return getManagementController().getVersion();
+ }
+ return super.getActualAttribute(name);
+ }
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/LegacyCategoryController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/LegacyCategoryController.java
new file mode 100644
index 0000000..82ace6d
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/LegacyCategoryController.java
@@ -0,0 +1,63 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.v7_0.category;
+
+import java.util.Set;
+
+import org.apache.qpid.server.management.plugin.controller.GenericCategoryController;
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+import org.apache.qpid.server.management.plugin.controller.latest.LatestManagementControllerAdapter;
+
+public class LegacyCategoryController extends GenericCategoryController
+{
+ private final String _parentCategory;
+
+ LegacyCategoryController(final LegacyManagementController managementController,
+ final String name,
+ final String parentCategory,
+ final String defaultType,
+ final Set<TypeController> typeControllers)
+ {
+ super(managementController,
+ new LatestManagementControllerAdapter(managementController.getNextVersionManagementController()),
+ name,
+ defaultType,
+ typeControllers);
+ _parentCategory = parentCategory;
+ }
+
+ @Override
+ public String[] getParentCategories()
+ {
+ return new String[]{_parentCategory};
+ }
+
+ @Override
+ protected LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+ {
+ return new GenericLegacyConfiguredObject(getManagementController(),
+ object,
+ getCategory());
+ }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/LegacyCategoryControllerFactory.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/LegacyCategoryControllerFactory.java
new file mode 100644
index 0000000..3f07cc3
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/LegacyCategoryControllerFactory.java
@@ -0,0 +1,154 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.v7_0.category;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.management.plugin.controller.CategoryController;
+import org.apache.qpid.server.management.plugin.controller.CategoryControllerFactory;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.v7_0.LegacyManagementControllerFactory;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class LegacyCategoryControllerFactory implements CategoryControllerFactory
+{
+ static final String CATEGORY_BROKER = "Broker";
+ private static final String CATEGORY_BROKER_LOGGER = "BrokerLogger";
+ private static final String CATEGORY_BROKER_LOG_INCLUSION_RULE = "BrokerLogInclusionRule";
+ private static final String CATEGORY_AUTHENTICATION_PROVIDER = "AuthenticationProvider";
+ private static final String CATEGORY_USER = "User";
+ private static final String CATEGORY_ACCESS_CONTROL_PROVIDER = "AccessControlProvider";
+ private static final String CATEGORY_PLUGIN = "Plugin";
+ private static final String CATEGORY_TRUST_STORE = "TrustStore";
+ private static final String CATEGORY_KEY_STORE = "KeyStore";
+ private static final String CATEGORY_PORT = "Port";
+ private static final String CATEGORY_VIRTUAL_HOST_ALIAS = "VirtualHostAlias";
+ private static final String CATEGORY_GROUP_PROVIDER = "GroupProvider";
+ private static final String CATEGORY_GROUP = "Group";
+ private static final String CATEGORY_GROUP_MEMBER = "GroupMember";
+ private static final String CATEGORY_VIRTUAL_HOST_NODE = "VirtualHostNode";
+ private static final String CATEGORY_REMOTE_REPLICATION_NODE = "RemoteReplicationNode";
+ static final String CATEGORY_VIRTUAL_HOST = "VirtualHost";
+ private static final String CATEGORY_VIRTUAL_HOST_LOGGER = "VirtualHostLogger";
+ private static final String CATEGORY_VIRTUAL_HOST_LOG_INCLUSION_RULE = "VirtualHostLogInclusionRule";
+ private static final String CATEGORY_VIRTUAL_HOST_ACCESS_CONTROL_PROVIDER = "VirtualHostAccessControlProvider";
+ private static final String CATEGORY_EXCHANGE = "Exchange";
+ private static final String CATEGORY_QUEUE = "Queue";
+ private static final String CATEGORY_CONSUMER = "Consumer";
+ private static final String CATEGORY_CONNECTION = "Connection";
+ private static final String CATEGORY_SESSION = "Session";
+ private static final String CATEGORY_SYSTEM_CONFIG = "SystemConfig";
+ static final Map<String, String> SUPPORTED_CATEGORIES =
+ Collections.unmodifiableMap(new HashMap<String, String>()
+ {
+ {
+ put(CATEGORY_BROKER_LOGGER, CATEGORY_BROKER);
+ put(CATEGORY_BROKER_LOG_INCLUSION_RULE, CATEGORY_BROKER_LOGGER);
+ put(CATEGORY_AUTHENTICATION_PROVIDER, CATEGORY_BROKER);
+ put(CATEGORY_USER, CATEGORY_AUTHENTICATION_PROVIDER);
+ put(CATEGORY_ACCESS_CONTROL_PROVIDER, CATEGORY_BROKER);
+ put(CATEGORY_PLUGIN, CATEGORY_BROKER);
+ put(CATEGORY_TRUST_STORE, CATEGORY_BROKER);
+ put(CATEGORY_KEY_STORE, CATEGORY_BROKER);
+ put(CATEGORY_PORT, CATEGORY_BROKER);
+ put(CATEGORY_VIRTUAL_HOST_ALIAS, CATEGORY_PORT);
+ put(CATEGORY_GROUP_PROVIDER, CATEGORY_BROKER);
+ put(CATEGORY_GROUP, CATEGORY_GROUP_PROVIDER);
+ put(CATEGORY_GROUP_MEMBER, CATEGORY_GROUP);
+ put(CATEGORY_VIRTUAL_HOST_NODE, CATEGORY_BROKER);
+ put(CATEGORY_REMOTE_REPLICATION_NODE, CATEGORY_VIRTUAL_HOST_NODE);
+ put(CATEGORY_VIRTUAL_HOST, CATEGORY_VIRTUAL_HOST_NODE);
+ put(CATEGORY_VIRTUAL_HOST_LOGGER, CATEGORY_VIRTUAL_HOST);
+ put(CATEGORY_VIRTUAL_HOST_LOG_INCLUSION_RULE, CATEGORY_VIRTUAL_HOST_LOGGER);
+ put(CATEGORY_VIRTUAL_HOST_ACCESS_CONTROL_PROVIDER, CATEGORY_VIRTUAL_HOST);
+ put(CATEGORY_EXCHANGE, CATEGORY_VIRTUAL_HOST);
+ put(CATEGORY_QUEUE, CATEGORY_VIRTUAL_HOST);
+ put(CATEGORY_CONSUMER, CATEGORY_QUEUE);
+ put(CATEGORY_CONNECTION, CATEGORY_VIRTUAL_HOST);
+ put(CATEGORY_SESSION, CATEGORY_CONNECTION);
+ put(CATEGORY_BROKER, CATEGORY_SYSTEM_CONFIG);
+ }
+ });
+
+ private static final Map<String, String> DEFAULT_TYPES = Collections.unmodifiableMap(new HashMap<String, String>()
+ {
+ {
+ put(CATEGORY_BROKER_LOGGER, "Broker");
+ put(CATEGORY_TRUST_STORE, "FileTrustStore");
+ put(CATEGORY_KEY_STORE, "FileKeyStore");
+ put(CATEGORY_GROUP, "ManagedGroup");
+ put(CATEGORY_GROUP_MEMBER, "ManagedGroupMember");
+ put(CATEGORY_VIRTUAL_HOST, "ProvidedStore");
+ put(CATEGORY_QUEUE, "standard");
+ }
+ });
+
+ @Override
+ public CategoryController createController(final String type,
+ final LegacyManagementController legacyManagementController)
+ {
+ if (SUPPORTED_CATEGORIES.containsKey(type))
+ {
+ if (CATEGORY_VIRTUAL_HOST.equals(type) || CATEGORY_BROKER.equals(type))
+ {
+ return new ContainerController(legacyManagementController,
+ type,
+ SUPPORTED_CATEGORIES.get(type),
+ DEFAULT_TYPES.get(type),
+ legacyManagementController.getTypeControllersByCategory(type));
+ }
+ else
+ {
+ return new LegacyCategoryController(legacyManagementController,
+ type,
+ SUPPORTED_CATEGORIES.get(type),
+ DEFAULT_TYPES.get(type),
+ legacyManagementController.getTypeControllersByCategory(type));
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException(String.format("Unsupported type '%s'", type));
+ }
+ }
+
+ @Override
+ public Set<String> getSupportedCategories()
+ {
+ return SUPPORTED_CATEGORIES.keySet();
+ }
+
+ @Override
+ public String getModelVersion()
+ {
+ return LegacyManagementControllerFactory.MODEL_VERSION;
+ }
+
+ @Override
+ public String getType()
+ {
+ return LegacyCategoryControllerFactory.class.getName();
+ }
+}
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/AbstractLegacyConfiguredObjectControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/AbstractLegacyConfiguredObjectControllerTest.java
new file mode 100644
index 0000000..8df9aea
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/AbstractLegacyConfiguredObjectControllerTest.java
@@ -0,0 +1,292 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementRequest;
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.RequestType;
+import org.apache.qpid.server.management.plugin.ResponseType;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class AbstractLegacyConfiguredObjectControllerTest extends UnitTestBase
+{
+
+ private static final String TEST_VERSION = "testVersion";
+ private static final String TEST_CATEGORY = "testCategory";
+ private static final String TEST_CATEGORY_2 = "testCategory2";
+ private static final String TEST_TYPE = "testType";
+ private ManagementController _nextVersionManagementController;
+ private AbstractLegacyConfiguredObjectController _controller;
+ private CategoryController _categoryController2;
+ private ConfiguredObject<?> _root;
+ private TypeController _typeController;
+
+ @Before
+ public void setUp()
+ {
+ _nextVersionManagementController = mock(ManagementController.class);
+ _controller = new AbstractLegacyConfiguredObjectController(TEST_VERSION, _nextVersionManagementController)
+ {
+ @Override
+ public Object formatConfiguredObject(final Object content,
+ final Map<String, List<String>> parameters,
+ final boolean isSecureOrAllowedOnInsecureChannel)
+ {
+ return null;
+ }
+
+ @Override
+ protected Map<String, List<String>> convertQueryParameters(final Map<String, List<String>> parameters)
+ {
+ return parameters;
+ }
+ };
+ _root = mock(ConfiguredObject.class);
+ final CategoryControllerFactory categoryFactory = mock(CategoryControllerFactory.class);
+ final TypeControllerFactory typeFactory = mock(TypeControllerFactory.class);
+ final CategoryController categoryController = mock(CategoryController.class);
+ when(categoryController.getParentCategories()).thenReturn(new String[0]);
+ when(categoryController.getCategory()).thenReturn(TEST_CATEGORY);
+ _categoryController2 = mock(CategoryController.class);
+ when(_categoryController2.getCategory()).thenReturn(TEST_CATEGORY_2);
+ when(_categoryController2.getParentCategories()).thenReturn(new String[]{TEST_CATEGORY});
+
+ when(categoryFactory.getModelVersion()).thenReturn(TEST_VERSION);
+ when(categoryFactory.getSupportedCategories()).thenReturn(new HashSet<>(Arrays.asList(TEST_CATEGORY,
+ TEST_CATEGORY_2)));
+ when(categoryFactory.createController(TEST_CATEGORY, _controller)).thenReturn(categoryController);
+ when(categoryFactory.createController(TEST_CATEGORY_2, _controller)).thenReturn(_categoryController2);
+ when(typeFactory.getCategory()).thenReturn(TEST_CATEGORY);
+ when(typeFactory.getModelVersion()).thenReturn(TEST_VERSION);
+ _typeController = mock(TypeController.class);
+ when(_typeController.getTypeName()).thenReturn(TEST_TYPE);
+ when(typeFactory.createController(_controller)).thenReturn(_typeController);
+ _controller.initialize(Collections.singleton(categoryFactory), Collections.singleton(typeFactory));
+ }
+
+ @Test
+ public void getVersion()
+ {
+ assertThat(_controller.getVersion(), is(equalTo(TEST_VERSION)));
+ }
+
+ @Test
+ public void getCategories()
+ {
+ Collection<String> categories = _controller.getCategories();
+ Set<String> expected = new HashSet<>(Arrays.asList(TEST_CATEGORY, TEST_CATEGORY_2));
+ assertThat(new HashSet<>(categories), is(equalTo(expected)));
+ }
+
+ @Test
+ public void getCategoryMapping()
+ {
+ assertThat(_controller.getCategoryMapping(TEST_CATEGORY), is(equalTo(
+ String.format("/api/v%s/%s/", TEST_VERSION, TEST_CATEGORY.toLowerCase()))));
+ }
+
+ @Test
+ public void getCategory()
+ {
+ final ConfiguredObject<?> managementObject = mock(ConfiguredObject.class);
+ when(_nextVersionManagementController.getCategory(managementObject)).thenReturn(TEST_CATEGORY);
+ String category = _controller.getCategory(managementObject);
+ assertThat(category, is(equalTo(TEST_CATEGORY)));
+ }
+
+ @Test
+ public void getCategoryHierarchy()
+ {
+ when(_nextVersionManagementController.getCategory(_root)).thenReturn(TEST_CATEGORY);
+ final List<String> hierarchy = _controller.getCategoryHierarchy(_root, TEST_CATEGORY_2);
+
+ final Set<String> expected = Collections.singleton(TEST_CATEGORY_2);
+ assertThat(new HashSet<>(hierarchy), is(equalTo(expected)));
+ }
+
+ @Test
+ public void getNextVersionManagementController()
+ {
+ assertThat(_controller.getNextVersionManagementController(), is(equalTo(_nextVersionManagementController)));
+ }
+
+ @Test
+ public void createOrUpdate()
+ {
+ final List<String> path = Collections.singletonList("test");
+ final Map<String, Object> attributes = Collections.singletonMap("name", "test");
+ final LegacyConfiguredObject object = mock(LegacyConfiguredObject.class);
+ when(_categoryController2.createOrUpdate(_root, path, attributes, false)).thenReturn(object);
+ final LegacyConfiguredObject result =
+ _controller.createOrUpdate(_root, TEST_CATEGORY_2, path, attributes, false);
+ assertThat(result, is(equalTo(object)));
+ }
+
+ @Test
+ public void get()
+ {
+ final List<String> path = Collections.singletonList("test");
+ final LegacyConfiguredObject object = mock(LegacyConfiguredObject.class);
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("name", Collections.singletonList("test"));
+ when(_categoryController2.get(_root, path, parameters)).thenReturn(object);
+ final Object result = _controller.get(_root, TEST_CATEGORY_2, path, parameters);
+ assertThat(result, is(equalTo(object)));
+ }
+
+ @Test
+ public void delete()
+ {
+ final List<String> path = Collections.singletonList("test");
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("name", Collections.singletonList("test"));
+ _controller.delete(_root, TEST_CATEGORY_2, path, parameters);
+ verify(_categoryController2).delete(_root, path, parameters);
+ }
+
+ @Test
+ public void invoke()
+ {
+ final List<String> path = Collections.singletonList("test");
+ final Map<String, Object> parameters = Collections.singletonMap("name", "test");
+ final Object operationResult = mock(Object.class);
+
+ final String operationName = "testOperation";
+
+ final ManagementResponse managementResponse =
+ new ControllerManagementResponse(ResponseType.DATA, operationResult);
+ when(_categoryController2.invoke(_root, path, operationName, parameters, true, true)).thenReturn(
+ managementResponse);
+ final ManagementResponse result =
+ _controller.invoke(_root, TEST_CATEGORY_2, path, operationName, parameters, true, true);
+
+ assertThat(result, is(notNullValue()));
+ assertThat(result.getResponseCode(), is(equalTo(200)));
+ assertThat(result.getBody(), is(equalTo(operationResult)));
+ verify(_categoryController2).invoke(_root, path, operationName, parameters, true, true);
+ }
+
+ @Test
+ public void getPreferences()
+ {
+ final List<String> path = Arrays.asList("test", "preferences");
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("name", Collections.singletonList("test"));
+ final Object prefs = mock(Object.class);
+ when(_categoryController2.getPreferences(_root, path, parameters)).thenReturn(prefs);
+ final Object preferences = _controller.getPreferences(_root, TEST_CATEGORY_2, path, parameters);
+ assertThat(preferences, is(equalTo(prefs)));
+ verify(_categoryController2).getPreferences(_root, path, parameters);
+ }
+
+ @Test
+ public void setPreferences()
+ {
+ final List<String> path = Arrays.asList("test", "preferences");
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("name", Collections.singletonList("test"));
+ final Object prefs = mock(Object.class);
+ _controller.setPreferences(_root, TEST_CATEGORY_2, path, prefs, parameters, true);
+ verify(_categoryController2).setPreferences(_root, path, prefs, parameters, true);
+ }
+
+ @Test
+ public void deletePreferences()
+ {
+ final List<String> path = Arrays.asList("test", "preferences");
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("name", Collections.singletonList("test"));
+ _controller.deletePreferences(_root, TEST_CATEGORY_2, path, parameters);
+ verify(_categoryController2).deletePreferences(_root, path, parameters);
+ }
+
+ @Test
+ public void getCategoryController()
+ {
+ assertThat(_controller.getCategoryController(TEST_CATEGORY_2), is(equalTo(_categoryController2)));
+ }
+
+ @Test
+ public void getTypeControllersByCategory()
+ {
+ final Set<TypeController> typeControllers = _controller.getTypeControllersByCategory(TEST_CATEGORY);
+ assertThat(typeControllers, is(equalTo(Collections.singleton(_typeController))));
+ }
+
+ @Test
+ public void getChildrenCategories()
+ {
+ final Collection<String> childrenCategories = _controller.getChildrenCategories(TEST_CATEGORY);
+ assertThat(new HashSet<>(childrenCategories), is(equalTo(Collections.singleton(TEST_CATEGORY_2))));
+ }
+
+ @Test
+ public void getParentTypes()
+ {
+ final Collection<String> childrenCategories = _controller.getParentTypes(TEST_CATEGORY_2);
+ assertThat(new HashSet<>(childrenCategories), is(equalTo(Collections.singleton(TEST_CATEGORY))));
+ }
+
+ @Test
+ public void getNextVersionLegacyConfiguredObjectConverter()
+ {
+ assertThat(_controller.getNextVersionManagementController(), is(equalTo(_nextVersionManagementController)));
+ }
+
+ @Test
+ public void getRequestType()
+ {
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("name", Collections.singletonList("test"));
+ final ManagementRequest managementRequest = mock(ManagementRequest.class);
+ doReturn(_root).when(managementRequest).getRoot();
+ when(managementRequest.getMethod()).thenReturn("GET");
+ when(managementRequest.getParameters()).thenReturn(parameters);
+ when(managementRequest.getPath()).thenReturn(Collections.singletonList("test"));
+ when(managementRequest.getCategory()).thenReturn(TEST_CATEGORY_2);
+ when(_controller.getCategory(_root)).thenReturn(TEST_CATEGORY);
+
+ final RequestType requestType = _controller.getRequestType(managementRequest);
+ assertThat(requestType, is(equalTo(RequestType.MODEL_OBJECT)));
+ }
+}
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/GenericCategoryControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/GenericCategoryControllerTest.java
new file mode 100644
index 0000000..1f336ae
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/GenericCategoryControllerTest.java
@@ -0,0 +1,247 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.ResponseType;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class GenericCategoryControllerTest extends UnitTestBase
+{
+ private static final String TEST_CATEGORY = "testCategory";
+ private static final String DEFAULT_TYPE = "defaultType";
+ private LegacyManagementController _managementController;
+ private LegacyManagementController _nextVersionManagementController;
+ private GenericCategoryController _controller;
+ private ConfiguredObject _root;
+ private TypeController _typeController;
+ private LegacyConfiguredObject _converted;
+
+ @Before
+ public void setUp()
+ {
+ _managementController = mock(LegacyManagementController.class);
+ _nextVersionManagementController = mock(LegacyManagementController.class);
+ _typeController = mock(TypeController.class);
+ when(_typeController.getTypeName()).thenReturn(DEFAULT_TYPE);
+ when(_typeController.getNextVersionTypeName()).thenReturn(DEFAULT_TYPE);
+ _converted = mock(LegacyConfiguredObject.class);
+ _controller = new GenericCategoryController(_managementController,
+ _nextVersionManagementController,
+ TEST_CATEGORY,
+ DEFAULT_TYPE,
+ Collections.singleton(_typeController))
+ {
+ @Override
+ protected LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+ {
+ return _converted;
+ }
+
+ @Override
+ public String[] getParentCategories()
+ {
+ return new String[0];
+ }
+ };
+ _root = mock(ConfiguredObject.class);
+ }
+
+ @Test
+ public void getCategory()
+ {
+ assertThat(_controller.getCategory(), is(equalTo(TEST_CATEGORY)));
+ }
+
+ @Test
+ public void getDefaultType()
+ {
+ assertThat(_controller.getDefaultType(), is(equalTo(DEFAULT_TYPE)));
+ }
+
+ @Test
+ public void getManagementController()
+ {
+ assertThat(_controller.getManagementController(), is(equalTo(_managementController)));
+ }
+
+ @Test
+ public void get()
+ {
+ final List<String> path = Arrays.asList("test1", "test2");
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("testParam", Collections.singletonList("testValue"));
+ final LegacyConfiguredObject result = mock(LegacyConfiguredObject.class);
+ when(result.getAttribute(LegacyConfiguredObject.TYPE)).thenReturn(DEFAULT_TYPE);
+ final LegacyConfiguredObject convertedResult = mock(LegacyConfiguredObject.class);
+ when(_nextVersionManagementController.get(_root, TEST_CATEGORY, path, parameters)).thenReturn(result);
+ when(_typeController.convertFromNextVersion(result)).thenReturn(convertedResult);
+ final Object readResult = _controller.get(_root, path, parameters);
+ assertThat(readResult, is(equalTo(convertedResult)));
+ verify(_nextVersionManagementController).get(_root, TEST_CATEGORY, path, parameters);
+ }
+
+ @Test
+ public void createOrUpdate()
+ {
+ final List<String> path = Arrays.asList("test1", "test2");
+ final Map<String, Object> attributes = Collections.singletonMap("test", "testValue");
+ final LegacyConfiguredObject result = mock(LegacyConfiguredObject.class);
+ final LegacyConfiguredObject convertedResult = mock(LegacyConfiguredObject.class);
+ when(result.getAttribute(LegacyConfiguredObject.TYPE)).thenReturn(DEFAULT_TYPE);
+
+ when(_typeController.convertAttributesToNextVersion(_root, path, attributes)).thenReturn(attributes);
+ when(_typeController.convertFromNextVersion(result)).thenReturn(convertedResult);
+ when(_nextVersionManagementController.createOrUpdate(_root, TEST_CATEGORY, path, attributes, false))
+ .thenReturn(result);
+ when(_typeController.convertFromNextVersion(result)).thenReturn(convertedResult);
+ final Object createResult = _controller.createOrUpdate(_root, path, attributes, false);
+ assertThat(createResult, is(equalTo(convertedResult)));
+ verify(_nextVersionManagementController).createOrUpdate(_root, TEST_CATEGORY, path, attributes, false);
+ }
+
+ @Test
+ public void delete()
+ {
+ final List<String> path = Arrays.asList("test1", "test2");
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("testParam", Collections.singletonList("testValue"));
+
+ final int result = 1;
+ when(_nextVersionManagementController.delete(_root, TEST_CATEGORY, path, parameters)).thenReturn(result);
+ final Object deleteResult = _controller.delete(_root, path, parameters);
+ assertThat(deleteResult, is(equalTo(result)));
+ verify(_nextVersionManagementController).delete(_root, TEST_CATEGORY, path, parameters);
+ }
+
+ @Test
+ public void invoke()
+ {
+ final List<String> path = Arrays.asList("test1", "test2");
+ final String operationName = "testOperation";
+ final Map<String, Object> operationParameters = Collections.singletonMap("testParam", "testValue");
+
+ final LegacyConfiguredObject result = mock(LegacyConfiguredObject.class);
+ when(result.getAttribute(LegacyConfiguredObject.TYPE)).thenReturn(DEFAULT_TYPE);
+ final LegacyConfiguredObject convertedResult = mock(LegacyConfiguredObject.class);
+ when(_nextVersionManagementController.get(eq(_root),
+ eq(TEST_CATEGORY),
+ eq(path),
+ eq(Collections.emptyMap()))).thenReturn(result);
+ when(_typeController.convertFromNextVersion(result)).thenReturn(convertedResult);
+
+
+ final Object operationValue = "testValue";
+ final ManagementResponse operationResult = new ControllerManagementResponse(ResponseType.DATA, operationValue);
+ when(convertedResult.invoke(operationName, operationParameters, true)).thenReturn(operationResult);
+ final ManagementResponse response =
+ _controller.invoke(_root, path, operationName, operationParameters, true, true);
+ assertThat(response, is(notNullValue()));
+ assertThat(response.getResponseCode(), is(equalTo(200)));
+ assertThat(response.getBody(), is(equalTo(operationValue)));
+ verify(_nextVersionManagementController).get(_root, TEST_CATEGORY, path, Collections.emptyMap());
+ verify(convertedResult).invoke(operationName, operationParameters, true);
+ }
+
+ @Test
+ public void getPreferences()
+ {
+ final List<String> path = Arrays.asList("test1", "test2");
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("testParam", Collections.singletonList("testValue"));
+
+ final Object result = mock(Object.class);
+ when(_nextVersionManagementController.getPreferences(_root,
+ TEST_CATEGORY,
+ path,
+ parameters)).thenReturn(result);
+
+ final Object preferences = _controller.getPreferences(_root, path, parameters);
+ assertThat(preferences, is(equalTo(result)));
+ verify(_nextVersionManagementController).getPreferences(_root, TEST_CATEGORY, path, parameters);
+ }
+
+ @Test
+ public void setPreferences()
+ {
+ final List<String> path = Arrays.asList("test1", "test2");
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("testParam", Collections.singletonList("testValue"));
+
+ final Object preferences = mock(Object.class);
+ _controller.setPreferences(_root, path, preferences, parameters, true);
+
+ verify(_nextVersionManagementController).setPreferences(_root,
+ TEST_CATEGORY,
+ path,
+ preferences,
+ parameters,
+ true);
+ }
+
+ @Test
+ public void deletePreferences()
+ {
+ final List<String> path = Arrays.asList("test1", "test2");
+ final Map<String, List<String>> parameters =
+ Collections.singletonMap("testParam", Collections.singletonList("testValue"));
+
+ _controller.deletePreferences(_root, path, parameters);
+
+ verify(_nextVersionManagementController).deletePreferences(_root, TEST_CATEGORY, path, parameters);
+ }
+
+ @Test
+ public void getNextVersionManagementController()
+ {
+ assertThat(_controller.getNextVersionManagementController(), is(equalTo(_nextVersionManagementController)));
+ }
+
+ @Test
+ public void convertAttributesToNextVersion()
+ {
+ final List<String> path = Arrays.asList("test1", "test2");
+ final Map<String, Object> attributes = Collections.singletonMap("testParam", "testValue");
+ final Map<String, Object> convertedAttributes = Collections.singletonMap("testParam", "testValue2");
+
+ when(_typeController.convertAttributesToNextVersion(_root, path, attributes)).thenReturn(convertedAttributes);
+ final Map<String, Object> converted = _controller.convertAttributesToNextVersion(_root, path, attributes);
+ assertThat(converted, is(equalTo(convertedAttributes)));
+ }
+}
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/GenericLegacyConfiguredObjectTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/GenericLegacyConfiguredObjectTest.java
new file mode 100644
index 0000000..b55a1f2
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/GenericLegacyConfiguredObjectTest.java
@@ -0,0 +1,212 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.ResponseType;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class GenericLegacyConfiguredObjectTest extends UnitTestBase
+{
+
+ private GenericLegacyConfiguredObject _object;
+ private LegacyConfiguredObject _nextVersionLegacyConfiguredObject;
+ private static final String CATEGORY = "testCategory";
+ private LegacyManagementController _managementController;
+
+ @Before
+ public void setUp()
+ {
+ _managementController = mock(LegacyManagementController.class);
+ _nextVersionLegacyConfiguredObject = mock(LegacyConfiguredObject.class);
+
+ _object = new GenericLegacyConfiguredObject(_managementController,
+ _nextVersionLegacyConfiguredObject,
+ CATEGORY);
+ }
+
+ @Test
+ public void getAttributeNames()
+ {
+ final Collection<String> attributeNames = Arrays.asList("foo", "bar", "test");
+ when(_nextVersionLegacyConfiguredObject.getAttributeNames()).thenReturn(attributeNames);
+ Collection<String> names = _object.getAttributeNames();
+
+ assertThat(names, is(equalTo(attributeNames)));
+ verify(_nextVersionLegacyConfiguredObject).getAttributeNames();
+ }
+
+ @Test
+ public void getAttribute()
+ {
+ final String attributeName = "name";
+ final String attributeValue = "test";
+
+ when(_nextVersionLegacyConfiguredObject.getAttribute(attributeName)).thenReturn(attributeValue);
+ final Object value = _object.getAttribute(attributeName);
+
+ assertThat(value, is(equalTo(attributeValue)));
+ verify(_nextVersionLegacyConfiguredObject).getAttribute(attributeName);
+ }
+
+ @Test
+ public void getActualAttribute()
+ {
+ final String attributeName = "name";
+ final String attributeValue = "test";
+
+ when(_nextVersionLegacyConfiguredObject.getActualAttribute(attributeName)).thenReturn(attributeValue);
+ final Object value = _object.getActualAttribute(attributeName);
+
+ assertThat(value, is(equalTo(attributeValue)));
+ verify(_nextVersionLegacyConfiguredObject).getActualAttribute(attributeName);
+ }
+
+ @Test
+ public void getChildren()
+ {
+ final String childrenCategory = "testChildrenCategory";
+
+ final LegacyConfiguredObject child = mock(LegacyConfiguredObject.class);
+ final Collection<LegacyConfiguredObject> children = Collections.singleton(child);
+ when(_nextVersionLegacyConfiguredObject.getChildren(childrenCategory)).thenReturn(children);
+ final LegacyConfiguredObject converted = mock(LegacyConfiguredObject.class);
+ when(_managementController.convertFromNextVersion(child)).thenReturn(converted);
+ final Collection<LegacyConfiguredObject> value = _object.getChildren(childrenCategory);
+
+ assertThat(value.size(), is(equalTo(1)));
+ final LegacyConfiguredObject convertedChild = value.iterator().next();
+ assertThat(convertedChild, is(equalTo(converted)));
+ verify(_nextVersionLegacyConfiguredObject).getChildren(childrenCategory);
+ verify(_managementController).convertFromNextVersion(child);
+ }
+
+ @Test
+ public void getCategory()
+ {
+ assertThat(_object.getCategory(), is(equalTo(CATEGORY)));
+ }
+
+ @Test
+ public void invoke()
+ {
+ final String operationName = "testOperation";
+ final Map<String, Object> operationArguments = Collections.singletonMap("arg", "argValue");
+ final String operationResult = "testOperationResult";
+ final ControllerManagementResponse managementResponse = new ControllerManagementResponse(
+ ResponseType.DATA, operationResult);
+ when(_nextVersionLegacyConfiguredObject.invoke(operationName,
+ operationArguments,
+ true)).thenReturn(managementResponse);
+
+ final ManagementResponse result =
+ _object.invoke(operationName, operationArguments, true);
+
+ assertThat(result, is(notNullValue()));
+ assertThat(result.getResponseCode(), is(equalTo(200)));
+ assertThat(result.getBody(), is(equalTo(operationResult)));
+ }
+
+ @Test
+ public void getNextVersionConfiguredObject()
+ {
+ assertThat(_object.getNextVersionConfiguredObject(), is(equalTo(_nextVersionLegacyConfiguredObject)));
+ }
+
+ @Test
+ public void getParent()
+ {
+ final String parentCategory = "testParentCategory";
+ final LegacyConfiguredObject nextVersionParent = mock(LegacyConfiguredObject.class);
+ final LegacyConfiguredObject nextVersionParentConverted = mock(LegacyConfiguredObject.class);
+ when(_nextVersionLegacyConfiguredObject.getParent(parentCategory)).thenReturn(nextVersionParent);
+ when(_managementController.convertFromNextVersion(nextVersionParent)).thenReturn(
+ nextVersionParentConverted);
+ final LegacyConfiguredObject parent = _object.getParent(parentCategory);
+ assertThat(parent, is(equalTo(nextVersionParentConverted)));
+ verify(_nextVersionLegacyConfiguredObject).getParent(parentCategory);
+ }
+
+ @Test
+ public void isSecureAttribute()
+ {
+ final String attributeName = "testAttribute";
+ when(_nextVersionLegacyConfiguredObject.isSecureAttribute(attributeName)).thenReturn(true);
+ assertThat(_object.isSecureAttribute(attributeName), is(equalTo(true)));
+ verify(_nextVersionLegacyConfiguredObject).isSecureAttribute(attributeName);
+ }
+
+ @Test
+ public void isOversizedAttribute()
+ {
+ final String attributeName = "testAttribute";
+ when(_nextVersionLegacyConfiguredObject.isOversizedAttribute(attributeName)).thenReturn(true);
+ assertThat(_object.isOversizedAttribute(attributeName), is(equalTo(true)));
+ verify(_nextVersionLegacyConfiguredObject).isOversizedAttribute(attributeName);
+ }
+
+ @Test
+ public void getContextValue()
+ {
+ final String contextName = "testContext";
+ final String contextValue = "testValue";
+ when(_nextVersionLegacyConfiguredObject.getContextValue(contextName)).thenReturn(contextValue);
+ assertThat(_object.getContextValue(contextName), is(equalTo(contextValue)));
+ verify(_nextVersionLegacyConfiguredObject).getContextValue(contextName);
+ }
+
+ @Test
+ public void getStatistics()
+ {
+ Map<String, Object> stats = Collections.singletonMap("testStat", "statValue");
+ when(_nextVersionLegacyConfiguredObject.getStatistics()).thenReturn(stats);
+ assertThat(_object.getStatistics(), is(equalTo(stats)));
+ verify(_nextVersionLegacyConfiguredObject).getStatistics();
+ }
+
+ @Test
+ public void getManagementController()
+ {
+ assertThat(_object.getManagementController(), is(equalTo(_managementController)));
+ }
+
+ @Test
+ public void getNextVersionLegacyConfiguredObject()
+ {
+ assertThat(_object.getNextVersionConfiguredObject(), is(equalTo(_nextVersionLegacyConfiguredObject)));
+ }
+}
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/latest/LatestManagementControllerAdapterTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/latest/LatestManagementControllerAdapterTest.java
new file mode 100644
index 0000000..aede511
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/latest/LatestManagementControllerAdapterTest.java
@@ -0,0 +1,395 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.latest;
+
+import static org.apache.qpid.server.management.plugin.HttpManagementConfiguration.PREFERENCE_OPERTAION_TIMEOUT_CONTEXT_NAME;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementRequest;
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.BrokerTestHelper;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.server.virtualhost.QueueManagingVirtualHost;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class LatestManagementControllerAdapterTest extends UnitTestBase
+{
+ private LatestManagementControllerAdapter _adapter;
+
+ @Before
+ public void setUp()
+ {
+ final HttpManagementConfiguration<?> httpManagement = mock(HttpManagementConfiguration.class);
+ when(httpManagement.getContextValue(Long.class, PREFERENCE_OPERTAION_TIMEOUT_CONTEXT_NAME)).thenReturn(1000L);
+ final ManagementController managementController = new LatestManagementController(httpManagement);
+ when(managementController.getVersion()).thenReturn(BrokerModel.MODEL_VERSION);
+ _adapter = new LatestManagementControllerAdapter(managementController);
+ }
+
+ @Test
+ public void getVersion()
+ {
+ assertThat(_adapter.getVersion(), is(equalTo(BrokerModel.MODEL_VERSION)));
+ }
+
+ @Test
+ public void getCategories()
+ {
+ assertThat(_adapter.getCategories(), is(equalTo(BrokerModel.getInstance()
+ .getSupportedCategories()
+ .stream()
+ .map(Class::getSimpleName)
+ .collect(Collectors.toSet()))));
+ }
+
+ @Test
+ public void getCategoryMapping()
+ {
+ assertThat(_adapter.getCategoryMapping("foo"),
+ is(equalTo(String.format("/api/v%s/%s/", BrokerModel.MODEL_VERSION, "foo"))));
+ }
+
+ @Test
+ public void getCategory()
+ {
+ final ConfiguredObject<?> object = mock(ConfiguredObject.class);
+ doReturn(Broker.class).when(object).getCategoryClass();
+ assertThat(_adapter.getCategory(object), is(equalTo(Broker.class.getSimpleName())));
+ }
+
+ @Test
+ public void getCategoryHierarchy()
+ {
+ final Broker<?> object = BrokerTestHelper.createBrokerMock();
+ final Collection<String> expected = Arrays.asList("VirtualHostNode", "VirtualHost", "Queue");
+ assertThat(_adapter.getCategoryHierarchy(object, "Queue"), is(equalTo(expected)));
+ }
+
+ @Test
+ public void handleGet() throws Exception
+ {
+ final String hostName = "test";
+ final String queueName = "foo";
+
+ final QueueManagingVirtualHost<?> virtualHost = createTestVirtualHost(hostName);
+ virtualHost.createChild(Queue.class, Collections.singletonMap(Queue.NAME, queueName));
+
+ final String nodeName = virtualHost.getParent().getName();
+ final ManagementRequest request = mockManagementRequest(virtualHost.getBroker(),
+ "GET",
+ "queue",
+ Arrays.asList(nodeName, hostName),
+ Collections.singletonMap("name",
+ Collections.singletonList("foo")));
+
+ final ManagementResponse response = _adapter.handleGet(request);
+ assertThat(response, is(notNullValue()));
+ assertThat(response.getResponseCode(), is(equalTo(200)));
+ assertThat(response.getBody(), is(notNullValue()));
+ assertThat(response.getBody(), is(instanceOf(Collection.class)));
+
+ final Collection data = (Collection) response.getBody();
+ assertThat(data.size(), is(equalTo(1)));
+
+ final Object object = data.iterator().next();
+ assertThat(object, is(notNullValue()));
+ assertThat(object, is(instanceOf(LegacyConfiguredObject.class)));
+ assertThat(((LegacyConfiguredObject) object).getAttribute(LegacyConfiguredObject.NAME), is(equalTo("foo")));
+ }
+
+
+ @Test
+ public void handlePut() throws Exception
+ {
+ final String hostName = "test";
+ final String queueName = "foo";
+
+ final QueueManagingVirtualHost<?> virtualHost = createTestVirtualHost(hostName);
+ final String nodeName = virtualHost.getParent().getName();
+ final Broker root = virtualHost.getBroker();
+
+ final ManagementRequest request =
+ mockManagementRequest(root, "PUT", "queue", Arrays.asList(nodeName, hostName), Collections.emptyMap());
+
+ when(request.getBody(LinkedHashMap.class)).thenReturn(new LinkedHashMap<String, Object>(Collections.singletonMap(
+ "name",
+ queueName)));
+ when(request.getRequestURL()).thenReturn("test");
+
+ final ManagementResponse response = _adapter.handlePut(request);
+ assertThat(response, is(notNullValue()));
+ assertThat(response.getResponseCode(), is(equalTo(201)));
+ assertThat(response.getBody(), is(notNullValue()));
+ assertThat(response.getBody(), is(instanceOf(LegacyConfiguredObject.class)));
+
+ final LegacyConfiguredObject object = (LegacyConfiguredObject) response.getBody();
+ assertThat(object.getAttribute(LegacyConfiguredObject.NAME), is(equalTo("foo")));
+ }
+
+ @Test
+ public void handlePost() throws Exception
+ {
+ final String hostName = "test";
+ final String queueName = "foo";
+
+ final QueueManagingVirtualHost<?> virtualHost = createTestVirtualHost(hostName);
+ final String nodeName = virtualHost.getParent().getName();
+ final Broker root = virtualHost.getBroker();
+
+ final ManagementRequest request =
+ mockManagementRequest(root, "POST", "queue", Arrays.asList(nodeName, hostName), Collections.emptyMap());
+
+ when(request.getBody(LinkedHashMap.class)).thenReturn(new LinkedHashMap<String, Object>(Collections.singletonMap(
+ "name",
+ queueName)));
+ when(request.getRequestURL()).thenReturn("test");
+
+ final ManagementResponse response = _adapter.handlePut(request);
+ assertThat(response, is(notNullValue()));
+ assertThat(response.getResponseCode(), is(equalTo(201)));
+ assertThat(response.getBody(), is(notNullValue()));
+ assertThat(response.getBody(), is(instanceOf(LegacyConfiguredObject.class)));
+
+ final LegacyConfiguredObject object = (LegacyConfiguredObject) response.getBody();
+ assertThat(object.getAttribute(LegacyConfiguredObject.NAME), is(equalTo("foo")));
+ }
+
+ @Test
+ public void handleDelete() throws Exception
+ {
+ final String hostName = "test";
+ final String queueName = "foo";
+
+ final QueueManagingVirtualHost<?> virtualHost = createTestVirtualHost(hostName);
+ virtualHost.createChild(Queue.class, Collections.singletonMap(Queue.NAME, queueName));
+ assertThat(virtualHost.getQueueCount(), is(equalTo(1L)));
+
+ final String nodeName = virtualHost.getParent().getName();
+ final ManagementRequest request = mockManagementRequest(virtualHost.getBroker(),
+ "DELETE",
+ "queue",
+ Arrays.asList(nodeName, hostName),
+ Collections.singletonMap("name",
+ Collections.singletonList("foo")));
+ final ManagementResponse response = _adapter.handleDelete(request);
+ assertThat(response, is(notNullValue()));
+ assertThat(response.getResponseCode(), is(equalTo(200)));
+ assertThat(virtualHost.getQueueCount(), is(equalTo(0L)));
+ }
+
+ @Test
+ public void get() throws Exception
+ {
+ final String hostName = "test";
+ final String queueName = "foo";
+
+ final QueueManagingVirtualHost<?> virtualHost = createTestVirtualHost(hostName);
+ virtualHost.createChild(Queue.class, Collections.singletonMap(Queue.NAME, queueName));
+
+ final String nodeName = virtualHost.getParent().getName();
+
+ final Object response = _adapter.get(virtualHost.getBroker(), "queue", Arrays.asList(nodeName, hostName),
+ Collections.singletonMap("name",
+ Collections.singletonList("foo")));
+ assertThat(response, is(instanceOf(Collection.class)));
+
+ final Collection data = (Collection) response;
+ assertThat(data.size(), is(equalTo(1)));
+
+ final Object object = data.iterator().next();
+ assertThat(object, is(notNullValue()));
+ assertThat(object, is(instanceOf(LegacyConfiguredObject.class)));
+ assertThat(((LegacyConfiguredObject) object).getAttribute(LegacyConfiguredObject.NAME), is(equalTo("foo")));
+ }
+
+ @Test
+ public void createOrUpdate() throws Exception
+ {
+ final String hostName = "test";
+ final String queueName = "foo";
+
+ final QueueManagingVirtualHost<?> virtualHost = createTestVirtualHost(hostName);
+ final String nodeName = virtualHost.getParent().getName();
+ final Broker root = virtualHost.getBroker();
+
+ final ManagementRequest request =
+ mockManagementRequest(root, "POST", "queue", Arrays.asList(nodeName, hostName), Collections.emptyMap());
+
+ when(request.getBody(LinkedHashMap.class)).thenReturn(new LinkedHashMap<String, Object>(Collections.singletonMap(
+ "name",
+ queueName)));
+ when(request.getRequestURL()).thenReturn("test");
+
+ final Object response = _adapter.createOrUpdate(virtualHost.getBroker(),
+ "queue",
+ Arrays.asList(nodeName, hostName),
+ Collections.singletonMap("name", queueName),
+ true);
+ assertThat(response, is(instanceOf(LegacyConfiguredObject.class)));
+
+ final LegacyConfiguredObject object = (LegacyConfiguredObject) response;
+ assertThat(object.getAttribute(LegacyConfiguredObject.NAME), is(equalTo(queueName)));
+ }
+
+ @Test
+ public void delete() throws Exception
+ {
+ final String hostName = "test";
+ final String queueName = "foo";
+
+ final QueueManagingVirtualHost<?> virtualHost = createTestVirtualHost(hostName);
+ virtualHost.createChild(Queue.class, Collections.singletonMap(Queue.NAME, queueName));
+ assertThat(virtualHost.getQueueCount(), is(equalTo(1L)));
+
+ final String nodeName = virtualHost.getParent().getName();
+
+ _adapter.delete(virtualHost.getBroker(),
+ "queue",
+ Arrays.asList(nodeName, hostName, queueName),
+ Collections.emptyMap());
+
+ assertThat(virtualHost.getQueueCount(), is(equalTo(0L)));
+ }
+
+ @Test
+ public void invoke() throws Exception
+ {
+ final String hostName = "test";
+ final String queueName = "foo";
+
+ final QueueManagingVirtualHost<?> virtualHost = createTestVirtualHost(hostName);
+ Queue queue = virtualHost.createChild(Queue.class, Collections.singletonMap(Queue.NAME, queueName));
+ assertThat(virtualHost.getQueueCount(), is(equalTo(1L)));
+
+ List<String> path = Arrays.asList(virtualHost.getParent().getName(), hostName);
+
+ Map<String, Object> message = new HashMap<>();
+ message.put("address", "foo");
+ message.put("persistent", "false");
+ message.put("content", "Test Content");
+ message.put("mimeType", "text/plain");
+ ManagementResponse response = _adapter.invoke(virtualHost.getBroker(),
+ "virtualhost",
+ path,
+ "publishMessage",
+ Collections.singletonMap("message", message),
+ true,
+ true);
+
+ assertThat(response, is(notNullValue()));
+ assertThat(response.getResponseCode(), is(equalTo(200)));
+ Object body = response.getBody();
+ assertThat(body, is(instanceOf(Number.class)));
+ assertThat(((Number) body).intValue(), is(equalTo(1)));
+ assertThat(queue.getQueueDepthMessages(), is(equalTo(1)));
+ }
+
+ @Test
+ public void formatConfiguredObject() throws Exception
+ {
+ final String hostName = "test";
+ final QueueManagingVirtualHost<?> virtualHost = createTestVirtualHost(hostName);
+ final String queueName = "foo";
+ virtualHost.createChild(Queue.class, Collections.singletonMap(Queue.NAME, queueName));
+ assertThat(virtualHost.getQueueCount(), is(equalTo(1L)));
+
+ final Object formatted = _adapter.formatConfiguredObject(virtualHost,
+ Collections.singletonMap("depth",
+ Collections.singletonList(
+ "1")),
+ true);
+ assertThat(formatted, is(notNullValue()));
+ assertThat(formatted, is(instanceOf(Map.class)));
+
+ final Map<?, ?> data = (Map<?, ?>) formatted;
+ assertThat(data.get(VirtualHost.NAME), is(equalTo(hostName)));
+ final Object queues = data.get("queues");
+ assertThat(queues, is(notNullValue()));
+ assertThat(queues, is(instanceOf(Collection.class)));
+
+ final Collection<?> queueCollection = (Collection<?>) queues;
+
+ assertThat(queueCollection.size(), is(equalTo(1)));
+ final Iterator<?> iterator = queueCollection.iterator();
+ final Object queue1 = iterator.next();
+
+ assertThat(queue1, is(instanceOf(Map.class)));
+
+ final Map<?, ?> queueMap1 = (Map<?, ?>) queue1;
+
+ assertThat(queueMap1.get(Queue.NAME), is(equalTo("foo")));
+ }
+
+
+ private QueueManagingVirtualHost<?> createTestVirtualHost(final String hostName) throws Exception
+ {
+ final QueueManagingVirtualHost<?> virtualHost = BrokerTestHelper.createVirtualHost(hostName, this);
+ final Broker root = virtualHost.getBroker();
+ final ConfiguredObject<?> virtualHostNode = virtualHost.getParent();
+ when(root.getChildren(VirtualHostNode.class)).thenReturn(Collections.singletonList(virtualHostNode));
+ when(virtualHostNode.getChildren(VirtualHost.class)).thenReturn(Collections.singletonList(virtualHost));
+ when(virtualHostNode.getChildByName(VirtualHost.class, hostName)).thenReturn(virtualHost);
+ return virtualHost;
+ }
+
+ private ManagementRequest mockManagementRequest(ConfiguredObject<?> root,
+ String method,
+ String category,
+ List<String> path,
+ Map<String, List<String>> parameters)
+ {
+ final ManagementRequest request = mock(ManagementRequest.class);
+ when(request.getCategory()).thenReturn(category);
+ doReturn(root).when(request).getRoot();
+ when(request.getPath()).thenReturn(path);
+ when(request.getParameters()).thenReturn(parameters);
+ when(request.getMethod()).thenReturn(method);
+ return request;
+ }
+}
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v7_0/LegacyManagementControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v7_0/LegacyManagementControllerTest.java
new file mode 100644
index 0000000..8c7c378
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v7_0/LegacyManagementControllerTest.java
@@ -0,0 +1,105 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.v7_0;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class LegacyManagementControllerTest extends UnitTestBase
+{
+ private LegacyManagementController _controller;
+
+ @Before
+ public void setUp()
+ {
+ final ManagementController nextVersionManagementController = mock(ManagementController.class);
+ _controller = new LegacyManagementController(nextVersionManagementController);
+ _controller.initialize();
+ }
+
+ @Test
+ public void convertQueryParameters()
+ {
+ final Map<String, List<String>> parameters = Collections.singletonMap("depth", Collections.singletonList("1"));
+ final Map<String, List<String>> converted = _controller.convertQueryParameters(parameters);
+ assertThat(converted, is(equalTo(parameters)));
+ }
+
+ @Test
+ public void formatConfiguredObject()
+ {
+ final String objectName = "test-object";
+ final String hostName = "test-vhn";
+ final Map<String, List<String>> parameters = Collections.singletonMap("depth", Collections.singletonList("1"));
+ final LegacyConfiguredObject object = mock(LegacyConfiguredObject.class);
+ final LegacyConfiguredObject vhn = mock(LegacyConfiguredObject.class);
+ when(object.getAttributeNames()).thenReturn(Arrays.asList(LegacyConfiguredObject.NAME,
+ LegacyConfiguredObject.TYPE));
+ when(object.getAttribute(LegacyConfiguredObject.NAME)).thenReturn(objectName);
+ when(object.getAttribute(LegacyConfiguredObject.TYPE)).thenReturn("Broker");
+ when(object.getCategory()).thenReturn("Broker");
+ when(object.getChildren("VirtualHostNode")).thenReturn(Collections.singletonList(vhn));
+ when(vhn.getAttributeNames()).thenReturn(Arrays.asList(LegacyConfiguredObject.NAME,
+ LegacyConfiguredObject.TYPE));
+ when(vhn.getAttribute(LegacyConfiguredObject.NAME)).thenReturn(hostName);
+ when(vhn.getAttribute(LegacyConfiguredObject.TYPE)).thenReturn("VirtualHostNode");
+ when(vhn.getCategory()).thenReturn("VirtualHostNode");
+
+ Object data = _controller.formatConfiguredObject(object, parameters, true);
+
+ assertThat(data, is(instanceOf(Map.class)));
+ Map<?, ?> formatted = (Map<?, ?>) data;
+
+ assertThat(formatted.get(LegacyConfiguredObject.NAME), is(equalTo(objectName)));
+ assertThat(formatted.get(LegacyConfiguredObject.TYPE), is(equalTo("Broker")));
+
+ Object vhns = formatted.get("virtualhostnodes");
+ assertThat(vhns, is(instanceOf(Collection.class)));
+
+ Collection<?> nodes = (Collection<?>)vhns;
+
+ assertThat(nodes.size(), is(equalTo(1)));
+
+ Object node = nodes.iterator().next();
+ assertThat(node, is(instanceOf(Map.class)));
+ Map<?, ?> formattedNode = (Map<?, ?>) node;
+
+ assertThat(formattedNode.get(LegacyConfiguredObject.NAME), is(equalTo(hostName)));
+ assertThat(formattedNode.get(LegacyConfiguredObject.TYPE), is(equalTo("VirtualHostNode")));
+ }
+}
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/ContainerControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/ContainerControllerTest.java
new file mode 100644
index 0000000..896d41b
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/ContainerControllerTest.java
@@ -0,0 +1,83 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.v7_0.category;
+
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.controller.CategoryController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class ContainerControllerTest extends UnitTestBase
+{
+ private LegacyCategoryControllerFactory _factory;
+ private LegacyManagementController _nextVersionManagementController;
+ private String MODEL_VERSION = "7.0";
+
+ @Before
+ public void setUp()
+ {
+ _nextVersionManagementController = mock(LegacyManagementController.class);
+ when(_nextVersionManagementController.getVersion()).thenReturn(MODEL_VERSION);
+ _factory = new LegacyCategoryControllerFactory();
+ }
+
+ @Test
+ public void convertNextVersionBrokerConfiguredObject()
+ {
+ final CategoryController controller =
+ _factory.createController("Broker", _nextVersionManagementController);
+
+ assertThat(controller.getCategory(), is(equalTo("Broker")));
+
+ final LegacyConfiguredObject object = mock(LegacyConfiguredObject.class);
+ when(object.getAttribute("modelVersion")).thenReturn("foo");
+ final LegacyConfiguredObject converted = controller.convertFromNextVersion(object);
+
+ Object modelVersion = converted.getAttribute("modelVersion");
+ assertThat(modelVersion, is(equalTo(MODEL_VERSION)));
+ }
+
+ @Test
+ public void convertNextVersionVirtualHostConfiguredObject()
+ {
+ final CategoryController controller =
+ _factory.createController("VirtualHost", _nextVersionManagementController);
+
+ assertThat(controller.getCategory(), is(equalTo("VirtualHost")));
+
+ final LegacyConfiguredObject object = mock(LegacyConfiguredObject.class);
+ when(object.getAttribute("modelVersion")).thenReturn("foo");
+ final LegacyConfiguredObject converted = controller.convertFromNextVersion(object);
+
+ Object modelVersion = converted.getAttribute("modelVersion");
+ assertThat(modelVersion, is(equalTo(MODEL_VERSION)));
+ }
+}
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/LegacyCategoryControllerFactoryTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/LegacyCategoryControllerFactoryTest.java
new file mode 100644
index 0000000..3964d2e
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v7_0/category/LegacyCategoryControllerFactoryTest.java
@@ -0,0 +1,58 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.qpid.server.management.plugin.controller.v7_0.category;
+
+import static org.apache.qpid.server.management.plugin.controller.v7_0.category.LegacyCategoryControllerFactory.SUPPORTED_CATEGORIES;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.CategoryController;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class LegacyCategoryControllerFactoryTest extends UnitTestBase
+{
+ private LegacyCategoryControllerFactory _factory;
+ private LegacyManagementController _nextVersionManagementController;
+
+ @Before
+ public void setUp()
+ {
+ _nextVersionManagementController = mock(LegacyManagementController.class);
+ _factory = new LegacyCategoryControllerFactory();
+ }
+
+ @Test
+ public void createController()
+ {
+ SUPPORTED_CATEGORIES.keySet().forEach(category-> {
+ final CategoryController controller =
+ _factory.createController(category, _nextVersionManagementController);
+ assertThat(controller.getCategory(), is(equalTo(category)));
+ });
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org