use of org.apache.qpid.qmf2.common.QmfData in project qpid by apache.
the class QueueFuse method purgeQueue.
/**
* Look up a queue object with the given name and if it's not a ring queue invoke the queue's purge method.
* @param queueName the name of the queue to purge
* @param msgDepth the number of messages on the queue, used to determine how many messages to purge.
*/
private void purgeQueue(final String queueName, long msgDepth) {
QmfConsoleData queue = _queueCache.get(queueName);
if (queue == null) {
System.out.printf("%s ERROR QueueFuse.disconnectQueue() %s reference couldn't be found\n", new Date().toString(), queueName);
} else {
// If we've found a queue called queueName we then find the bindings that reference it.
Map args = (Map) queue.getValue("arguments");
String policyType = (String) args.get("qpid.policy_type");
if (policyType != null && policyType.equals("ring")) {
// If qpid.policy_type=ring we return.
return;
}
try {
QmfData arguments = new QmfData();
arguments.setValue("request", (long) (_purge * msgDepth));
queue.invokeMethod("purge", arguments);
} catch (QmfException e) {
System.out.println(e.getMessage());
}
}
}
use of org.apache.qpid.qmf2.common.QmfData 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());
}
}
use of org.apache.qpid.qmf2.common.QmfData 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:<value>, publishInterval:<value>, replyHandle:<value>, timeout:<value>}"</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());
}
}
use of org.apache.qpid.qmf2.common.QmfData in project qpid by apache.
the class Broker method invokeMethod.
/**
* 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.
*/
@SuppressWarnings("unchecked")
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 (// method = create
methodName.equals("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 (// create exchange.
type.equals("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;
}
// 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.
Map<String, Object> attributes = new HashMap<>();
attributes.put(Exchange.NAME, nameParser.getExchangeName());
attributes.put(Exchange.STATE, State.ACTIVE);
attributes.put(Exchange.DURABLE, durable);
attributes.put(Exchange.LIFETIME_POLICY, LifetimePolicy.PERMANENT);
attributes.put(Exchange.TYPE, exchangeType);
attributes.put(Exchange.ALTERNATE_EXCHANGE, alternateExchange);
vhost.createExchange(attributes);
} else // End of create exchange.
if (// create queue.
type.equals("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.
Map<String, Object> attributes = new HashMap<String, Object>(properties);
attributes.put(Queue.NAME, nameParser.getQueueName());
attributes.put(Queue.DURABLE, durable);
attributes.put(Queue.LIFETIME_POLICY, LifetimePolicy.PERMANENT);
// 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();
attributes.put(Queue.ALTERNATE_EXCHANGE, altEx.getId());
}
}
Queue queue = vhost.createQueue(attributes);
} else if (// create binding.
type.equals("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 (// delete exchange.
type.equals("exchange")) {
Exchange exchange = nameParser.getExchange();
if (exchange != null) {
exchange.delete();
}
} else if (// delete queue.
type.equals("queue")) {
Queue queue = nameParser.getQueue();
if (queue != null) {
queue.deleteAndReturnCount();
}
} else if (// delete binding.
type.equals("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.");
}
}
use of org.apache.qpid.qmf2.common.QmfData in project qpid by apache.
the class Console method getObjects.
/**
* Perform a query for QmfConsoleData objects. Returns a list (possibly empty) of matching objects.
* If replyHandle is null this method will block until the agent replies, or the timeout expires.
* Once the timeout expires, all data retrieved to date is returned. If replyHandle is non-null an
* asynchronous request is performed
*
* @param agent the Agent being queried
* @param query the ObjectId or SchemaClassId being queried for.
* @param replyHandle the correlation handle used to tie asynchronous method requests with responses
* @param timeout the time to wait for a reply from the Agent, a value of -1 means use the default timeout
* @return a List of QMF Objects describing that class
*/
private List<QmfConsoleData> getObjects(final Agent agent, final QmfData query, final String replyHandle, int timeout) {
String agentName = agent.getName();
timeout = (timeout < 1) ? _replyTimeout : timeout;
List<QmfConsoleData> results = Collections.emptyList();
try {
Destination destination = (replyHandle == null) ? _replyAddress : _asyncReplyAddress;
MapMessage request = _syncSession.createMapMessage();
request.setJMSReplyTo(destination);
request.setJMSCorrelationID(replyHandle);
request.setStringProperty("x-amqp-0-10.app-id", "qmf2");
request.setStringProperty("method", "request");
request.setStringProperty("qmf.opcode", "_query_request");
request.setStringProperty("qpid.subject", agentName);
// Create a QMF Query for an "OBJECT" target using either a schema ID or object ID
String queryType = (query instanceof SchemaClassId) ? "_schema_id" : "_object_id";
request.setObject("_what", "OBJECT");
request.setObject(queryType, query.mapEncode());
// it would be somewhat unfortunate if their response got interleaved with ours!!
synchronized (this) {
_requester.send(request);
if (replyHandle == null) {
boolean lastResult = true;
ArrayList<QmfConsoleData> partials = new ArrayList<QmfConsoleData>();
do {
// Wrap in a do/while loop to cater for the case where the Agent may send partial results.
Message response = _responder.receive(timeout * 1000);
if (response == null) {
_log.info("No response received in getObjects()");
return partials;
}
lastResult = !response.propertyExists("partial");
if (AMQPMessage.isAMQPList(response)) {
List<Map> mapResults = AMQPMessage.getList(response);
partials.ensureCapacity(partials.size() + mapResults.size());
for (Map content : mapResults) {
partials.add(new QmfConsoleData(content, agent));
}
} else if (AMQPMessage.isAMQPMap(response)) {
// Error responses are returned as MapMessages, though they are being ignored here.
// QmfData exception = new QmfData(AMQPMessage.getMap(response));
// System.out.println(agentName + " " + exception.getStringValue("error_text"));
} else {
_log.info("getObjects() Received response message in incorrect format");
}
} while (!lastResult);
results = partials;
}
}
} catch (JMSException jmse) {
_log.info("JMSException {} caught in getObjects()", jmse.getMessage());
}
return results;
}
Aggregations