You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by fa...@apache.org on 2013/04/08 17:19:09 UTC

svn commit: r1465662 [21/26] - in /qpid/trunk/qpid/tools/src/java: ./ bin/ bin/qpid-web/ bin/qpid-web/authentication/ bin/qpid-web/web/ bin/qpid-web/web/itablet/ bin/qpid-web/web/itablet/css/ bin/qpid-web/web/itablet/images/ bin/qpid-web/web/itablet/im...

Added: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Broker.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Broker.java?rev=1465662&view=auto
==============================================================================
--- qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Broker.java (added)
+++ qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Broker.java Mon Apr  8 15:19:04 2013
@@ -0,0 +1,678 @@
+/*
+ *
+ * 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.qmf2.agentdata;
+
+// Misc Imports
+import java.util.Collections;
+import java.util.Map;
+
+// Simple Logging Facade 4 Java
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// QMF2 Imports
+import org.apache.qpid.qmf2.agent.Agent;
+import org.apache.qpid.qmf2.agent.QmfAgentData;
+import org.apache.qpid.qmf2.common.Handle;
+import org.apache.qpid.qmf2.common.ObjectId;
+import org.apache.qpid.qmf2.common.QmfData;
+/*import org.apache.qpid.qmf2.common.QmfEvent;
+import org.apache.qpid.qmf2.common.QmfEventListener;
+import org.apache.qpid.qmf2.common.QmfException;
+import org.apache.qpid.qmf2.common.QmfType;*/
+import org.apache.qpid.qmf2.common.SchemaEventClass;
+import org.apache.qpid.qmf2.common.SchemaMethod;
+import org.apache.qpid.qmf2.common.SchemaObjectClass;
+import org.apache.qpid.qmf2.common.SchemaProperty;
+
+// Java Broker model Imports
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+
+/**
+ * This class provides a concrete implementation of QmfAgentData for the Broker Management Object.
+ * In general it's possible to use QmfAgentData without sub-classing as it's really a "bean" style class
+ * that retains its properties in a Map, but in the case of the Java Broker Management Agent it's useful
+ * to sub-class as we need to map between the properties/statistics as specified in the Java Broker
+ * management model and those specified in qpid/spec/management-schema.xml which is what the C++ broker 
+ * uses. This class retains a reference to its peer org.apache.qpid.server.model.Broker and does the
+ * necessary mapping when its mapEncode() method is called (which is used to serialise the QmfAgentData).
+ *
+ * @author Fraser Adams
+ */
+public class Broker extends QmfAgentData
+{
+    private static final Logger _log = LoggerFactory.getLogger(Broker.class);
+
+    /**
+     * This static initialiser block initialises the QMF2 Schema information needed by the Agent to find
+     * QmfAgentData Objects of a given type.
+     */
+    private static final SchemaObjectClass _schema;
+    public static SchemaObjectClass getSchema()
+    {
+        return _schema;
+    }
+
+    static
+    {
+        // Declare the schema for the QMF2 broker class.
+        _schema = new SchemaObjectClass("org.apache.qpid.broker", "broker");
+
+        // TODO
+        //_schema.addProperty(new SchemaProperty("whatHappened", QmfType.TYPE_STRING));
+    }
+
+    private final org.apache.qpid.server.model.Broker _broker; // Passed in by Plugin bootstrapping.
+    private final String _defaultVirtualHost; // Pulled from the broker attributes.
+
+    /**
+     * This inner class parses the name String that was passed in as a QMF method argument.
+     * There are a few quirks with this name. In the first instance it may be prefixed with Virtual Host information
+     * e.g. [vhost:<vhost-name>/]<queue-name> this is because in order to allow Java Broker QMF to work with things like
+     * qpid-config which are not particularly Virtual Host aware prefixing the names seemed to be the most natural,
+     * if slightly ugly approach. In addition the way bindings are named is of the form:
+     * <exchange-name>/<queue-name>[/<binding-key>] so we need a mechanism to parse the relevant information.
+     * <p>
+     * N.B. the parsing that takes place in this class makes an assumption that there are no valid exchange or queue
+     * names that contain a "/". This is probably a reasonable assumption given the way that a binding name is
+     * constructed, but it's worth recording the restriction here in case such a beast crops up.
+     * <p>
+     * This class also provides accessors that allow the Exchange, Queue and Binding ConfiguredObjects for the
+     * name parsed in the Constructor to be retrieved. This is generally useful because although in QMF the create
+     * and delete methods are invoked on the Broker object in the Java Broker ConfiguredObject model the underlying
+     * methods are distributed across a number of different classes.
+     */
+    private class NameParser
+    {
+        private String _vhostName = _defaultVirtualHost;
+        private VirtualHost _vhost = null;
+        private String _exchangeName = "";
+        private Exchange _exchange = null;
+        private String _queueName = "";
+        private Queue _queue = null;
+        private String _bindingKey = "";
+        private Binding _binding = null;
+
+        /**
+         * NameParser Constructor.
+         * The Constructor actually does the majority of the parsing, the remaining method are largely just accessors.
+         *
+         * @param name the name argument that was retrieved from the QMF method inArgs. This will be the exchange name,
+         * the queue name or the binding name (which is of the form <exchange-name>/<queue-name>[/<binding-key>])
+         * exchange and queue names may be prefixed by a Virtual Host name e.g. [vhost:<vhost-name>/]<queue-name>
+         * @param type the type argument that was retrieved from the QMF method inArgs. Valid types are "exchange, 
+         * "queue" or "binding".
+         */
+        public NameParser(final String name, final String type)
+        {
+            boolean malformedVHostName = false;
+            String[] splitName = name.split("/"); // A slash is used as a separator in a couple of scenarios.
+            if (name.startsWith("vhost:"))
+            {
+                if (splitName.length == 1) // If it starts with vhost: the name should also contain at least one "/".
+                {
+                    malformedVHostName = true;
+                    _vhostName = name;
+                }
+                else
+                {
+                    _vhostName = splitName[0];
+                    _vhostName = _vhostName.substring(6, _vhostName.length());
+                }
+            }
+
+            // If the vhostName isn't malformed then try to find the actual Virtual Host that it relates to.
+            // If it is malformed the vhost stays set to null, which will cause an exception to be returned later.
+            if (!malformedVHostName)
+            {
+                for (VirtualHost vhost : _broker.getVirtualHosts())
+                {
+                    if (vhost.getName().equals(_vhostName))
+                    {
+                        _vhost = vhost;
+                        break;
+                    }
+                }
+            }
+
+            // Populate the exchange, queue and binding names. We only populate the names in the constructor
+            // when we actually want to find the Object associated with the name we do it "on demand" in the
+            // relevant accessor and cache the result.
+            if (type.equals("exchange"))
+            {
+                _exchangeName = splitName[splitName.length - 1];
+            }
+            else if (type.equals("queue"))
+            {
+                _queueName = splitName[splitName.length - 1];
+            }
+            else if (type.equals("binding"))
+            { // TODO is there a way to make this parse less nasty and a bit more elegant....
+                int i = 0;
+                String vhost1Name = _defaultVirtualHost; // The exchange and queue vhostName need to be the same.
+                if (splitName[i].startsWith("vhost:")) // Does the exchange name specify a vhost?
+                {
+                    vhost1Name = splitName[i];
+                    i++;
+                }
+
+                if (i < splitName.length) // Extract the exchange name sans vhost part.
+                {
+                    _exchangeName = splitName[i];
+                    i++;
+                }
+
+                String vhost2Name = _defaultVirtualHost;
+                if (i < splitName.length && splitName[i].startsWith("vhost:")) // Does the queue name specify a vhost?
+                {
+                    vhost2Name = splitName[i];
+                    i++;
+                }
+
+                // If the exchange and queue vhost names differ set _vhost and _vhostName to null which causes
+                // an exception that says "VirtualHost names for exchange and queue must match.".
+                if (!vhost2Name.equals(vhost1Name))
+                {
+                    _vhost = null;
+                    _vhostName = null;
+                }
+
+                if (i < splitName.length) // Extract the queue name sans vhost part.
+                {
+                    _queueName = splitName[i];
+                    i++;
+                }
+
+                if (i < splitName.length) // Extract the binding key if present (it's optional).
+                {
+                    _bindingKey = splitName[i];
+                    i++;
+                }
+            } // End of binding name parse.
+        }
+
+        // NameParser accessors.
+
+        /**
+         * Retrieves the name of the Virtual Host that was parsed from the name supplied in the Constructor.
+         * @return the parsed Virtual Host name (may be an empty String).
+         */
+        public String getVirtualHostName()
+        {
+            return _vhostName;
+        }
+
+        /**
+         * Retrieves the Virtual Host with the name that was parsed from the name supplied in the Constructor.
+         * @return the Virtual Host with the name that was parsed from the name supplied in the Constructor (may be null).
+         */
+        public VirtualHost getVirtualHost()
+        {
+            return _vhost;
+        }
+
+        /**
+         * Retrieves the name of the Exchange that was parsed from the name supplied in the Constructor.
+         * @return the parsed Exchange name (may be an empty String).
+         */
+        public String getExchangeName()
+        {
+            return _exchangeName;
+        }
+
+        /**
+         * Retrieves the Exchange with the name that was parsed from the name supplied in the Constructor.
+         * @return the Exchange with the name that was parsed from the name supplied in the Constructor (may be null).
+         */
+        public Exchange getExchange()
+        {
+            // If we've not previously cached the _exchange and the previously parsed Virtual Host isn't null we do a 
+            // look up for the actual Exchange with the name _exchangeName and cache it.
+            if (_exchange == null && _vhost != null)
+            {
+                for (Exchange exchange : _vhost.getExchanges())
+                {
+                    if (exchange.getName().equals(_exchangeName))
+                    {
+                        _exchange = exchange;
+                        break;
+                    }
+                }
+            }
+
+            return _exchange;
+        }
+
+        /**
+         * Retrieves the name of the Queue that was parsed from the name supplied in the Constructor.
+         * @return the parsed Queue name (may be an empty String).
+         */
+        public String getQueueName()
+        {
+            return _queueName;
+        }
+
+        /**
+         * Retrieves the Queue with the name that was parsed from the name supplied in the Constructor.
+         * @return the Queue with the name that was parsed from the name supplied in the Constructor (may be null).
+         */
+        public Queue getQueue()
+        {
+            // If we've not previously cached the _queue and the previously parsed Virtual Host isn't null we do a 
+            // look up for the actual Queue with the name _queueName and cache it.
+            if (_queue == null && _vhost != null)
+            {
+                for (Queue queue : _vhost.getQueues())
+                {
+                    if (queue.getName().equals(_queueName))
+                    {
+                        _queue = queue;
+                        break;
+                    }
+                }
+            }
+
+            return _queue;
+        }
+
+        /**
+         * Retrieves the name of the Binding that was parsed from the name supplied in the Constructor.
+         * @return the parsed Binding name (may be an empty String).
+         */
+        public String getBindingKey()
+        {
+            return _bindingKey;
+        }
+
+        /**
+         * Retrieves the Binding with the name that was parsed from the name supplied in the Constructor.
+         * @return the Binding with the name that was parsed from the name supplied in the Constructor (may be null).
+         */
+        public Binding getBinding()
+        {
+            // In order to retrieve a Binding it's first necessary to get the Exchange (or Queue) ConfiguredObject.
+            _exchange = getExchange(); // Need to get it via the accessor as it's initialised by lazy evaluation.
+
+            // If we've not previously cached the _binding and the previously retrieved Exchange isn't null we do a 
+            // look up for the actual Binding with the name _bindingKey and cache it.
+            if (_binding == null && _exchange != null)
+            {
+                for (Binding binding : _exchange.getBindings())
+                {
+                    if (binding.getName().equals(_bindingKey))
+                    {
+                        _binding = binding;
+                        break;
+                    }
+                }
+            }
+
+            return _binding;
+        }
+    } // End of class NameParser
+
+    /**
+     * Broker Constructor.
+     * @param broker the root Broker Management Object from which the other Management Objects may be obtained.
+     */
+    public Broker(final org.apache.qpid.server.model.Broker broker)
+    {
+        super(getSchema());
+        _broker = broker;
+        _defaultVirtualHost = (String)broker.getAttribute("defaultVirtualHost");
+        int amqpPort = 5672; // Default AMQP Port.
+
+        // Search through the available Ports on this Broker looking for the AMQP Port. When we find the
+        // AMQP Port we record that in amqpPort;
+        for (Port port : _broker.getPorts())
+        {
+            boolean isAMQP = false;
+            for (Protocol protocol : port.getProtocols())
+            {
+                isAMQP = protocol.isAMQP();
+                if (isAMQP)
+                {
+                    break;
+                }
+            }
+
+            if (isAMQP)
+            {
+                amqpPort = port.getPort();
+                break;
+            }
+        }
+
+        String port = "" + amqpPort;
+
+        // systemRef is ignored in this implementation.
+        // stagingThreshold is ignored in this implementation (it's deprecated anyway I believe).
+
+        // Use this name to be fairly consistent with C++ broker which uses "amqp-broker".
+        // N.B. although it's useful to be able to distinguish between C++ and Java brokers note that the
+        // _object_name in the ObjectId that we set below uses actually uses "amqp-broker" vice "amqp-java-broker",
+        // this is because qpid-config uses a "hardcoded" ObjectId to invoke methods so we need to use the same name.
+        setValue("name", "amqp-java-broker");
+        setValue("port", port);
+
+        // workerThreads doesn't *appear* to be configurable in the Java Broker, looks like there's no pool and the
+        // Threads just grow with the number of Connections?
+        setValue("workerThreads", 0);
+
+        // maxConns doesn't *appear* to be configurable in the Java Broker.
+        setValue("maxConns", 0);
+
+        // The Java Broker ServerSocket seems to be created in org.apache.qpid.transport.network.io.IoNetworkTransport
+        // In AcceptingThread. The does't appear to use any configuration for ServerSocket, which suggests that the
+        // backlog is the default value which is assumed to be 10.
+        setValue("connBacklog", 10);
+
+        // "Technically" this isn't quite the same as for the C++ broker, which pushes management data to a particular 
+        // topic - the subscription "qmf.default.topic/agent.ind.#" grabs that plus heartbeats for the C++ broker.
+        // This Agent allows the use of the QMF2 Query Subscriptions (which the C++ broker does not!! - the Console
+        // class fakes this client side for the C++ broker. TODO make sure that the Console does not fake for Java broker.
+        setValue("mgmtPublish", true);
+        setValue("mgmtPubInterval", 10);
+
+        setValue("version", org.apache.qpid.common.QpidProperties.getReleaseVersion());
+        setValue("dataDir", System.getProperty("QPID_WORK"));
+
+        // ObjectId needs to be set here in Broker because the QMF2 version of qpid-config uses a hardcoded
+        // _object_name of "org.apache.qpid.broker:broker:amqp-broker" in the _object_id that it sets.
+        // It *shouldn't* do this and should really use the _object_id of the broker object returned by
+        // getObjects("broker"), but it does. The following line causes the Agent to use the explicit
+        // ObjectId below rather than constructing its own, which fixes the qpid-config issue.
+        // Note we use "amqp-broker" in the ObjectId to be compatible with qpid-config but we set the actual
+        // name to "amqp-java-broker" as it's useful to be able to distinguish between C++ and Java Brokers.
+        setObjectId(new ObjectId("", "org.apache.qpid.broker:broker:amqp-broker", 0));
+    }
+
+    /**
+     * This helper method checks the supplied properties Map for the "alternate-exchange" property, if it is present
+     * the property is removed from the map and the alternate exchange is parsed to recover the Virtual Host name
+     * and the actual alternate exchange name. If the alternate exchange Virtual Host name is not the same as the
+     * supplied vhostName this method returns "invalid" otherwise it returns the alternate exchange name or null.
+     *
+     * @param vhostName the Virtual Host name that we want to compare the alternate exchange's Virtual Host name with.
+     * @param properties a Map of properties that might contain "alternate-exchange".
+     * @return the alternate exchange name if present, null if not present or "invalid" if the Virtual Host name that
+     * was parsed from the alternate exchange doesn't match the name supplied in the vhostName parameter.
+     */
+    private String parseAlternateExchange(String vhostName, Map<String, Object> properties)
+    {
+        String alternateExchange = null;
+        Object property = properties.get("alternate-exchange");
+        if (property != null && property instanceof String) // Alternate exchange has been specified.
+        {
+            alternateExchange = property.toString();
+            properties.remove("alternate-exchange");
+
+            String altExVhostName = _defaultVirtualHost;
+            String[] splitName = alternateExchange.split("/"); 
+            if (alternateExchange.startsWith("vhost:"))
+            {
+                altExVhostName = splitName[0];
+                altExVhostName = altExVhostName.substring(6, altExVhostName.length());
+            }
+
+            // If the Virtual Hosts differ raise an exception and return.
+            if (!altExVhostName.equals(vhostName))
+            {
+                return "invalid";
+            }
+        }
+
+        return alternateExchange;
+    }
+
+    /**
+     * This method acts as a single entry point for QMF methods invoked on the Broker Object.
+     *
+     * @param agent the org.apache.qpid.qmf2.agent.Agent instance that we call methodResponse() and raiseException() on.
+     * @param handle the reply handle used by methodResponse() and raiseException().
+     * @param methodName the name of the QMF method being invoked.
+     * @param inArgs a Map of input arguments wrapped in a QmfData Object.
+     */
+    public void invokeMethod(Agent agent, Handle handle, String methodName, QmfData inArgs)
+    {
+        if (methodName.equals("create") || methodName.equals("delete"))
+        {
+            QmfData outArgs = new QmfData();
+
+            String name = inArgs.getStringValue("name");
+            String type = inArgs.getStringValue("type");
+
+            NameParser nameParser = new NameParser(name, type);
+            String vhostName = nameParser.getVirtualHostName();
+            VirtualHost vhost = nameParser.getVirtualHost();
+
+            if (vhost == null)
+            {
+                if (vhostName == null)
+                {
+                    agent.raiseException(handle, "VirtualHost names for exchange and queue must match.");
+                }
+                else
+                {
+                    agent.raiseException(handle, "VirtualHost " + vhostName + " not found.");
+                }
+            }
+            else
+            {
+                if (methodName.equals("create")) // method = create
+                {
+                    try
+                    {
+                        //boolean strict = inArgs.getBooleanValue("strict");
+                        Map<String, Object> properties = inArgs.getValue("properties");
+
+                        boolean durable = false;
+                        Object property = properties.get("durable");
+                        if (property != null && property instanceof Boolean)
+                        {
+                            Boolean durableProperty = (Boolean)property;
+                            durable = durableProperty.booleanValue();
+                            properties.remove("durable");
+                        }
+
+                        if (type.equals("exchange")) // create exchange.
+                        {
+/*
+System.out.println("Create Exchange");
+System.out.println("vhostName = " + vhostName);
+System.out.println("exchange name = " + nameParser.getExchangeName());
+System.out.println("properties = " + properties);
+*/
+                            String exchangeType = "";
+                            property = properties.get("exchange-type");
+                            if (property != null && property instanceof String)
+                            {
+                                exchangeType = property.toString();
+                                properties.remove("exchange-type");
+                            }
+
+                            String alternateExchange = parseAlternateExchange(vhostName, properties);
+                            if (alternateExchange != null && alternateExchange.equals("invalid"))
+                            {
+                                agent.raiseException(handle, "Alternate Exchange must belong to the same Virtual Host as the Exchange being added.");
+                                return;
+                            }
+
+                            // TODO delete this block when adding an AlternateExchange is implemented.
+                            if (alternateExchange != null)
+                            {
+                                agent.raiseException(handle,
+                                    "Setting an Alternate Exchange on an Exchange is not yet implemented.");
+                                return;
+                            }
+
+                            // Note that for Qpid 0.20 the "qpid.msg_sequence=1" and "qpid.ive=1" properties are
+                            // not suppored, indeed no exchange properties seem to be supported yet.
+                            vhost.createExchange(nameParser.getExchangeName(), State.ACTIVE, durable,
+                                                 LifetimePolicy.PERMANENT, 0l, exchangeType, properties);
+                            if (alternateExchange != null)
+                            {
+                                // TODO set Alternate Exchange. There doesn't seem to be a way to do this yet!!!
+                            }
+                        } // End of create exchange.
+                        else if (type.equals("queue")) // create queue.
+                        {
+/*
+System.out.println("Create Queue");
+System.out.println("vhostName = " + vhostName);
+System.out.println("queue name = " + nameParser.getQueueName());
+System.out.println("properties = " + properties);
+*/
+
+                            // TODO Try to map from the QMF create queue properties to the closest equivalents on
+                            // the Java Broker. Unfortunately there are a *lot* of frustrating little differences.
+
+
+                            String alternateExchange = parseAlternateExchange(vhostName, properties);
+                            if (alternateExchange != null && alternateExchange.equals("invalid"))
+                            {
+                                agent.raiseException(handle, "Alternate Exchange must belong to the same Virtual Host as the Queue being added.");
+                                return;
+                            }
+
+                            // I don't *think* that it make sense to allow setting exclusive or autoDelete to
+                            // a queue created from config.
+                            Queue queue = vhost.createQueue(nameParser.getQueueName(), State.ACTIVE, durable, false,
+                                                            LifetimePolicy.PERMANENT, 0l, properties);
+
+                            // Set the queue's alternateExchange, which is just a little bit involved......
+                            // The queue.setAttribute() method needs an org.apache.qpid.server.model.Exchange instance
+                            // not just a name, so we look up org.apache.qpid.server.qmf2.agentdata.Exchange by ID
+                            // and get its associated org.apache.qpid.server.model.Exchange. We can do a look up by ID
+                            // because we needed to use ObjectIds that were based on names in order to allow qpid-config
+                            // to work, so we may as well make use of this convenience here too.
+                            if (alternateExchange != null)
+                            {
+                                ObjectId objectId =
+                                        new ObjectId("", "org.apache.qpid.broker:exchange:" + alternateExchange, 0);
+
+                                // Look up Exchange QmfAgentData by ObjectId from the Agent's internal Object store.
+                                QmfAgentData object = agent.getObject(objectId);
+                                if (object != null)
+                                {
+                                    org.apache.qpid.server.qmf2.agentdata.Exchange ex = 
+                                        (org.apache.qpid.server.qmf2.agentdata.Exchange)object;
+
+                                    Exchange altEx = ex.getExchange();
+                                    queue.setAttribute("alternateExchange", null, altEx);
+                                }
+                            }
+                        }
+                        else if (type.equals("binding")) // create binding.
+                        {
+                            Exchange exchange = nameParser.getExchange();
+                            if (exchange == null)
+                            {
+                                agent.raiseException(handle, "Cannot create binding on Exchange " +
+                                                     nameParser.getExchangeName());
+                                return;
+                            }
+                            else
+                            {
+                                Map<String, Object> attributes = Collections.emptyMap();
+                                exchange.createBinding(nameParser.getBindingKey(), nameParser.getQueue(),
+                                                       properties, attributes);
+                            }
+                        }
+
+                        agent.methodResponse(methodName, handle, outArgs, null);
+                    }
+                    catch (Exception e)
+                    {
+                        agent.raiseException(handle, e.getMessage());
+                    }
+                }
+                else // method = delete
+                {
+                    try
+                    {
+                        if (type.equals("exchange")) // delete exchange.
+                        {
+                            Exchange exchange = nameParser.getExchange();
+                            if (exchange != null)
+                            {
+                                exchange.delete();
+                            }
+                        }
+                        else if (type.equals("queue")) // delete queue.
+                        {
+                            Queue queue = nameParser.getQueue();
+                            if (queue != null)
+                            {
+                                queue.delete();
+                            }
+                        }
+                        else if (type.equals("binding")) // delete binding.
+                        {
+                            Binding binding = nameParser.getBinding();
+                            if (binding != null)
+                            {
+                                binding.delete();
+                            }
+                        }
+
+                        agent.methodResponse(methodName, handle, outArgs, null);
+                    }
+                    catch (Exception e)
+                    {
+                        agent.raiseException(handle, e.getMessage());
+                    }
+                }
+            }
+        }
+        else // If methodName is not create or delete.
+        {
+            agent.raiseException(handle, methodName + " not yet implemented on Broker.");
+        }
+    } // End of invokeMethod.
+
+    /**
+     * This method maps the org.apache.qpid.server.model.Broker to QMF2 broker properties where possible then
+     * serialises into the underlying Map for transmission via AMQP. This method is called by handleQueryRequest()
+     * in the org.apache.qpid.qmf2.agent.Agent class implementing the main QMF2 Agent behaviour.
+     * 
+     * @return the underlying map. 
+     */
+    @Override
+    public Map<String, Object> mapEncode()
+    {
+        update(); // Need to do update before setting uptime in order to get the latest getUpdateTime() value.
+
+        // Not sure if there's an "official" broker uptime anywhere, but as the QmfManagementAgent is created when
+        // the broker is and the Broker object is created then too the following approach should be good enough.
+        setValue("uptime", getUpdateTime() - getCreateTime());
+
+        return super.mapEncode();
+    }
+}

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Broker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Broker.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Connection.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Connection.java?rev=1465662&view=auto
==============================================================================
--- qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Connection.java (added)
+++ qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Connection.java Mon Apr  8 15:19:04 2013
@@ -0,0 +1,203 @@
+/*
+ *
+ * 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.qmf2.agentdata;
+
+// Misc Imports
+import java.util.Map;
+
+// Simple Logging Facade 4 Java
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// QMF2 Imports
+import org.apache.qpid.qmf2.agent.QmfAgentData;
+import org.apache.qpid.qmf2.common.QmfEvent;
+import org.apache.qpid.qmf2.common.SchemaEventClass;
+//import org.apache.qpid.qmf2.common.SchemaMethod;
+import org.apache.qpid.qmf2.common.SchemaObjectClass;
+//import org.apache.qpid.qmf2.common.SchemaProperty;
+
+
+/**
+ * This class provides a concrete implementation of QmfAgentData for the Connection Management Object.
+ * In general it's possible to use QmfAgentData without sub-classing as it's really a "bean" style class
+ * that retains its properties in a Map, but in the case of the Java Broker Management Agent it's useful
+ * to sub-class as we need to map between the properties/statistics as specified in the Java Broker
+ * management model and those specified in qpid/spec/management-schema.xml which is what the C++ broker 
+ * uses. This class retains a reference to its peer org.apache.qpid.server.model.Connection and does the
+ * necessary mapping when its mapEncode() method is called (which is used to serialise the QmfAgentData).
+ *
+ * @author Fraser Adams
+ */
+public class Connection extends QmfAgentData
+{
+    private static final Logger _log = LoggerFactory.getLogger(Connection.class);
+
+    /**
+     * This static initialiser block initialises the QMF2 Schema information needed by the Agent to find
+     * QmfAgentData and QmfEvent Objects of a given type.
+     */
+    private static final SchemaObjectClass _schema;
+    private static final SchemaEventClass _clientConnectSchema;
+    private static final SchemaEventClass _clientDisconnectSchema;
+
+    /**
+     * Returns the schema for the Connection class.
+     * @return the SchemaObjectClass for the Connection class.
+     */
+    public static SchemaObjectClass getSchema()
+    {
+        return _schema;
+    }
+
+    /**
+     * Returns the schema for the Client Connect Event.
+     * @return the SchemaEventClass for the Client Connect Event.
+     */
+    public static SchemaEventClass getClientConnectSchema()
+    {
+        return _clientConnectSchema;
+    }
+
+    /**
+     * Returns the schema for the Client Disconnect Event.
+     * @return the SchemaEventClass for the Client Disconnect Event.
+     */
+    public static SchemaEventClass getClientDisconnectSchema()
+    {
+        return _clientDisconnectSchema;
+    }
+
+    static
+    {
+        // Declare the schema for the QMF2 connection class.
+        _schema = new SchemaObjectClass("org.apache.qpid.broker", "connection");
+
+        // TODO
+        //_schema.addProperty(new SchemaProperty("whatHappened", QmfType.TYPE_STRING));
+
+        // Declare the schema for the QMF2 clientConnect Event class.
+        _clientConnectSchema = new SchemaEventClass("org.apache.qpid.broker", "clientConnect");
+
+        // Declare the schema for the QMF2 clientDisconnect Event class.
+        _clientDisconnectSchema = new SchemaEventClass("org.apache.qpid.broker", "clientDisconnect");
+    }
+    // End of static initialiser.
+
+    private final org.apache.qpid.server.model.Connection _connection;
+
+    /**
+     * Constructor.
+     * @param vhost the parent VirtualHost ConfiguredObject from the broker model.
+     * @param connection the Connection ConfiguredObject from the broker model.
+     */
+    public Connection(final org.apache.qpid.server.model.VirtualHost vhost,
+                      final org.apache.qpid.server.model.Connection connection)
+    {
+        super(getSchema());
+        _connection = connection; // Will eventually be used to retrieve statistics (when useful ones get populated).
+        String vhostName = (vhost == null) ? "" : "vhost:" + vhost.getName() + "/";
+        String address = vhostName + _connection.getName();
+
+        // TODO vhostRef - currently just use its name to try and get things working with standard command line tools.
+
+        setValue("address", address);
+        setValue("incoming", true); // incoming not supported in Qpid 0.20
+
+        // Although not implemented in Qpid 0.20 it's reasonable for them to be false
+        setValue("SystemConnection", false); // Is the S in System really a capital? not implemented in Qpid 0.20
+        setValue("userProxyAuth", false); // Not implemented in Qpid 0.20
+        setValue("federationLink", false); // Not implemented in Qpid 0.20
+
+        setValue("authIdentity", connection.getAttribute("principal"));
+        setValue("remoteProcessName", "unknown"); // remoteProcessName not supported in Qpid 0.20
+        setValue("remotePid", "unknown"); // remoteProcessName not supported in Qpid 0.20
+        setValue("remoteParentPid", "unknown"); // remoteProcessName not supported in Qpid 0.20
+
+        // shadow Not implemented in Qpid 0.20
+        // saslMechanism Not implemented in Qpid 0.20
+        // saslSsf Not implemented in Qpid 0.20
+        // protocol Not implemented in Qpid 0.20
+    }
+
+    /**
+     * Factory method to create a Client Connect Event Object with timestamp of now.
+     * @return the newly created Client Connect Event Object.
+     */
+    public QmfEvent createClientConnectEvent()
+    {
+        QmfEvent clientConnect = new QmfEvent(_clientConnectSchema);
+        clientConnect.setSeverity("info");
+        // TODO Set properties Map - can't really get much info from the org.apache.qpid.server.model.Connection yet.
+        clientConnect.setValue("rhost", _connection.getName());
+        clientConnect.setValue("user", getStringValue("authIdentity"));
+        return clientConnect;
+    }
+
+    /**
+     * Factory method to create a Client Disconnect Event Object with timestamp of now.
+     * @return the newly created Client Disconnect Event Object.
+     */
+    public QmfEvent createClientDisconnectEvent()
+    {
+        QmfEvent clientDisconnect = new QmfEvent(_clientDisconnectSchema);
+        clientDisconnect.setSeverity("info");
+        // TODO Set properties Map - can't really get much info from the org.apache.qpid.server.model.Connection yet.
+        clientDisconnect.setValue("rhost", _connection.getName());
+        clientDisconnect.setValue("user", getStringValue("authIdentity"));
+        return clientDisconnect;
+    }
+
+    /**
+     * This method maps the org.apache.qpid.server.model.Connection to QMF2 broker properties where possible then
+     * serialises into the underlying Map for transmission via AMQP. This method is called by handleQueryRequest()
+     * in the org.apache.qpid.qmf2.agent.Agent class implementing the main QMF2 Agent behaviour.
+     * 
+     * @return the underlying map. 
+     */
+    @Override
+    public Map<String, Object> mapEncode()
+    {
+/*
+        // There isn't yet a way yet in the Java Broker to associate Connections->Sessions->Subscriptions->Queues
+        System.out.println("Connection name = " + _connection.getName());
+        for (org.apache.qpid.server.model.Session session : _connection.getSessions())
+        {
+            System.out.println("Session name = " + session);
+        }
+*/
+
+
+        // Statistics
+        //Statistics stats = _queue.getStatistics();
+        // closing Not implemented in Qpid 0.20
+        setValue("framesFromClient", 0); // framesFromClient Not implemented in Qpid 0.20
+        setValue("framesToClient", 0); // framesToClient Not implemented in Qpid 0.20
+        setValue("bytesFromClient", 0); // bytesFromClient Not implemented in Qpid 0.20
+        setValue("bytesToClient", 0); // bytesToClient Not implemented in Qpid 0.20
+        setValue("msgsFromClient", 0); // msgsFromClient Not implemented in Qpid 0.20
+        setValue("msgsToClient", 0); // msgsToClient Not implemented in Qpid 0.20
+
+        //update(); // TODO set update if statistics change.
+        return super.mapEncode();
+    }
+}

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Connection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Connection.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Exchange.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Exchange.java?rev=1465662&view=auto
==============================================================================
--- qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Exchange.java (added)
+++ qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Exchange.java Mon Apr  8 15:19:04 2013
@@ -0,0 +1,252 @@
+/*
+ *
+ * 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.qmf2.agentdata;
+
+// Misc Imports
+import java.util.Collections;
+import java.util.Map;
+
+// Simple Logging Facade 4 Java
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// QMF2 Imports
+import org.apache.qpid.qmf2.agent.QmfAgentData;
+import org.apache.qpid.qmf2.common.QmfEvent;
+import org.apache.qpid.qmf2.common.ObjectId;
+import org.apache.qpid.qmf2.common.SchemaEventClass;
+//import org.apache.qpid.qmf2.common.SchemaMethod;
+import org.apache.qpid.qmf2.common.SchemaObjectClass;
+//import org.apache.qpid.qmf2.common.SchemaProperty;
+
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Statistics;
+
+/**
+ * This class provides a concrete implementation of QmfAgentData for the Exchange Management Object.
+ * In general it's possible to use QmfAgentData without sub-classing as it's really a "bean" style class
+ * that retains its properties in a Map, but in the case of the Java Broker Management Agent it's useful
+ * to sub-class as we need to map between the properties/statistics as specified in the Java Broker
+ * management model and those specified in qpid/spec/management-schema.xml which is what the C++ broker 
+ * uses. This class retains a reference to its peer org.apache.qpid.server.model.Exchange and does the
+ * necessary mapping when its mapEncode() method is called (which is used to serialise the QmfAgentData).
+ *
+ * @author Fraser Adams
+ */
+public class Exchange extends QmfAgentData
+{
+    private static final Logger _log = LoggerFactory.getLogger(Exchange.class);
+
+    /**
+     * This static initialiser block initialises the QMF2 Schema information needed by the Agent to find
+     * QmfAgentData and QmfEvent Objects of a given type.
+     */
+    private static final SchemaObjectClass _schema;
+    private static final SchemaEventClass _exchangeDeclareSchema;
+    private static final SchemaEventClass _exchangeDeleteSchema;
+
+    /**
+     * Returns the schema for the Exchange class.
+     * @return the SchemaObjectClass for the Exchange class.
+     */
+    public static SchemaObjectClass getSchema()
+    {
+        return _schema;
+    }
+
+    /**
+     * Returns the schema for the Exchange Declare Event.
+     * @return the SchemaEventClass for the Exchange Declare Event.
+     */
+    public static SchemaEventClass getExchangeDeclareSchema()
+    {
+        return _exchangeDeclareSchema;
+    }
+
+    /**
+     * Returns the schema for the Exchange Delete Event.
+     * @return the SchemaEventClass for the Exchange Delete Event.
+     */
+    public static SchemaEventClass getExchangeDeleteSchema()
+    {
+        return _exchangeDeleteSchema;
+    }
+
+    static
+    {
+        // Declare the schema for the QMF2 broker class.
+        _schema = new SchemaObjectClass("org.apache.qpid.broker", "exchange");
+
+        // TODO
+        //_schema.addProperty(new SchemaProperty("whatHappened", QmfType.TYPE_STRING));
+
+        // Declare the schema for the QMF2 exchangeDeclare Event class.
+        _exchangeDeclareSchema = new SchemaEventClass("org.apache.qpid.broker", "exchangeDeclare");
+
+        // Declare the schema for the QMF2 exchangeDelete Event class.
+        _exchangeDeleteSchema = new SchemaEventClass("org.apache.qpid.broker", "exchangeDelete");
+    }
+    // End of static initialiser.
+
+    private final org.apache.qpid.server.model.Exchange _exchange;
+    private String _name;
+
+    /**
+     * Constructor.
+     * @param vhost the parent VirtualHost ConfiguredObject from the broker model.
+     * @param exchange the Exchange ConfiguredObject from the broker model.
+     */
+    public Exchange(final org.apache.qpid.server.model.VirtualHost vhost,
+                    final org.apache.qpid.server.model.Exchange exchange)
+    {
+        super(getSchema());
+        _exchange = exchange;
+
+        _name = _exchange.getName();
+        _name = (_name.equals("<<default>>")) ? "" : _name;
+
+        if (vhost == null)
+        { // Note we include an empty vhost name in the compare key to make sure things get sorted properly.
+            setCompareKey("vhost:/" + _name);
+        }
+        else
+        {
+            _name = "vhost:" + vhost.getName() + "/" + _name;
+            setCompareKey(_name);
+        }
+
+        LifetimePolicy lifetimePolicy = (LifetimePolicy)_exchange.getAttribute("lifetimePolicy");
+        boolean autoDelete = (lifetimePolicy == LifetimePolicy.AUTO_DELETE) ? true : false;
+
+        // TODO vhostRef - currently just use its name to try and get things working with standard command line tools.
+
+        setValue("name", _name);
+        setValue("type", _exchange.getAttribute("type"));
+        setValue("durable", _exchange.getAttribute("durable"));
+        setValue("autoDelete", autoDelete);
+
+        // TODO altExchange and arguments properties.
+
+        // ObjectId needs to be set here in Exchange because the QMF2 version of qpid-config uses a hardcoded
+        // _object_name as below in the _object_id that it sets in the getExchange() call and in exchangeRef.
+        // It *shouldn't* do this and should really use the _object_id of the exchange object returned by
+        // getObjects("exchange"), but it does. The following line causes the Agent to use the explicit
+        // ObjectId below rather than constructing its own, which fixes the qpid-config issue.
+        setObjectId(new ObjectId("", "org.apache.qpid.broker:exchange:" + _name, 0));
+    }
+
+    /**
+     * Get the peer org.apache.qpid.server.model.Exchange instance. This is mainly used when creating an Alternate
+     * Exchange on a Queue as the underlying method requires an org.apache.qpid.server.model.Exchange.
+     */
+    public org.apache.qpid.server.model.Exchange getExchange()
+    {
+        return _exchange;
+    }
+
+    /**
+     * Factory method to create an Exchange Declare Event Object with timestamp of now.
+     * @return the newly created Exchange Declare Event Object.
+     */
+    public QmfEvent createExchangeDeclareEvent()
+    {
+        QmfEvent exchangeDeclare = new QmfEvent(_exchangeDeclareSchema);
+        exchangeDeclare.setSeverity("info");
+        exchangeDeclare.setValue("altEx", ""); // Java Broker can't set Alternate Exchange on Exchange
+        exchangeDeclare.setValue("args", Collections.EMPTY_MAP);
+        exchangeDeclare.setValue("autoDel", getBooleanValue("autoDelete"));
+        exchangeDeclare.setValue("disp", "created");
+        exchangeDeclare.setValue("durable", getBooleanValue("durable"));
+        exchangeDeclare.setValue("exName", _name);
+        exchangeDeclare.setValue("exType", getStringValue("type"));
+        // TODO Not sure of a way to get these for Java Broker Exchange.
+        //exchangeDeclare.setValue("rhost", _connection.getName());
+        //exchangeDeclare.setValue("user", getStringValue("authIdentity"));
+        return exchangeDeclare;
+    }
+
+    /**
+     * Factory method to create an Exchange Delete Event Object with timestamp of now.
+     * @return the newly created Exchange Delete Event Object.
+     */
+    public QmfEvent createExchangeDeleteEvent()
+    {
+        QmfEvent exchangeDelete = new QmfEvent(_exchangeDeleteSchema);
+        exchangeDelete.setSeverity("info");
+        exchangeDelete.setValue("exName", _name);
+        // TODO Not sure of a way to get these for Java Broker Exchange.
+        //exchangeDelete.setValue("rhost", _connection.getName());
+        //exchangeDelete.setValue("user", getStringValue("authIdentity"));
+        return exchangeDelete;
+    }
+
+    /**
+     * This method maps the org.apache.qpid.server.model.Exchange to QMF2 broker properties where possible then
+     * serialises into the underlying Map for transmission via AMQP. This method is called by handleQueryRequest()
+     * in the org.apache.qpid.qmf2.agent.Agent class implementing the main QMF2 Agent behaviour.
+     * 
+     * @return the underlying map. 
+     */
+    @Override
+    public Map<String, Object> mapEncode()
+    {
+        // Statistics
+        Statistics stats = _exchange.getStatistics();
+        long msgReceives = ((Long)stats.getStatistic("messagesIn")).longValue();
+        long msgDrops = ((Long)stats.getStatistic("messagesDropped")).longValue();
+        long msgRoutes = msgReceives - msgDrops;
+
+        long byteReceives = ((Long)stats.getStatistic("bytesIn")).longValue();
+        long byteDrops = ((Long)stats.getStatistic("bytesDropped")).longValue();
+        long byteRoutes = byteReceives - byteDrops;
+
+        setValue("producerCount", "Not yet implemented"); // In Qpid 0.20 producerCount statistic returns null.
+
+        // We have to modify the value of bindingCount for Exchange because the QmfManagementAgent "hides" the
+        // QMF Objects that relate to its own AMQP Connection/Queues/Bindings so the bindingCount for default direct
+        // qmf.default.direct and qmf.default.topic is different to the actual number of QMF bindings.
+        long bindingCount = ((Long)stats.getStatistic("bindingCount")).longValue();
+        if (_name.equals(""))
+        {
+            bindingCount -= 3;
+        }
+        else if (_name.equals("qmf.default.direct"))
+        {
+            bindingCount -= 2;
+        }
+        else if (_name.equals("qmf.default.topic"))
+        {
+            bindingCount -= 1;
+        }
+        setValue("bindingCount", bindingCount);
+
+        setValue("msgReceives", msgReceives);
+        setValue("msgDrops", msgDrops);
+        setValue("msgRoutes", msgRoutes);
+        setValue("byteReceives", byteReceives);
+        setValue("byteDrops", byteDrops);
+        setValue("byteRoutes", byteRoutes);
+
+        update(); // TODO only set update if a statistic has actually changed value.
+        return super.mapEncode();
+    }
+}

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Exchange.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Exchange.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Queue.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Queue.java?rev=1465662&view=auto
==============================================================================
--- qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Queue.java (added)
+++ qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Queue.java Mon Apr  8 15:19:04 2013
@@ -0,0 +1,287 @@
+/*
+ *
+ * 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.qmf2.agentdata;
+
+// Misc Imports
+import java.util.Collections;
+import java.util.Map;
+
+// Simple Logging Facade 4 Java
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// QMF2 Imports
+import org.apache.qpid.qmf2.agent.Agent;
+import org.apache.qpid.qmf2.agent.QmfAgentData;
+import org.apache.qpid.qmf2.common.QmfEvent;
+import org.apache.qpid.qmf2.common.Handle;
+import org.apache.qpid.qmf2.common.ObjectId;
+import org.apache.qpid.qmf2.common.QmfData;
+import org.apache.qpid.qmf2.common.SchemaEventClass;
+//import org.apache.qpid.qmf2.common.SchemaMethod;
+import org.apache.qpid.qmf2.common.SchemaObjectClass;
+//import org.apache.qpid.qmf2.common.SchemaProperty;
+
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.Statistics;
+
+/**
+ * This class provides a concrete implementation of QmfAgentData for the Queue Management Object.
+ * In general it's possible to use QmfAgentData without sub-classing as it's really a "bean" style class
+ * that retains its properties in a Map, but in the case of the Java Broker Management Agent it's useful
+ * to sub-class as we need to map between the properties/statistics as specified in the Java Broker
+ * management model and those specified in qpid/spec/management-schema.xml which is what the C++ broker 
+ * uses. This class retains a reference to its peer org.apache.qpid.server.model.Queue and does the
+ * necessary mapping when its mapEncode() method is called (which is used to serialise the QmfAgentData).
+ *
+ * @author Fraser Adams
+ */
+public class Queue extends QmfAgentData
+{
+    private static final Logger _log = LoggerFactory.getLogger(Queue.class);
+
+    /**
+     * This static initialiser block initialises the QMF2 Schema information needed by the Agent to find
+     * QmfAgentData and QmfEvent Objects of a given type.
+     */
+    private static final SchemaObjectClass _schema;
+    private static final SchemaEventClass _queueDeclareSchema;
+    private static final SchemaEventClass _queueDeleteSchema;
+
+    /**
+     * Returns the schema for the Queue class.
+     * @return the SchemaObjectClass for the Queue class.
+     */
+    public static SchemaObjectClass getSchema()
+    {
+        return _schema;
+    }
+
+    /**
+     * Returns the schema for the Queue Declare Event.
+     * @return the SchemaEventClass for the Queue Declare Event.
+     */
+    public static SchemaEventClass getQueueDeclareSchema()
+    {
+        return _queueDeclareSchema;
+    }
+
+    /**
+     * Returns the schema for the Queue Delete Event.
+     * @return the SchemaEventClass for the Queue Delete Event.
+     */
+    public static SchemaEventClass getQueueDeleteSchema()
+    {
+        return _queueDeleteSchema;
+    }
+
+    static
+    {
+        // Declare the schema for the QMF2 broker class.
+        _schema = new SchemaObjectClass("org.apache.qpid.broker", "queue");
+
+        // TODO
+        //_schema.addProperty(new SchemaProperty("whatHappened", QmfType.TYPE_STRING));
+
+        // Declare the schema for the QMF2 queueDeclare Event class.
+        _queueDeclareSchema = new SchemaEventClass("org.apache.qpid.broker", "queueDeclare");
+
+        // Declare the schema for the QMF2 queueDelete Event class.
+        _queueDeleteSchema = new SchemaEventClass("org.apache.qpid.broker", "queueDelete");
+    }
+    // End of static initialiser.
+
+    private final org.apache.qpid.server.model.Queue _queue;
+    private String _vhostName = "";
+    private ObjectId _alternateExchange = null;
+    private String _alternateExchangeName = "";
+
+    /**
+     * Constructor.
+     * @param vhost the parent VirtualHost ConfiguredObject from the broker model.
+     * @param queue the Queue ConfiguredObject from the broker model.
+     */
+    public Queue(final org.apache.qpid.server.model.VirtualHost vhost,
+                 final org.apache.qpid.server.model.Queue queue)
+    {
+        super(getSchema());
+        _queue = queue;
+
+        String name = _queue.getName();
+
+        if (vhost == null)
+        { // Note we include an empty vhost name in the compare key to make sure things get sorted properly.
+            setCompareKey("vhost:/" + name);
+        }
+        else
+        {
+            _vhostName = "vhost:" + vhost.getName() + "/";
+            name = _vhostName + name;
+            setCompareKey(name);
+        }
+
+        LifetimePolicy lifetimePolicy = (LifetimePolicy)_queue.getAttribute("lifetimePolicy");
+        boolean autoDelete = (lifetimePolicy == LifetimePolicy.AUTO_DELETE) ? true : false;
+
+        // TODO vhostRef - currently just use its name to try and get things working with standard command line tools.
+
+        setValue("name", name);
+        setValue("durable", _queue.getAttribute("durable"));
+        setValue("autoDelete", autoDelete);
+        setValue("exclusive", _queue.getAttribute("exclusive"));
+
+        // altExchange needs to be set later, done in mapEncode() for convenience, because it isn't set during
+        // Queue construction in the Java Broker.
+
+        // TODO arguments properties.
+
+
+        // ObjectId needs to be set here in Queue because the QMF2 version of qpid-config uses a hardcoded
+        // _object_name as below in the _object_id that it sets in the getQueue() call and in queueRef.
+        // It *shouldn't* do this and should really use the _object_id of the queue object returned by
+        // getObjects("queue"), but it does. The following line causes the Agent to use the explicit
+        // ObjectId below rather than constructing its own, which fixes the qpid-config issue.
+        setObjectId(new ObjectId("", "org.apache.qpid.broker:queue:" + name, 0));
+    }
+
+    /**
+     * TODO
+     * 
+     */
+    public void invokeMethod(Agent agent, Handle handle, String methodName, QmfData inArgs)
+    {
+        /*if (methodName.equals("purge"))
+        {
+            //broker.create(inArgs);
+        }
+        else if (methodName.equals("reroute"))
+        {
+            //broker.create(inArgs);
+        }
+        else*/
+        {
+            agent.raiseException(handle, methodName + " not yet implemented on Queue.");
+        }
+    }
+
+    /**
+     * Factory method to create a Queue Declare Event Object with timestamp of now.
+     * @return the newly created Queue Declare Event Object.
+     */
+    public QmfEvent createQueueDeclareEvent()
+    {
+        QmfEvent queueDeclare = new QmfEvent(_queueDeclareSchema);
+        queueDeclare.setSeverity("info");
+        // TODO the _alternateExchangeName gets set some time after the Constructor - how do I get its value for
+        // the queueDeclareEvent???!!!
+        queueDeclare.setValue("altEx", _alternateExchangeName);
+        queueDeclare.setValue("args", Collections.EMPTY_MAP); // TODO
+        queueDeclare.setValue("autoDel", getBooleanValue("autoDelete"));
+        queueDeclare.setValue("disp", "created");
+        queueDeclare.setValue("durable", getBooleanValue("durable"));
+        queueDeclare.setValue("excl", getBooleanValue("durable"));
+        queueDeclare.setValue("qName", getStringValue("name"));
+        // TODO Not sure of a way to get these for Java Broker Exchange.
+        //queueDeclare.setValue("rhost", _connection.getName());
+        //queueDeclare.setValue("user", getStringValue("authIdentity"));
+        return queueDeclare;
+    }
+
+    /**
+     * Factory method to create a Queue Delete Event Object with timestamp of now.
+     * @return the newly created Queue Delete Event Object.
+     */
+    public QmfEvent createQueueDeleteEvent()
+    {
+        QmfEvent queueDelete = new QmfEvent(_queueDeleteSchema);
+        queueDelete.setSeverity("info");
+        queueDelete.setValue("qName", getStringValue("name"));
+        // TODO Not sure of a way to get these for Java Broker Exchange.
+        //queueDelete.setValue("rhost", _connection.getName());
+        //queueDelete.setValue("user", getStringValue("authIdentity"));
+        return queueDelete;
+    }
+
+    /**
+     * This method maps the org.apache.qpid.server.model.Queue to QMF2 broker properties where possible then
+     * serialises into the underlying Map for transmission via AMQP. This method is called by handleQueryRequest()
+     * in the org.apache.qpid.qmf2.agent.Agent class implementing the main QMF2 Agent behaviour.
+     * 
+     * @return the underlying map. 
+     */
+    @Override
+    public Map<String, Object> mapEncode()
+    {
+        // Set the altExchange reference if an alternateExchange exists and hasn't already been set.
+        // Not sure how to set this closer to the Constructor. At the moment the _alternateExchangeName gets set
+        // too late to populate the "altEx" property of the queueDeclareEvent.
+        if (_alternateExchange == null)
+        {
+            Exchange altEx = (Exchange)_queue.getAttribute("alternateExchange");
+            if (altEx != null)
+            {
+                _alternateExchangeName = _vhostName + altEx.getName();
+                _alternateExchange = new ObjectId("", "org.apache.qpid.broker:exchange:" + _alternateExchangeName, 0);
+                setRefValue("altExchange", _alternateExchange);
+            }
+        }
+
+        // Statistics
+        Statistics stats = _queue.getStatistics();
+        setValue("msgTotalEnqueues", stats.getStatistic("totalEnqueuedMessages"));
+        setValue("msgTotalDequeues", stats.getStatistic("totalDequeuedMessages"));
+        // msgTxnEnqueues not implemented in Qpid 0.20
+        // msgTxnDequeues not implemented in Qpid 0.20
+        setValue("msgPersistEnqueues", stats.getStatistic("persistentEnqueuedMessages"));
+        setValue("msgPersistDequeues", stats.getStatistic("persistentDequeuedMessages"));
+        setValue("msgDepth", stats.getStatistic("queueDepthMessages"));
+        setValue("byteDepth", stats.getStatistic("queueDepthBytes"));
+        setValue("byteTotalEnqueues", stats.getStatistic("totalEnqueuedBytes"));
+        setValue("byteTotalDequeues", stats.getStatistic("totalDequeuedBytes"));
+        // byteTxnEnqueues not implemented in Qpid 0.20
+        // byteTxnDequeues not implemented in Qpid 0.20
+        setValue("bytePersistEnqueues", stats.getStatistic("persistentEnqueuedBytes"));
+        setValue("bytePersistDequeues", stats.getStatistic("persistentDequeuedBytes"));
+
+        // Flow-to-disk Statistics not implemented in Qpid 0.20
+        // releases & acquires not implemented in Qpid 0.20
+        // discardsTtl (discardsTtlMessages) not implemented in Qpid 0.20
+        // discardsRing not implemented in Qpid 0.20
+        // discardsLvq not implemented in Qpid 0.20
+        // discardsOverflow not implemented in Qpid 0.20
+        // discardsSubscriber not implemented in Qpid 0.20
+        // discardsPurge not implemented in Qpid 0.20
+        // reroutes not implemented in Qpid 0.20
+
+        setValue("consumerCount", stats.getStatistic("consumerCount"));
+        setValue("bindingCount", stats.getStatistic("bindingCount"));
+        setValue("unackedMessages", stats.getStatistic("unacknowledgedMessages"));
+
+        setValue("messageLatency", "Not yet implemented");
+        // flowStopped not implemented in Qpid 0.20
+        // flowStoppedCount not implemented in Qpid 0.20
+
+        update(); // TODO only update if statistics have actually changed.
+        return super.mapEncode();
+    }
+}

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Queue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Queue.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Subscription.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Subscription.java?rev=1465662&view=auto
==============================================================================
--- qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Subscription.java (added)
+++ qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Subscription.java Mon Apr  8 15:19:04 2013
@@ -0,0 +1,207 @@
+/*
+ *
+ * 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.qmf2.agentdata;
+
+// Misc Imports
+import java.util.Collections;
+import java.util.Map;
+
+// Simple Logging Facade 4 Java
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// QMF2 Imports
+import org.apache.qpid.qmf2.agent.QmfAgentData;
+import org.apache.qpid.qmf2.common.QmfEvent;
+import org.apache.qpid.qmf2.common.ObjectId;
+import org.apache.qpid.qmf2.common.QmfEvent;
+import org.apache.qpid.qmf2.common.SchemaEventClass;
+//import org.apache.qpid.qmf2.common.SchemaMethod;
+import org.apache.qpid.qmf2.common.SchemaObjectClass;
+//import org.apache.qpid.qmf2.common.SchemaProperty;
+
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.Statistics;
+
+/**
+ * This class provides a concrete implementation of QmfAgentData for the Subscription Management Object.
+ * In general it's possible to use QmfAgentData without sub-classing as it's really a "bean" style class
+ * that retains its properties in a Map, but in the case of the Java Broker Management Agent it's useful
+ * to sub-class as we need to map between the properties/statistics as specified in the Java Broker
+ * management model and those specified in qpid/spec/management-schema.xml which is what the C++ broker 
+ * uses. This class retains a reference to its peer org.apache.qpid.server.model.Consumer and does the
+ * necessary mapping when its mapEncode() method is called (which is used to serialise the QmfAgentData).
+ *
+ * @author Fraser Adams
+ */
+public class Subscription extends QmfAgentData
+{
+    private static final Logger _log = LoggerFactory.getLogger(Subscription.class);
+
+    /**
+     * This static initialiser block initialises the QMF2 Schema information needed by the Agent to find
+     * QmfAgentData and QmfEvent Objects of a given type.
+     */
+    private static final SchemaObjectClass _schema;
+    private static final SchemaEventClass _subscribeSchema;
+    private static final SchemaEventClass _unsubscribeSchema;
+
+    /**
+     * Returns the schema for the Subscription class.
+     * @return the SchemaObjectClass for the Subscription class.
+     */
+    public static SchemaObjectClass getSchema()
+    {
+        return _schema;
+    }
+
+    /**
+     * Returns the schema for the Subscribe Event.
+     * @return the SchemaEventClass for the Subscribe Event.
+     */
+    public static SchemaEventClass getSubscribeSchema()
+    {
+        return _subscribeSchema;
+    }
+
+    /**
+     * Returns the schema for the Unsubscribe Event.
+     * @return the SchemaEventClass for the Unsubscribe Event.
+     */
+    public static SchemaEventClass getUnsubscribeSchema()
+    {
+        return _unsubscribeSchema;
+    }
+
+    static
+    {
+        // Declare the schema for the QMF2 subscription class.
+        _schema = new SchemaObjectClass("org.apache.qpid.broker", "subscription");
+
+        // TODO
+        //_schema.addProperty(new SchemaProperty("whatHappened", QmfType.TYPE_STRING));
+
+        // Declare the schema for the QMF2 subscribe Event class.
+        _subscribeSchema = new SchemaEventClass("org.apache.qpid.broker", "subscribe");
+
+        // Declare the schema for the QMF2 unsubscribe Event class.
+        _unsubscribeSchema = new SchemaEventClass("org.apache.qpid.broker", "unsubscribe");
+    }
+    // End of static initialiser.
+
+    private final org.apache.qpid.server.model.Consumer _subscription;
+
+    private boolean _exclusive = false;
+    private String _qName = "";
+
+    /**
+     * Constructor.
+     * @param subscription the Consumer ConfiguredObject from the broker model.
+     */
+    public Subscription(final org.apache.qpid.server.model.Consumer subscription)
+    {
+        super(getSchema());
+        _subscription = subscription; // Will eventually be used in mapEncode() to retrieve statistics.
+
+        setValue("name", subscription.getName());
+        setValue("browsing", false); // TODO not supported in Qpid 0.20.
+        setValue("acknowledged", true); // TODO not supported in Qpid 0.20.
+        setValue("creditMode", "WINDOW"); // TODO not supported in Qpid 0.20.
+    }
+
+    /**
+     * Set the sessionRef property.
+     * @param sessionRef the sessionRef ObjectId.
+     */
+    public void setSessionRef(final ObjectId sessionRef)
+    {
+        setRefValue("sessionRef", sessionRef);
+    }
+
+    /**
+     * Set the queueRef property.
+     * @param queueRef the queueRef ObjectId.
+     */
+    public void setQueueRef(final ObjectId queueRef, final Queue queue)
+    {
+        setRefValue("queueRef", queueRef);
+
+        // Unfortunately the org.apache.qpid.server.model.Consumer doesn't yet allow access to its associated Queue
+        // so we pass a reference ourselves when we do setQueueRef. This is because some Subscription properties
+        // are *actually" related to the associated Queue.
+        _qName = queue.getName();
+        _exclusive = ((Boolean)queue.getAttribute("exclusive")).booleanValue();
+    }
+
+    /**
+     * Factory method to create a Subscribe Event Object with timestamp of now.
+     * @return the newly created Subscribe Event Object.
+     */
+    public QmfEvent createSubscribeEvent()
+    {
+        QmfEvent subscribe = new QmfEvent(_subscribeSchema);
+        subscribe.setSeverity("info");
+        subscribe.setValue("args", Collections.EMPTY_MAP);
+        subscribe.setValue("dest", getStringValue("name"));
+        subscribe.setValue("excl", _exclusive);
+        subscribe.setValue("qName", _qName);
+        // TODO Not sure of a way to get these for Java Broker Subscription.
+        //subscribe.setValue("rhost", _connection.getName());
+        //subscribe.setValue("user", getStringValue("authIdentity"));
+        return subscribe;
+    }
+
+    /**
+     * Factory method to create an Unsubscribe Event Object with timestamp of now.
+     * @return the newly created Unsubscribe Event Object.
+     */
+    public QmfEvent createUnsubscribeEvent()
+    {
+        QmfEvent unsubscribe = new QmfEvent(_unsubscribeSchema);
+        unsubscribe.setSeverity("info");
+        unsubscribe.setValue("dest", getStringValue("name"));
+        // TODO Not sure of a way to get these for Java Broker Subscription.
+        //unsubscribe.setValue("rhost", _connection.getName());
+        //unsubscribe.setValue("user", getStringValue("authIdentity"));
+        return unsubscribe;
+    }
+
+    /**
+     * This method maps the org.apache.qpid.server.model.Consumer to QMF2 subscribe properties where possible then
+     * serialises into the underlying Map for transmission via AMQP. This method is called by handleQueryRequest()
+     * in the org.apache.qpid.qmf2.agent.Agent class implementing the main QMF2 Agent behaviour.
+     * 
+     * @return the underlying map. 
+     */
+    @Override
+    public Map<String, Object> mapEncode()
+    {
+        // Statistics 
+        Statistics stats = _subscription.getStatistics();
+        setValue("delivered", stats.getStatistic("messagesOut"));
+
+        setValue("exclusive", _exclusive);
+
+        update(); // TODO Only Update if statistics have changes.
+        return super.mapEncode();
+    }
+}

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Subscription.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: qpid/trunk/qpid/tools/src/java/src/qpid-broker-plugins-management-qmf2/java/org/apache/qpid/server/qmf2/agentdata/Subscription.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date



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