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