use of javax.jms.MapMessage in project qpid by apache.
the class Agent method handleLocateRequest.
/**
* Send an _agent_locate_response back to the Console that requested the locate.
* @param handle the reply handle that contains the replyTo Address.
*/
private final void handleLocateRequest(final Handle handle) {
try {
MapMessage response = _syncSession.createMapMessage();
response.setStringProperty("x-amqp-0-10.app-id", "qmf2");
response.setStringProperty("method", "indication");
response.setStringProperty("qmf.opcode", "_agent_locate_response");
response.setStringProperty("qmf.agent", _name);
response.setStringProperty("qpid.subject", handle.getRoutingKey());
setValue("_timestamp", System.currentTimeMillis() * 1000000l);
response.setObject("_values", mapEncode());
sendResponse(handle, response);
} catch (JMSException jmse) {
_log.info("JMSException {} caught in handleLocateRequest()", jmse.getMessage());
}
}
use of javax.jms.MapMessage in project qpid by apache.
the class Agent method methodResponse.
/**
* Indicate to the Agent that the application has completed processing a method request.
* <p>
* See the description of the METHOD_CALL WorkItem.
* @param methodName the method's name.
* @param handle the reply handle from WorkItem.
* @param outArgs the output argument map.
* @param error the error object that was created if the method failed in any way, otherwise null.
*/
public final void methodResponse(final String methodName, final Handle handle, final QmfData outArgs, final QmfData error) {
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", "_method_response");
response.setStringProperty("qmf.agent", _name);
response.setStringProperty("qpid.subject", handle.getRoutingKey());
if (error == null) {
if (outArgs != null) {
response.setObject("_arguments", outArgs.mapEncode());
if (outArgs.getSubtypes() != null) {
response.setObject("_subtypes", outArgs.getSubtypes());
}
}
} else {
Map<String, Object> errorMap = error.mapEncode();
for (Map.Entry<String, Object> entry : errorMap.entrySet()) {
response.setObject(entry.getKey(), entry.getValue());
}
}
sendResponse(handle, response);
} catch (JMSException jmse) {
_log.info("JMSException {} caught in methodResponse()", jmse.getMessage());
}
}
use of javax.jms.MapMessage in project qpid by apache.
the class AMQPMessage method getList.
/**
* JMS QMF returns amqp/list types as a BytesMessage this method decodes that into a java.util.List
* <p>
* Taken from Gordon Sim's initial JMS QMF Example using the BBDecoder
* <p>
* Trivia: This block of code from Gordon Sim is the seed that spawned the whole of this Java QMF2 API
* implementation - cheers Gordon.
*
* @param message amqp/list encoded JMS Message
* @return a java.util.List decoded from Message
*/
@SuppressWarnings("unchecked")
public static <T> List<T> getList(final Message message) throws JMSException {
if (message == null) {
throw new MessageFormatException("Attempting to do AMQPMessage.getList() on null Message");
} else if (message instanceof BytesMessage) {
BytesMessage msg = (BytesMessage) message;
//only handles responses up to 2^31-1 bytes long
byte[] data = new byte[(int) msg.getBodyLength()];
msg.readBytes(data);
BBDecoder decoder = new BBDecoder();
decoder.init(ByteBuffer.wrap(data));
return (List<T>) decoder.readList();
} else if (message instanceof MapMessage) {
/*
* In Qpid version 0.20 instead of exposing amqp/list as a BytesMessage as above rather it is exposed
* as a MapMessage!!??? the Object Keys are the indices into the List. We create a java.util.List
* out of this by iterating through the getMapNames() Enumeration and copying the Objects into the List.
* This amount of copying doesn't feel healthy and we can't even work out the capacity for the List
* a priori, but I'm not sure of a better way at present. I can't say I much like how amqp/list or indeed
* amqp/map are currently encoded. I'd *much* prefer to see them exposed as JMS ObjectMessage.
*/
MapMessage msg = (MapMessage) message;
// Initial capacity of 50, can we better estimate this?
List resultList = new ArrayList(50);
for (Enumeration e = msg.getMapNames(); e.hasMoreElements(); ) {
String key = (String) e.nextElement();
resultList.add(msg.getObject(key));
}
return resultList;
} else {
return null;
}
}
use of javax.jms.MapMessage in project qpid by apache.
the class Console method invokeMethod.
/**
* Invoke the named method on the named Agent.
* <p>
* Intended to by called by the AgentProxy. Shouldn't generally be called directly by Console applications.
*
* @param agent the Agent to invoke the method on.
* @param content an unordered set of key/value pairs comprising the method arguments.
* @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 the method response Arguments in Map form
*/
public MethodResult invokeMethod(final Agent agent, final Map<String, Object> content, final String replyHandle, int timeout) throws QmfException {
if (!agent.isActive()) {
throw new QmfException("Called invokeMethod() with inactive agent");
}
String agentName = agent.getName();
timeout = (timeout < 1) ? _replyTimeout : timeout;
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", "_method_request");
request.setStringProperty("qpid.subject", agentName);
for (Map.Entry<String, Object> entry : content.entrySet()) {
request.setObject(entry.getKey(), entry.getValue());
}
// it would be somewhat unfortunate if their response got interleaved with ours!!
synchronized (this) {
_requester.send(request);
if (replyHandle == null) {
// If this is a synchronous request get the response
Message response = _responder.receive(timeout * 1000);
if (response == null) {
_log.info("No response received in invokeMethod()");
throw new QmfException("No response received for Console.invokeMethod()");
}
MethodResult result = new MethodResult(AMQPMessage.getMap(response));
QmfException exception = result.getQmfException();
if (exception != null) {
throw exception;
}
return result;
}
}
// If this is an asynchronous request return without waiting for a response
return null;
} catch (JMSException jmse) {
_log.info("JMSException {} caught in invokeMethod()", jmse.getMessage());
throw new QmfException(jmse.getMessage());
}
}
use of javax.jms.MapMessage 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());
}
}
Aggregations