Search in sources :

Example 6 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class Agent method onMessage.

//                                          MessageListener
// ********************************************************************************************************
/**
     * MessageListener for QMF2 Console requests.
     *
     * @param message the JMS Message passed to the listener.
     */
public final void onMessage(final Message message) {
    try {
        String agentName = QmfData.getString(message.getObjectProperty("qmf.agent"));
        String content = QmfData.getString(message.getObjectProperty("qmf.content"));
        String opcode = QmfData.getString(message.getObjectProperty("qmf.opcode"));
        //String routingKey = ((javax.jms.Topic)message.getJMSDestination()).getTopicName();
        //String contentType = ((org.apache.qpid.client.message.AbstractJMSMessage)message).getContentType();
        //System.out.println();
        //System.out.println("agentName = " + agentName);
        //System.out.println("content = " + content);
        //System.out.println("opcode = " + opcode);
        //System.out.println("routingKey = " + routingKey);
        //System.out.println("contentType = " + contentType);
        Handle handle = new Handle(message.getJMSCorrelationID(), message.getJMSReplyTo());
        if (opcode.equals("_agent_locate_request")) {
            handleLocateRequest(handle);
        } else if (opcode.equals("_method_request")) {
            if (AMQPMessage.isAMQPMap(message)) {
                _eventListener.onEvent(new MethodCallWorkItem(handle, new MethodCallParams(AMQPMessage.getMap(message))));
            } else {
                _log.info("onMessage() Received Method Request message in incorrect format");
            }
        } else if (opcode.equals("_query_request")) {
            if (AMQPMessage.isAMQPMap(message)) {
                try {
                    QmfQuery query = new QmfQuery(AMQPMessage.getMap(message));
                    handleQueryRequest(handle, query);
                } catch (QmfException qmfe) {
                    raiseException(handle, "Query Request failed, invalid Query: " + qmfe.getMessage());
                }
            } else {
                _log.info("onMessage() Received Query Request message in incorrect format");
            }
        } else if (opcode.equals("_subscribe_request")) {
            if (AMQPMessage.isAMQPMap(message)) {
                try {
                    SubscriptionParams subscriptionParams = new SubscriptionParams(handle, AMQPMessage.getMap(message));
                    if (this instanceof AgentExternal) {
                        _eventListener.onEvent(new SubscribeRequestWorkItem(handle, subscriptionParams));
                    } else {
                        Subscription subscription = new Subscription(this, subscriptionParams);
                        String subscriptionId = subscription.getSubscriptionId();
                        _subscriptions.put(subscriptionId, subscription);
                        _timer.schedule(subscription, 0, subscriptionParams.getPublishInterval());
                        subscriptionResponse(handle, subscription.getConsoleHandle(), subscriptionId, subscription.getDuration(), subscription.getInterval(), null);
                    }
                } catch (QmfException qmfe) {
                    raiseException(handle, "Subscribe Request failed, invalid Query: " + qmfe.getMessage());
                }
            } else {
                _log.info("onMessage() Received Subscribe Request message in incorrect format");
            }
        } else if (opcode.equals("_subscribe_refresh_indication")) {
            if (AMQPMessage.isAMQPMap(message)) {
                ResubscribeParams resubscribeParams = new ResubscribeParams(AMQPMessage.getMap(message));
                if (this instanceof AgentExternal) {
                    _eventListener.onEvent(new ResubscribeRequestWorkItem(handle, resubscribeParams));
                } else {
                    String subscriptionId = resubscribeParams.getSubscriptionId();
                    Subscription subscription = _subscriptions.get(subscriptionId);
                    if (subscription != null) {
                        subscription.refresh(resubscribeParams);
                        subscriptionResponse(handle, subscription.getConsoleHandle(), subscription.getSubscriptionId(), subscription.getDuration(), subscription.getInterval(), null);
                    }
                }
            } else {
                _log.info("onMessage() Received Resubscribe Request message in incorrect format");
            }
        } else if (opcode.equals("_subscribe_cancel_indication")) {
            if (AMQPMessage.isAMQPMap(message)) {
                QmfData qmfSubscribe = new QmfData(AMQPMessage.getMap(message));
                String subscriptionId = qmfSubscribe.getStringValue("_subscription_id");
                if (this instanceof AgentExternal) {
                    _eventListener.onEvent(new UnsubscribeRequestWorkItem(subscriptionId));
                } else {
                    Subscription subscription = _subscriptions.get(subscriptionId);
                    if (subscription != null) {
                        subscription.cancel();
                    }
                }
            } else {
                _log.info("onMessage() Received Subscribe Cancel Request message in incorrect format");
            }
        }
    } catch (JMSException jmse) {
        _log.info("JMSException {} caught in onMessage()", jmse.getMessage());
    }
}
Also used : QmfData(org.apache.qpid.qmf2.common.QmfData) JMSException(javax.jms.JMSException) Handle(org.apache.qpid.qmf2.common.Handle) QmfQuery(org.apache.qpid.qmf2.common.QmfQuery) QmfException(org.apache.qpid.qmf2.common.QmfException)

Example 7 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class QmfManagementAgent method childAdded.

/**
     * ConfigurationChangeListener method called when a child ConfiguredObject is added.
     * <p>
     * This method checks the type of the child ConfiguredObject that has been added and creates the equivalent
     * QMF2 Management Object if one doesn't already exist. In most cases it's a one-to-one mapping, but for
     * Binding for example the Binding child is added to both Queue and Exchange so we only create the Binding
     * QMF2 Management Object once and add the queueRef and exchangeRef reference properties referencing the Queue
     * and Exchange parent Objects respectively, Similarly for Consumer (AKA Subscription).
     * <p>
     * This method is also responsible for raising the appropriate QMF2 Events when Management Objects are created.
     * @param object the parent object that the child is being added to.
     * @param child the child object being added.
     */
@Override
public void childAdded(final ConfiguredObject object, final ConfiguredObject child) {
    if (_log.isDebugEnabled()) {
        _log.debug("childAdded: " + child.getClass().getSimpleName() + "." + child.getName());
    }
    QmfAgentData data = null;
    if (child instanceof Broker) {
        data = new org.apache.qpid.server.qmf2.agentdata.Broker((Broker) child);
    } else if (child instanceof Connection) {
        if (!agentConnection && !_objects.containsKey(child)) {
            // If the parent object is the default vhost set it to null so that the Connection ignores it.
            VirtualHost vhost = (object.getName().equals(_defaultVirtualHost)) ? null : (VirtualHost) object;
            data = new org.apache.qpid.server.qmf2.agentdata.Connection(vhost, (Connection) child);
            _objects.put(child, data);
            // Raise a Client Connect Event.
            _agent.raiseEvent(((org.apache.qpid.server.qmf2.agentdata.Connection) data).createClientConnectEvent());
        }
        // Only ignore the first Connection, which is the one from the Agent. 
        agentConnection = false;
    } else if (child instanceof Session) {
        if (!_objects.containsKey(child)) {
            // Get the Connection QmfAgentData so we can get connectionRef.
            QmfAgentData ref = _objects.get(object);
            if (ref != null) {
                data = new org.apache.qpid.server.qmf2.agentdata.Session((Session) child, ref.getObjectId());
                _objects.put(child, data);
            }
        }
    } else if (child instanceof Exchange) {
        if (!_objects.containsKey(child)) {
            // If the parent object is the default vhost set it to null so that the Connection ignores it.
            VirtualHost vhost = (object.getName().equals(_defaultVirtualHost)) ? null : (VirtualHost) object;
            data = new org.apache.qpid.server.qmf2.agentdata.Exchange(vhost, (Exchange) child);
            _objects.put(child, data);
            // Raise an Exchange Declare Event.
            _agent.raiseEvent(((org.apache.qpid.server.qmf2.agentdata.Exchange) data).createExchangeDeclareEvent());
        }
    } else if (child instanceof Queue) {
        if (!_objects.containsKey(child)) {
            // If the parent object is the default vhost set it to null so that the Connection ignores it.
            VirtualHost vhost = (object.getName().equals(_defaultVirtualHost)) ? null : (VirtualHost) object;
            data = new org.apache.qpid.server.qmf2.agentdata.Queue(vhost, (Queue) child);
            _objects.put(child, data);
            // Raise a Queue Declare Event.
            _agent.raiseEvent(((org.apache.qpid.server.qmf2.agentdata.Queue) data).createQueueDeclareEvent());
        }
    } else if (child instanceof Binding) {
        // depending on whether Queue or Exchange was the parent of this addChild() call.
        if (!_objects.containsKey(child)) {
            data = new org.apache.qpid.server.qmf2.agentdata.Binding((Binding) child);
            _objects.put(child, data);
            String eName = ((Binding) child).getExchange().getName();
            if (// Don't send Event for Binding to default direct.
            !eName.equals("<<default>>")) {
                // Raise a Bind Event.
                _agent.raiseEvent(((org.apache.qpid.server.qmf2.agentdata.Binding) data).createBindEvent());
            }
        }
        org.apache.qpid.server.qmf2.agentdata.Binding binding = (org.apache.qpid.server.qmf2.agentdata.Binding) _objects.get(child);
        QmfAgentData ref = _objects.get(object);
        if (ref != null) {
            if (object instanceof Queue) {
                binding.setQueueRef(ref.getObjectId());
            } else if (object instanceof Exchange) {
                binding.setExchangeRef(ref.getObjectId());
            }
        }
    } else if (// AKA Subscription
    child instanceof Consumer) {
        // Session reference depending on whether Queue or Session was the parent of this addChild() call.
        if (!_objects.containsKey(child)) {
            data = new org.apache.qpid.server.qmf2.agentdata.Subscription((Consumer) child);
            _objects.put(child, data);
        }
        org.apache.qpid.server.qmf2.agentdata.Subscription subscription = (org.apache.qpid.server.qmf2.agentdata.Subscription) _objects.get(child);
        QmfAgentData ref = _objects.get(object);
        if (ref != null) {
            if (object instanceof Queue) {
                subscription.setQueueRef(ref.getObjectId(), (Queue) object);
                // Raise a Subscribe Event - N.B. Need to do it *after* we've set the queueRef.
                _agent.raiseEvent(subscription.createSubscribeEvent());
            } else if (object instanceof Session) {
                subscription.setSessionRef(ref.getObjectId());
            }
        }
    }
    try {
        // If we've created new QmfAgentData we register it with the Agent.
        if (data != null) {
            _agent.addObject(data);
        }
    } catch (QmfException qmfe) {
        _log.error("QmfException caught in QmfManagementAgent.addObject()", qmfe);
    }
    child.addChangeListener(this);
}
Also used : Binding(org.apache.qpid.server.model.Binding) Broker(org.apache.qpid.server.model.Broker) Connection(org.apache.qpid.server.model.Connection) Exchange(org.apache.qpid.server.model.Exchange) Consumer(org.apache.qpid.server.model.Consumer) QmfAgentData(org.apache.qpid.qmf2.agent.QmfAgentData) VirtualHost(org.apache.qpid.server.model.VirtualHost) Queue(org.apache.qpid.server.model.Queue) Session(org.apache.qpid.server.model.Session) QmfException(org.apache.qpid.qmf2.common.QmfException)

Example 8 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class Console method createSubscription.

/**
     * Creates a subscription to the agent using the given Query.
     * <p>
     * The consoleHandle is an application-provided handle that will accompany each subscription update sent from
     * the Agent. Subscription updates will appear as SUBSCRIPTION_INDICATION WorkItems on the Console's work queue.
     * <p>
     * The publishInterval is the requested time interval in seconds on which the Agent should publish updates.
     * <p>
     * The lifetime parameter is the requested time interval in seconds for which this subscription should remain in
     * effect. Both the requested lifetime and publishInterval may be overridden by the Agent, as indicated in the 
     * subscription response.
     * <p>
     * This method may be called asynchronously by providing a replyHandle argument. When called
     * asynchronously, the result of this method call is returned in a SUBSCRIBE_RESPONSE WorkItem with a
     * handle matching the value of replyHandle.
     * <p>
     * Timeout can be used to override the console's default reply timeout.
     * <p>
     * When called synchronously, this method returns a SubscribeParams object containing the result of the
     * subscription request.
     *
     * @param agent the Agent on which to create the subscription.
     * @param query the Query to perform on the Agent
     * @param consoleHandle an application-provided handle that will accompany each subscription update sent
     *        from the Agent.
     * @param options a String representation of a Map containing the options in the form
     *        <pre>"{lifetime:&lt;value&gt;, publishInterval:&lt;value&gt;, replyHandle:&lt;value&gt;, timeout:&lt;value&gt;}"</pre>
     *        they are optional and may appear in any order.
     * <pre>
     *        <b>lifetime</b> the requested time interval in seconds for which this subscription should remain in effect.
     *        <b>publishInterval</b> the requested time interval in seconds on which the Agent should publish updates
     *        <b>replyHandle</b> the correlation handle used to tie asynchronous method requests with responses.
     *        <b>timeout</b> the time to wait for a reply from the Agent.
     * </pre>
     */
public synchronized SubscribeParams createSubscription(final Agent agent, final QmfQuery query, final String consoleHandle, final String options) throws QmfException {
    if (consoleHandle == null) {
        throw new QmfException("Called createSubscription() with null consoleHandle");
    }
    if (_subscriptionByHandle.get(consoleHandle) != null) {
        throw new QmfException("Called createSubscription() with a consoleHandle that is already in use");
    }
    if (agent == null) {
        throw new QmfException("Called createSubscription() with null agent");
    }
    if (!agent.isActive()) {
        throw new QmfException("Called createSubscription() with inactive agent");
    }
    String agentName = agent.getName();
    // Initialise optional values to defaults;
    long lifetime = _subscriptionDuration;
    long publishInterval = 10000;
    long timeout = _replyTimeout;
    String replyHandle = null;
    if (options != null) {
        // We wrap the Map in a QmfData object to avoid potential class cast issues with the parsed options
        QmfData optMap = new QmfData(new AddressParser(options).map());
        if (optMap.hasValue("lifetime")) {
            lifetime = optMap.getLongValue("lifetime");
        }
        if (optMap.hasValue("publishInterval")) {
            // Multiply publishInterval by 1000 because the QMF2 protocol spec says interval is
            // "The request time (in milliseconds) between periodic updates of data in this subscription"
            publishInterval = 1000 * optMap.getLongValue("publishInterval");
        }
        if (optMap.hasValue("timeout")) {
            timeout = optMap.getLongValue("timeout");
        }
        if (optMap.hasValue("replyHandle")) {
            replyHandle = optMap.getStringValue("replyHandle");
        }
    }
    try {
        MapMessage request = _syncSession.createMapMessage();
        // Deliberately forcing all replies to the _asyncReplyAddress
        request.setJMSReplyTo(_asyncReplyAddress);
        // Deliberately using consoleHandle not replyHandle here
        request.setJMSCorrelationID(consoleHandle);
        request.setStringProperty("x-amqp-0-10.app-id", "qmf2");
        request.setStringProperty("method", "request");
        request.setStringProperty("qmf.opcode", "_subscribe_request");
        request.setStringProperty("qpid.subject", agentName);
        request.setObject("_query", query.mapEncode());
        request.setObject("_interval", publishInterval);
        request.setObject("_duration", lifetime);
        SubscriptionManager subscription = new SubscriptionManager(agent, query, consoleHandle, replyHandle, publishInterval, lifetime);
        _subscriptionByHandle.put(consoleHandle, subscription);
        _timer.schedule(subscription, 0, publishInterval);
        if (_subscriptionEmulationEnabled && agentName.equals(_brokerAgentName)) {
            // If the Agent is the broker Agent we emulate the Subscription on the Console
            String subscriptionId = UUID.randomUUID().toString();
            _subscriptionById.put(subscriptionId, subscription);
            subscription.setSubscriptionId(subscriptionId);
            final SubscribeParams params = new SubscribeParams(consoleHandle, subscription.mapEncode());
            if (replyHandle == null) {
                return params;
            } else {
                final String handle = replyHandle;
                Thread thread = new Thread() {

                    public void run() {
                        _eventListener.onEvent(new SubscribeResponseWorkItem(new Handle(handle), params));
                    }
                };
                thread.start();
            }
            return null;
        }
        _requester.send(request);
        if (replyHandle == null) {
            // If this is an synchronous request get the response
            subscription.await(timeout * 1000);
            if (subscription.getSubscriptionId() == null) {
                _log.info("No response received in createSubscription()");
                throw new QmfException("No response received for Console.createSubscription()");
            }
            return new SubscribeParams(consoleHandle, subscription.mapEncode());
        }
        // If this is an asynchronous request return without waiting for a response
        return null;
    } catch (JMSException jmse) {
        _log.info("JMSException {} caught in createSubscription()", jmse.getMessage());
        throw new QmfException(jmse.getMessage());
    }
}
Also used : QmfData(org.apache.qpid.qmf2.common.QmfData) AddressParser(org.apache.qpid.messaging.util.AddressParser) MapMessage(javax.jms.MapMessage) JMSException(javax.jms.JMSException) QmfException(org.apache.qpid.qmf2.common.QmfException) Handle(org.apache.qpid.qmf2.common.Handle)

Example 9 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class Agent method addObject.

/**
     * Passes a reference to an instance of a managed QMF object to the Agent.
     * <p>
     * The object's name must uniquely identify this object among all objects known to this Agent.
     * <p>
     * This method creates an ObjectId for the QmfAgentData being added, it does this by first checking
     * the schema.
     * <p>
     * If an associated schema exists we look for the set of property names that have been
     * specified as idNames. If idNames exists we look for their values within the object and use that
     * to create the objectName. If we can't create a sensible name we use a randomUUID.
     * @param object the QmfAgentData object to be added
     */
public void addObject(final QmfAgentData object) throws QmfException {
    // There are some cases where a QmfAgentData Object might have already set its ObjectId, for example where
    // it may need to have a "well known" ObjectId. This is the case with the Java Broker Management Agent
    // where tools such as qpid-config might have made assumptions about its ObjectId rather than doing "discovery".
    ObjectId addr = object.getObjectId();
    if (addr == null) {
        SchemaClassId classId = object.getSchemaClassId();
        SchemaClass schema = _schemaCache.get(classId);
        // Try to create an objectName using the property names that have been specified as idNames in the schema
        StringBuilder buf = new StringBuilder();
        // Initialise idNames as an empty array as we want to check if a key has been used to construct the name.
        String[] idNames = {};
        if (schema != null && schema instanceof SchemaObjectClass) {
            idNames = ((SchemaObjectClass) schema).getIdNames();
            for (String property : idNames) {
                buf.append(object.getStringValue(property));
            }
        }
        String objectName = buf.toString();
        // exchange has name == "")
        if (objectName.length() == 0 && idNames.length == 0)
            objectName = UUID.randomUUID().toString();
        // Finish up the name by incorporating package and class names
        objectName = classId.getPackageName() + ":" + classId.getClassName() + ":" + objectName;
        // Now we've got a good name for the object we create its ObjectId and add that to the object
        addr = new ObjectId(_name, objectName, _epoch);
        object.setObjectId(addr);
    }
    QmfAgentData foundObject = _objectIndex.get(addr);
    if (foundObject != null) {
        // If a duplicate object has actually been Deleted we can reuse the address.
        if (!foundObject.isDeleted()) {
            throw new QmfException("Duplicate QmfAgentData Address");
        }
    }
    _objectIndex.put(addr, object);
    // Does the new object match any Subscriptions? If so add a reference to the matching Subscription and publish.
    for (Subscription subscription : _subscriptions.values()) {
        QmfQuery query = subscription.getQuery();
        if (query.getObjectId() != null) {
            if (query.getObjectId().equals(addr)) {
                object.addSubscription(subscription.getSubscriptionId(), subscription);
                object.publish();
            }
        } else if (query.evaluate(object)) {
            object.addSubscription(subscription.getSubscriptionId(), subscription);
            object.publish();
        }
    }
}
Also used : ObjectId(org.apache.qpid.qmf2.common.ObjectId) SchemaClass(org.apache.qpid.qmf2.common.SchemaClass) SchemaObjectClass(org.apache.qpid.qmf2.common.SchemaObjectClass) SchemaClassId(org.apache.qpid.qmf2.common.SchemaClassId) QmfQuery(org.apache.qpid.qmf2.common.QmfQuery) QmfException(org.apache.qpid.qmf2.common.QmfException)

Example 10 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class AgentExternalTest method addObject.

public void addObject(QmfAgentData object) throws QmfException {
    ObjectId addr = _agent.allocObjectId(UUID.randomUUID().toString());
    object.setObjectId(addr);
    _objectIndex.put(addr, object);
    // Does the new object match any Subscriptions? If so add a reference to the matching Subscription and publish.
    for (Subscription subscription : _subscriptions.values()) {
        QmfQuery query = subscription.getQuery();
        if (query.getObjectId() != null) {
            if (query.getObjectId().equals(addr)) {
                object.addSubscription(subscription.getSubscriptionId(), subscription);
                object.publish();
            }
        } else if (query.evaluate(object)) {
            object.addSubscription(subscription.getSubscriptionId(), subscription);
            object.publish();
        }
    }
}
Also used : ObjectId(org.apache.qpid.qmf2.common.ObjectId) Subscription(org.apache.qpid.qmf2.agent.Subscription) QmfQuery(org.apache.qpid.qmf2.common.QmfQuery)

Aggregations

QmfException (org.apache.qpid.qmf2.common.QmfException)9 ObjectId (org.apache.qpid.qmf2.common.ObjectId)8 QmfQuery (org.apache.qpid.qmf2.common.QmfQuery)6 JMSException (javax.jms.JMSException)5 Handle (org.apache.qpid.qmf2.common.Handle)5 QmfData (org.apache.qpid.qmf2.common.QmfData)4 QmfConsoleData (org.apache.qpid.qmf2.console.QmfConsoleData)4 ArrayList (java.util.ArrayList)3 Date (java.util.Date)3 MapMessage (javax.jms.MapMessage)3 QmfAgentData (org.apache.qpid.qmf2.agent.QmfAgentData)3 QmfEvent (org.apache.qpid.qmf2.common.QmfEvent)3 SchemaClassId (org.apache.qpid.qmf2.common.SchemaClassId)3 AddressParser (org.apache.qpid.messaging.util.AddressParser)2 Subscription (org.apache.qpid.qmf2.agent.Subscription)2 AgentHeartbeatWorkItem (org.apache.qpid.qmf2.console.AgentHeartbeatWorkItem)2 AgentRestartedWorkItem (org.apache.qpid.qmf2.console.AgentRestartedWorkItem)2 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1