use of org.apache.qpid.qmf2.console.Console in project qpid by apache.
the class Agent method handleQueryRequest.
/**
* Handle the query request and send the response back to the Console.
* @param handle the reply handle that contains the replyTo Address.
* @param query the inbound query from the Console.
*/
@SuppressWarnings("unchecked")
private final void handleQueryRequest(final Handle handle, final QmfQuery query) {
QmfQueryTarget target = query.getTarget();
if (target == QmfQueryTarget.SCHEMA_ID) {
List<Map> results = new ArrayList<Map>(_schemaCache.size());
// Look up all SchemaClassId objects
for (SchemaClassId classId : _schemaCache.keySet()) {
results.add(classId.mapEncode());
}
// Send the response back to the Console.
queryResponse(handle, results, "_schema_id");
} else if (target == QmfQueryTarget.SCHEMA) {
List<Map> results = new ArrayList<Map>(1);
// Look up a SchemaClass object by the SchemaClassId obtained from the query
SchemaClassId classId = query.getSchemaClassId();
SchemaClass schema = _schemaCache.get(classId);
if (schema != null) {
results.add(schema.mapEncode());
}
// Send the response back to the Console.
queryResponse(handle, results, "_schema");
} else if (target == QmfQueryTarget.OBJECT_ID) {
List<Map> results = new ArrayList<Map>(_objectIndex.size());
// Look up all ObjectId objects
for (ObjectId objectId : _objectIndex.keySet()) {
results.add(objectId.mapEncode());
}
// Send the response back to the Console.
queryResponse(handle, results, "_object_id");
} else if (target == QmfQueryTarget.OBJECT) {
// If this is implementing the AgentExternal model we pass the QmfQuery on in a QueryWorkItem
if (this instanceof AgentExternal) {
_eventListener.onEvent(new QueryWorkItem(handle, query));
return;
} else {
//qmfContentType = "_data";
if (query.getObjectId() != null) {
List<Map> results = new ArrayList<Map>(1);
// Look up a QmfAgentData object by the ObjectId obtained from the query
ObjectId objectId = query.getObjectId();
QmfAgentData object = _objectIndex.get(objectId);
if (object != null && !object.isDeleted()) {
results.add(object.mapEncode());
}
// Send the response back to the Console.
queryResponse(handle, results, "_data");
} else {
// Look up QmfAgentData objects by the SchemaClassId obtained from the query
// This is implemented by a linear search and allows searches with only the className specified.
// Linear searches clearly don't scale brilliantly, but the number of QmfAgentData objects managed
// by an Agent is generally fairly small, so it should be OK. Note that this is the same approach
// taken by the C++ broker ManagementAgent, so if it's a problem here........
// N.B. the results list declared here is a generic List of Objects. We *must* only pass a List of
// Map to queryResponse(), but conversely if the response items are sortable we need to sort them
// before doing mapEncode(). Unfortunately we don't know if the items are sortable a priori so
// we either add a Map or we add a QmfAgentData, then sort then mapEncode() each item. I'm not
// sure of a more elegant way to do this without creating two lists, which might not be so bad
// but we don't know the size of the list a priori either.
List results = new ArrayList(_objectIndex.size());
// It's unlikely that evaluating this query will return a mixture of sortable and notSortable
// QmfAgentData objects, but it's best to check if that has occurred as accidentally passing a
// List of QmfAgentData instead of a List of Map to queryResponse() will break things.
boolean sortable = false;
boolean notSortable = false;
for (QmfAgentData object : _objectIndex.values()) {
if (!object.isDeleted() && query.evaluate(object)) {
if (object.isSortable()) {
// If QmfAgentData is marked sortable we add the QmfAgentData object to the List
// so we can sort first before mapEncoding.
results.add(object);
sortable = true;
} else {
// If QmfAgentData is not marked sortable we mapEncode immediately and add the Map to List.
results.add(object.mapEncode());
notSortable = true;
}
}
}
// results List to avoid sending unconvertable data. Hopefully this condition should never occur.
if (sortable && notSortable) {
_log.info("Query resulted in inconsistent mixture of sortable and non-sortable data.");
results.clear();
} else if (sortable) {
Collections.sort(results);
int length = results.size();
for (int i = 0; i < length; i++) {
QmfAgentData object = (QmfAgentData) results.get(i);
results.set(i, object.mapEncode());
}
}
// Send the response back to the Console.
queryResponse(handle, results, "_data");
}
}
} else {
raiseException(handle, "Query for _what => '" + target + "' not supported");
return;
}
}
use of org.apache.qpid.qmf2.console.Console in project qpid by apache.
the class Agent method raiseException.
/**
* Send an exception back to the Console.
* @param handle the reply handle that contains the replyTo Address.
* @param message the exception message.
*/
public final void raiseException(final Handle handle, final String message) {
try {
MapMessage response = _syncSession.createMapMessage();
response.setJMSCorrelationID(handle.getCorrelationId());
response.setStringProperty("x-amqp-0-10.app-id", "qmf2");
response.setStringProperty("method", "response");
response.setStringProperty("qmf.opcode", "_exception");
response.setStringProperty("qmf.agent", _name);
response.setStringProperty("qpid.subject", handle.getRoutingKey());
QmfData exception = new QmfData();
exception.setValue("error_text", message);
response.setObject("_values", exception.mapEncode());
sendResponse(handle, response);
} catch (JMSException jmse) {
_log.info("JMSException {} caught in handleLocateRequest()", jmse.getMessage());
}
}
use of org.apache.qpid.qmf2.console.Console in project qpid by apache.
the class ConnectionProxy method createConnection.
/**
* Actually create the Qpid Connection and QMF2 Console specified in the Constructor.
*/
private synchronized void createConnection() {
//System.out.println("ConnectionProxy createConnection() name: " + _name + ", thread: " + Thread.currentThread().getId() + ", creating connection to " + _url + ", options " + _connectionOptions);
try {
_connection = ConnectionHelper.createConnection(_url, _connectionOptions);
if (_connection != null) {
_connection.setExceptionListener(this);
// front of the WorkQueue if it exceeds a particular size.
if (_disableEvents) {
_console = new Console(_name, null, null, null);
_console.disableEvents();
} else {
BlockingNotifier notifier = new BlockingNotifier();
_console = new Console(_name, null, notifier, null);
}
_console.addConnection(_connection);
_connected = true;
_expireCount = UNUSED_THRESHOLD;
notifyAll();
}
} catch (Exception ex) {
_log.info("Exception {} caught in ConnectionProxy constructor.", ex.getMessage());
_connected = false;
}
}
use of org.apache.qpid.qmf2.console.Console in project qpid by apache.
the class Console method removeConnection.
/**
* Remove the AMQP connection from the console. Un-does the addConnection() operation, and releases
* any Agents associated with the connection. All blocking methods are unblocked and given a failure
* status. All outstanding asynchronous operations are cancelled without producing WorkItems.
*
* @param conn a javax.jms.Connection
*/
public void removeConnection(final Connection conn) throws QmfException {
if (conn != _connection) {
throw new QmfException("Attempt to delete unknown connection");
}
try {
_timer.cancel();
// Should we close() the connection here or just stop() it ???
_connection.close();
} catch (JMSException jmse) {
throw new QmfException("Failed to remove connection, caught JMSException " + jmse.getMessage());
}
_connection = null;
}
use of org.apache.qpid.qmf2.console.Console in project qpid by apache.
the class Console method refreshSubscription.
/**
* Renews a subscription identified by SubscriptionId.
* <p>
* The Console may request a new subscription duration by providing a requested lifetime. This method may be called
* asynchronously by providing a replyHandle argument.
* <p>
* When called asynchronously, the result of this method call is returned in a SUBSCRIBE_RESPONSE WorkItem.
* <p>
* Timeout can be used to override the console's default reply timeout.
* <p>
* When called synchronously, this method returns a class SubscribeParams object containing the result of the
* subscription request.
*
* @param subscriptionId the ID of the subscription to be refreshed
* @param options a String representation of a Map containing the options in the form
* <pre>"{lifetime:<value>, replyHandle:<value>, timeout:<value>}"</pre>
* they are optional and may appear in any order.
* <pre>
* <b>lifetime</b> requests a new subscription duration.
* <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 SubscribeParams refreshSubscription(String subscriptionId, final String options) throws QmfException {
if (subscriptionId == null) {
throw new QmfException("Called refreshSubscription() with null subscriptionId");
}
SubscriptionManager subscription = _subscriptionById.get(subscriptionId);
if (subscription == null) {
throw new QmfException("Called refreshSubscription() with invalid subscriptionId");
}
String consoleHandle = subscription.getConsoleHandle();
Agent agent = subscription.getAgent();
if (!agent.isActive()) {
throw new QmfException("Called refreshSubscription() with inactive agent");
}
String agentName = agent.getName();
// Initialise optional values to defaults;
long lifetime = 0;
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("timeout")) {
timeout = optMap.getLongValue("timeout");
}
if (optMap.hasValue("replyHandle")) {
replyHandle = optMap.getStringValue("replyHandle");
}
}
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", "_subscribe_refresh_indication");
request.setStringProperty("qpid.subject", agentName);
request.setObject("_subscription_id", subscriptionId);
if (lifetime > 0) {
request.setObject("_duration", lifetime);
}
// it would be somewhat unfortunate if their response got interleaved with ours!!
synchronized (this) {
if (_subscriptionEmulationEnabled && agentName.equals(_brokerAgentName)) {
// If the Agent is the broker Agent we emulate the Subscription on the Console
subscription.refresh();
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
Message response = _responder.receive(timeout * 1000);
if (response == null) {
subscription.cancel();
_log.info("No response received in refreshSubscription()");
throw new QmfException("No response received for Console.refreshSubscription()");
}
SubscribeParams result = new SubscribeParams(consoleHandle, AMQPMessage.getMap(response));
subscriptionId = result.getSubscriptionId();
if (subscriptionId == null) {
subscription.cancel();
} else {
subscription.setDuration(result.getLifetime());
subscription.refresh();
}
return result;
}
}
// If this is an asynchronous request return without waiting for a response
return null;
} catch (JMSException jmse) {
_log.info("JMSException {} caught in refreshSubscription()", jmse.getMessage());
throw new QmfException(jmse.getMessage());
}
}
Aggregations