You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rg...@apache.org on 2016/11/23 08:05:59 UTC
svn commit: r1770932 - in /qpid/java/trunk:
broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/
systests/src/test/java/org/apache/qpid/systest/management/amqp/
Author: rgodfrey
Date: Wed Nov 23 08:05:59 2016
New Revision: 1770932
URL: http://svn.apache.org/viewvc?rev=1770932&view=rev
Log:
QPID-7533 : Implement QUERY operation
Added:
qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementInputConverter.java (with props)
Modified:
qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java
qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/management/amqp/AmqpManagementTest.java
Added: qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementInputConverter.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementInputConverter.java?rev=1770932&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementInputConverter.java (added)
+++ qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementInputConverter.java Wed Nov 23 08:05:59 2016
@@ -0,0 +1,155 @@
+/*
+ *
+ * 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.amqp;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+class ManagementInputConverter
+{
+ private final ManagementNode _managementNode;
+
+ ManagementInputConverter(final ManagementNode managementNode)
+ {
+ _managementNode = managementNode;
+ }
+
+ <T> T convert(Class<T> clazz, Object input)
+ {
+ if (input == null)
+ {
+ return null;
+ }
+ else
+ {
+ if (clazz.isAssignableFrom(input.getClass()))
+ {
+ return (T) input;
+ }
+ else
+ {
+ if (Number.class.isAssignableFrom(clazz))
+ {
+ if (input instanceof Number)
+ {
+ return convertToNumberClass(clazz, (Number) input);
+ }
+ else if (input instanceof String)
+ {
+ return convertToNumberClass(clazz, (String) input);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Do not know how to convert type " + input.getClass().getName() + " to a number");
+ }
+ }
+ else if(String.class == clazz)
+ {
+ return (T) input.toString();
+ }
+ else if(Collection.class.isAssignableFrom(clazz) || Map.class.isAssignableFrom(clazz))
+ {
+ ObjectMapper objectMapper = new ObjectMapper();
+ try
+ {
+ return objectMapper.readValue(input.toString(), clazz);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("Cannot convert String '"
+ + input.toString() + "' to a " + clazz.getSimpleName());
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Do not know how to convert to type " + clazz.getSimpleName());
+ }
+ }
+ }
+ }
+
+ private <N> N convertToNumberClass(final Class<N> clazz, final Number number)
+ {
+ if (clazz == Byte.class || clazz == Byte.TYPE)
+ {
+ return (N) new Byte(number.byteValue());
+ }
+ else if (clazz == Short.class || clazz == Short.TYPE)
+ {
+ return (N) new Short(number.shortValue());
+ }
+ else if (clazz == Integer.class || clazz == Integer.TYPE)
+ {
+ return (N) new Integer(number.intValue());
+ }
+ else if (clazz == Long.class || clazz == Long.TYPE)
+ {
+ return (N) new Long(number.longValue());
+ }
+ else if (clazz == Float.class || clazz == Float.TYPE)
+ {
+ return (N) new Float(number.floatValue());
+ }
+ else if (clazz == Double.class || clazz == Double.TYPE)
+ {
+ return (N) new Double(number.doubleValue());
+ }
+ else
+ {
+ throw new IllegalArgumentException("Do not know how to convert to type " + clazz.getSimpleName());
+ }
+ }
+
+ private <N> N convertToNumberClass(final Class<N> clazz, final String number)
+ {
+ if (clazz == Byte.class || clazz == Byte.TYPE)
+ {
+ return (N) Byte.valueOf(number);
+ }
+ else if (clazz == Short.class || clazz == Short.TYPE)
+ {
+ return (N) Short.valueOf(number);
+ }
+ else if (clazz == Integer.class || clazz == Integer.TYPE)
+ {
+ return (N) Integer.valueOf(number);
+ }
+ else if (clazz == Long.class || clazz == Long.TYPE)
+ {
+ return (N) Long.valueOf(number);
+ }
+ else if (clazz == Float.class || clazz == Float.TYPE)
+ {
+ return (N) Float.valueOf(number);
+ }
+ else if (clazz == Double.class || clazz == Double.TYPE)
+ {
+ return (N) Double.valueOf(number);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Do not know how to convert to type " + clazz.getSimpleName());
+ }
+ }
+}
Propchange: qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementInputConverter.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java?rev=1770932&r1=1770931&r2=1770932&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java (original)
+++ qpid/java/trunk/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java Wed Nov 23 08:05:59 2016
@@ -162,6 +162,8 @@ class ManagementNode implements MessageS
private final ManagementOutputConverter _managementOutputConverter;
+ private final ManagementInputConverter _managementInputConverter;
+
ManagementNode(final NamedAddressSpace addressSpace,
final ConfiguredObject<?> configuredObject)
{
@@ -174,6 +176,8 @@ class ManagementNode implements MessageS
populateMetaData();
_managementOutputConverter = new ManagementOutputConverter(this);
+ _managementInputConverter = new ManagementInputConverter(this);
+
_configuredObjectFinder = new ConfiguredObjectFinder(configuredObject);
}
@@ -1033,10 +1037,32 @@ class ManagementNode implements MessageS
private Map<?, ?> performQuery(final Map<String, Object> headerMap, final Map messageBody)
{
- List<String> attributeNames = (List<String>) messageBody.get(ATTRIBUTE_NAMES);
+
+ List<Object> attributeNameObjects = _managementInputConverter.convert(List.class, messageBody.get(ATTRIBUTE_NAMES));
+ List<String> attributeNames;
+ if(attributeNameObjects == null)
+ {
+ attributeNames = Collections.emptyList();
+ }
+ else
+ {
+ attributeNames = new ArrayList<>(attributeNameObjects.size());
+ for(Object nameObject : attributeNameObjects)
+ {
+ if(nameObject == null)
+ {
+ throw new IllegalArgumentException("All attribute names must be non-null");
+ }
+ else
+ {
+ attributeNames.add(nameObject.toString());
+ }
+ }
+ }
+
String entityType = (String)headerMap.get(ENTITY_TYPE_HEADER);
- if(attributeNames == null || attributeNames.isEmpty())
+ if(attributeNames.isEmpty())
{
attributeNames = generateAttributeNames(entityType);
}
@@ -1226,6 +1252,11 @@ class ManagementNode implements MessageS
{
Set<String> attrNameSet = new HashSet<>();
List<String> attributeNames = new ArrayList<>();
+ for(String standardAttribute : Arrays.asList(IDENTITY_ATTRIBUTE, TYPE_ATTRIBUTE, QPID_TYPE, OBJECT_PATH))
+ {
+ attrNameSet.add(standardAttribute);
+ attributeNames.add(standardAttribute);
+ }
final ConfiguredObjectTypeRegistry typeRegistry = _model.getTypeRegistry();
List<Class<? extends ConfiguredObject>> classes = new ArrayList<>();
@@ -1253,11 +1284,24 @@ class ManagementNode implements MessageS
{
for(String name : typeRegistry.getAttributeNames(clazz))
{
- if(attrNameSet.add(name))
+ if(!ConfiguredObject.ID.equals(name) && attrNameSet.add(name))
{
attributeNames.add(name);
}
}
+ final Class<? extends ConfiguredObject> category = ConfiguredObjectTypeRegistry.getCategory(clazz);
+ if(category != _managedObject.getCategoryClass()
+ && !isSyntheticChildClass(category))
+ {
+ for (Class<? extends ConfiguredObject> parentType : _model.getParentTypes(category))
+ {
+ if (parentType != _managedObject.getCategoryClass())
+ {
+ attributeNames.add(parentType.getSimpleName().toLowerCase());
+ }
+ }
+ }
+
}
return attributeNames;
Modified: qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/management/amqp/AmqpManagementTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/management/amqp/AmqpManagementTest.java?rev=1770932&r1=1770931&r2=1770932&view=diff
==============================================================================
--- qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/management/amqp/AmqpManagementTest.java (original)
+++ qpid/java/trunk/systests/src/test/java/org/apache/qpid/systest/management/amqp/AmqpManagementTest.java Wed Nov 23 08:05:59 2016
@@ -24,6 +24,7 @@ import static org.apache.qpid.server.mod
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import javax.jms.Connection;
@@ -126,8 +127,63 @@ public class AmqpManagementTest extends
Collections.list(responseMessage.getPropertyNames()).contains("statusCode"));
assertEquals("The response code did not indicate success", 200, responseMessage.getIntProperty("statusCode"));
assertTrue("The response was not a MapMessage", responseMessage instanceof MapMessage);
+ ArrayList resultMessageKeys = Collections.list(((MapMessage) responseMessage).getMapNames());
+ assertEquals("The response map has two entries", 2, resultMessageKeys.size());
+ assertTrue("The response map does not contain attribute names", resultMessageKeys.contains("attributeNames"));
+ assertTrue("The response map does not contain results ", resultMessageKeys.contains("results"));
+ Object attributeNames = ((MapMessage)responseMessage).getObject("attributeNames");
+ assertTrue("The attribute names are not a list", attributeNames instanceof Collection);
+ Collection attributeNamesCollection = (Collection)attributeNames;
+ assertTrue("The attribute names do not contain identity", attributeNamesCollection.contains("identity"));
+ assertTrue("The attribute names do not contain name", attributeNamesCollection.contains("name"));
+ assertTrue("The attribute names do not contain qpid-type", attributeNamesCollection.contains("qpid-type"));
+ // Now test filtering by type
+ message.setStringProperty("identity", "self");
+ message.setStringProperty("type", "org.amqp.management");
+ message.setStringProperty("operation", "QUERY");
+ message.setStringProperty("entityType", "org.apache.qpid.Exchange");
+
+ message.setObject("attributeNames", "[\"name\", \"identity\", \"type\"]");
+ message.setJMSReplyTo(_replyAddress);
+ _producer.send(message);
+
+ responseMessage = _consumer.receive(getReceiveTimeout());
+ assertNotNull("A response message was not sent", responseMessage);
+ assertEquals("The correlation id does not match the sent message's messageId", message.getJMSMessageID(), responseMessage.getJMSCorrelationID());
+ assertTrue("The response message does not have a status code",
+ Collections.list(responseMessage.getPropertyNames()).contains("statusCode"));
+ assertEquals("The response code did not indicate success", 200, responseMessage.getIntProperty("statusCode"));
+ assertTrue("The response was not a MapMessage", responseMessage instanceof MapMessage);
+ resultMessageKeys = Collections.list(((MapMessage) responseMessage).getMapNames());
+ assertEquals("The response map has two entries", 2, resultMessageKeys.size());
+ assertTrue("The response map does not contain attribute names", resultMessageKeys.contains("attributeNames"));
+ assertTrue("The response map does not contain results ", resultMessageKeys.contains("results"));
+ attributeNames = ((MapMessage)responseMessage).getObject("attributeNames");
+ assertTrue("The attribute names are not a list", attributeNames instanceof Collection);
+ attributeNamesCollection = (Collection)attributeNames;
+ assertEquals("The attributeNames are no as expected", Arrays.asList("name", "identity", "type"), attributeNamesCollection);
+ Object resultsObject = ((MapMessage) responseMessage).getObject("results");
+ assertTrue("results is not a collection", resultsObject instanceof Collection);
+ Collection results = (Collection)resultsObject;
+
+ final int numberOfExchanges = results.size();
+ assertTrue("results should have at least 4 elements", numberOfExchanges >= 4);
+
+ message.setStringProperty("identity", "self");
+ message.setStringProperty("type", "org.amqp.management");
+ message.setStringProperty("operation", "QUERY");
+ message.setStringProperty("entityType", "org.apache.qpid.DirectExchange");
+
+ message.setObject("attributeNames", "[\"name\", \"identity\", \"type\"]");
+ message.setJMSReplyTo(_replyAddress);
+ _producer.send(message);
+
+ responseMessage = _consumer.receive(getReceiveTimeout());
+ final Collection directExchanges = (Collection) ((MapMessage) responseMessage).getObject("results");
+ assertTrue("There are the same number of results when searching for direct exchanges as when searching for all exchanges", directExchanges.size() < numberOfExchanges);
+ assertTrue("The list of direct exchanges is not a proper subset of the list of all exchanges", results.containsAll(directExchanges));
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org