use of org.apache.qpid.server.message.InstanceProperties in project qpid-broker-j by apache.
the class AMQChannel method deliverCurrentMessageIfComplete.
private void deliverCurrentMessageIfComplete() {
// check and deliver if header says body length is zero
if (_currentMessage.allContentReceived()) {
MessagePublishInfo info = _currentMessage.getMessagePublishInfo();
String routingKey = AMQShortString.toString(info.getRoutingKey());
String exchangeName = AMQShortString.toString(info.getExchange());
try {
final MessageDestination destination = _currentMessage.getDestination();
ContentHeaderBody contentHeader = _currentMessage.getContentHeader();
_connection.checkAuthorizedMessagePrincipal(AMQShortString.toString(contentHeader.getProperties().getUserId()));
_publishAuthCache.authorisePublish(destination, routingKey, info.isImmediate(), _connection.getLastReadTime());
if (_confirmOnPublish) {
_confirmedMessageCounter++;
}
long bodySize = _currentMessage.getSize();
long timestamp = contentHeader.getProperties().getTimestamp();
try {
final MessagePublishInfo messagePublishInfo = _currentMessage.getMessagePublishInfo();
final MessageMetaData messageMetaData = new MessageMetaData(messagePublishInfo, contentHeader, getConnection().getLastReadTime());
final MessageHandle<MessageMetaData> handle = _messageStore.addMessage(messageMetaData);
int bodyCount = _currentMessage.getBodyCount();
if (bodyCount > 0) {
for (int i = 0; i < bodyCount; i++) {
ContentBody contentChunk = _currentMessage.getContentChunk(i);
handle.addContent(contentChunk.getPayload());
contentChunk.dispose();
}
}
final StoredMessage<MessageMetaData> storedMessage = handle.allContentAdded();
final AMQMessage amqMessage = new AMQMessage(storedMessage, _connection.getReference());
try (MessageReference reference = amqMessage.newReference()) {
_currentMessage = null;
final boolean immediate = messagePublishInfo.isImmediate();
final InstanceProperties instanceProperties = new InstanceProperties() {
@Override
public Object getProperty(final Property prop) {
switch(prop) {
case EXPIRATION:
return amqMessage.getExpiration();
case IMMEDIATE:
return immediate;
case PERSISTENT:
return amqMessage.isPersistent();
case MANDATORY:
return messagePublishInfo.isMandatory();
case REDELIVERED:
return false;
}
return null;
}
};
final RoutingResult<AMQMessage> result = destination.route(amqMessage, amqMessage.getInitialRoutingAddress(), instanceProperties);
int enqueues = result.send(_transaction, immediate ? _immediateAction : null);
if (enqueues == 0) {
boolean mandatory = amqMessage.isMandatory();
boolean closeOnNoRoute = _connection.isCloseWhenNoRoute();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Unroutable message exchange='{}', routing key='{}', mandatory={}," + " transactionalSession={}, closeOnNoRoute={}, confirmOnPublish={}", exchangeName, routingKey, mandatory, isTransactional(), closeOnNoRoute, _confirmOnPublish);
}
int errorCode = ErrorCodes.NO_ROUTE;
String errorMessage = String.format("No route for message with exchange '%s' and routing key '%s'", exchangeName, routingKey);
if (result.containsReject(RejectType.LIMIT_EXCEEDED)) {
errorCode = ErrorCodes.RESOURCE_ERROR;
errorMessage = errorMessage + ":" + result.getRejectReason();
}
if (mandatory && isTransactional() && !_confirmOnPublish && _connection.isCloseWhenNoRoute()) {
_connection.sendConnectionClose(errorCode, errorMessage, _channelId);
} else {
if (mandatory || amqMessage.isImmediate()) {
if (_confirmOnPublish) {
_connection.writeFrame(new AMQFrame(_channelId, new BasicNackBody(_confirmedMessageCounter, false, false)));
}
_transaction.addPostTransactionAction(new WriteReturnAction(errorCode, errorMessage, amqMessage));
} else {
if (_confirmOnPublish) {
_connection.writeFrame(new AMQFrame(_channelId, new BasicAckBody(_confirmedMessageCounter, false)));
}
message(ExchangeMessages.DISCARDMSG(exchangeName, routingKey));
}
}
} else {
if (_confirmOnPublish) {
recordFuture(Futures.immediateFuture(null), new ServerTransaction.Action() {
private final long _deliveryTag = _confirmedMessageCounter;
@Override
public void postCommit() {
BasicAckBody body = _connection.getMethodRegistry().createBasicAckBody(_deliveryTag, false);
_connection.writeFrame(body.generateFrame(_channelId));
}
@Override
public void onRollback() {
final BasicNackBody body = new BasicNackBody(_deliveryTag, false, false);
_connection.writeFrame(new AMQFrame(_channelId, body));
}
});
}
}
}
} finally {
_connection.registerMessageReceived(bodySize);
if (isTransactional()) {
_connection.registerTransactedMessageReceived();
}
_currentMessage = null;
}
} catch (AccessControlException e) {
_connection.sendConnectionClose(ErrorCodes.ACCESS_REFUSED, e.getMessage(), getChannelId());
}
}
}
use of org.apache.qpid.server.message.InstanceProperties in project qpid-broker-j by apache.
the class NodeReceivingDestination method send.
@Override
public void send(final ServerMessage<?> message, final ServerTransaction txn, final SecurityToken securityToken) throws UnroutableMessageException {
final String routingAddress = "".equals(_routingAddress) ? getRoutingAddress(message) : _routingAddress;
_destination.authorisePublish(securityToken, Collections.singletonMap("routingKey", routingAddress));
final InstanceProperties instanceProperties = new InstanceProperties() {
@Override
public Object getProperty(final Property prop) {
switch(prop) {
case MANDATORY:
return false;
case REDELIVERED:
return false;
case PERSISTENT:
return message.isPersistent();
case IMMEDIATE:
return false;
case EXPIRATION:
return message.getExpiration();
}
return null;
}
};
RoutingResult result = _destination.route(message, routingAddress, instanceProperties);
final int enqueues = result.send(txn, null);
if (enqueues == 0) {
if (!_discardUnroutable) {
final String errorMessage;
final AmqpError errorCode;
if (result.isRejected()) {
if (result.containsReject(RejectType.LIMIT_EXCEEDED)) {
errorCode = AmqpError.RESOURCE_LIMIT_EXCEEDED;
} else if (result.containsReject(RejectType.PRECONDITION_FAILED)) {
errorCode = AmqpError.PRECONDITION_FAILED;
} else {
errorCode = AmqpError.ILLEGAL_STATE;
}
errorMessage = result.getRejectReason();
} else {
errorCode = AmqpError.NOT_FOUND;
errorMessage = String.format("Unknown destination '%s'", routingAddress);
}
throw new UnroutableMessageException(errorCode, errorMessage);
} else {
_eventLogger.message(ExchangeMessages.DISCARDMSG(_destination.getName(), routingAddress));
}
}
}
use of org.apache.qpid.server.message.InstanceProperties in project qpid-broker-j by apache.
the class ServerSessionDelegate method messageTransfer.
@Override
public void messageTransfer(ServerSession ssn, final MessageTransfer xfr) {
try {
if (ssn.blockingTimeoutExceeded()) {
getEventLogger(ssn).message(ChannelMessages.FLOW_CONTROL_IGNORED());
ssn.close(ErrorCodes.MESSAGE_TOO_LARGE, "Session flow control was requested, but not enforced by sender");
} else if (xfr.getBodySize() > ssn.getConnection().getMaxMessageSize()) {
exception(ssn, xfr, ExecutionErrorCode.RESOURCE_LIMIT_EXCEEDED, "Message size of " + xfr.getBodySize() + " greater than allowed maximum of " + ssn.getConnection().getMaxMessageSize());
} else {
final MessageDestination destination = getDestinationForMessage(ssn, xfr);
final DeliveryProperties delvProps = xfr.getHeader() == null ? null : xfr.getHeader().getDeliveryProperties();
if (delvProps != null && delvProps.hasTtl() && !delvProps.hasExpiration()) {
delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl());
}
final MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr);
final NamedAddressSpace virtualHost = getAddressSpace(ssn);
try {
ssn.getAMQPConnection().checkAuthorizedMessagePrincipal(getMessageUserId(xfr));
ssn.authorisePublish(destination, messageMetaData.getRoutingKey(), messageMetaData.isImmediate(), ssn.getAMQPConnection().getLastReadTime());
} catch (AccessControlException e) {
ExecutionErrorCode errorCode = ExecutionErrorCode.UNAUTHORIZED_ACCESS;
exception(ssn, xfr, errorCode, e.getMessage());
return;
}
final MessageStore store = virtualHost.getMessageStore();
final StoredMessage<MessageMetaData_0_10> storeMessage = createStoreMessage(xfr, messageMetaData, store);
final MessageTransferMessage message = new MessageTransferMessage(storeMessage, ssn.getReference());
MessageReference<MessageTransferMessage> reference = message.newReference();
try {
final InstanceProperties instanceProperties = new InstanceProperties() {
@Override
public Object getProperty(final Property prop) {
switch(prop) {
case EXPIRATION:
return message.getExpiration();
case IMMEDIATE:
return message.isImmediate();
case MANDATORY:
return (delvProps == null || !delvProps.getDiscardUnroutable()) && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT;
case PERSISTENT:
return message.isPersistent();
case REDELIVERED:
return delvProps.getRedelivered();
}
return null;
}
};
RoutingResult<MessageTransferMessage> routingResult = ssn.enqueue(message, instanceProperties, destination);
boolean explictlyRejected = routingResult.containsReject(RejectType.LIMIT_EXCEEDED);
if (!routingResult.hasRoutes() || explictlyRejected) {
boolean closeWhenNoRoute = ssn.getAMQPConnection().getPort().getCloseWhenNoRoute();
boolean discardUnroutable = delvProps != null && delvProps.getDiscardUnroutable();
if (!discardUnroutable && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT) {
RangeSet rejects = RangeSetFactory.createRangeSet();
rejects.add(xfr.getId());
MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable");
ssn.invoke(reject);
} else if (!discardUnroutable && closeWhenNoRoute && explictlyRejected) {
ExecutionErrorCode code = ExecutionErrorCode.RESOURCE_LIMIT_EXCEEDED;
String errorMessage = String.format("No route for message with destination '%s' and routing key '%s' : %s", xfr.getDestination(), message.getInitialRoutingAddress(), routingResult.getRejectReason());
ExecutionException ex = new ExecutionException();
ex.setErrorCode(code);
ex.setDescription(errorMessage);
ssn.invoke(ex);
ssn.close(ErrorCodes.RESOURCE_ERROR, errorMessage);
return;
} else {
getEventLogger(ssn).message(ExchangeMessages.DISCARDMSG(destination.getName(), messageMetaData.getRoutingKey()));
}
}
// TODO: we currently do not send MessageAccept when AcceptMode is EXPLICIT
if (ssn.isTransactional()) {
ssn.processed(xfr);
} else {
ssn.recordFuture(Futures.immediateFuture(null), new CommandProcessedAction(ssn, xfr));
}
} catch (VirtualHostUnavailableException e) {
getServerConnection(ssn).sendConnectionCloseAsync(ConnectionCloseCode.CONNECTION_FORCED, e.getMessage());
} finally {
reference.release();
}
}
} finally {
xfr.dispose();
}
}
use of org.apache.qpid.server.message.InstanceProperties in project qpid-broker-j by apache.
the class TopicExchangeTest method testRouteToQueueWithSelector.
public void testRouteToQueueWithSelector() {
String bindingKey = "mybinding";
Queue<?> queue = _vhost.createChild(Queue.class, Collections.singletonMap(Queue.NAME, getTestName() + "_queue"));
InstanceProperties instanceProperties = mock(InstanceProperties.class);
ServerMessage<?> matchingMessage = createTestMessage(Collections.singletonMap("prop", true));
ServerMessage<?> unmatchingMessage = createTestMessage(Collections.singletonMap("prop", false));
boolean bind = _exchange.bind(queue.getName(), bindingKey, Collections.singletonMap(JMS_SELECTOR.toString(), "prop = True"), false);
assertTrue("Bind operation should be successful", bind);
RoutingResult<ServerMessage<?>> result = _exchange.route(matchingMessage, "mybinding", instanceProperties);
assertTrue("Message with matching selector not routed to queue", result.hasRoutes());
result = _exchange.route(unmatchingMessage, "mybinding", instanceProperties);
assertFalse("Message without matching selector unexpectedly routed to queue", result.hasRoutes());
boolean unbind = _exchange.unbind(queue.getName(), bindingKey);
assertTrue("Unbind operation should be successful", unbind);
result = _exchange.route(matchingMessage, "mybinding", instanceProperties);
assertFalse("Message with matching selector unexpectedly routed to queue after unbind", result.hasRoutes());
}
use of org.apache.qpid.server.message.InstanceProperties in project qpid-broker-j by apache.
the class TopicExchangeTest method testUpdateBindingAddingSelector.
public void testUpdateBindingAddingSelector() throws Exception {
String bindingKey = "mybinding";
Queue<?> queue = _vhost.createChild(Queue.class, Collections.singletonMap(Queue.NAME, getTestName() + "_queue"));
InstanceProperties instanceProperties = mock(InstanceProperties.class);
ServerMessage<?> message = createTestMessage(Collections.singletonMap("prop", false));
boolean bind = _exchange.bind(queue.getName(), bindingKey, Collections.emptyMap(), false);
assertTrue("Bind operation should be successful", bind);
RoutingResult<ServerMessage<?>> result = _exchange.route(message, bindingKey, instanceProperties);
assertTrue("Message not routed to queue", result.hasRoutes());
_exchange.replaceBinding(bindingKey, queue, Collections.singletonMap(JMS_SELECTOR.toString(), "prop = false"));
result = _exchange.route(message, bindingKey, instanceProperties);
assertTrue("Message that matches selector not routed to queue after rebind", result.hasRoutes());
result = _exchange.route(message = createTestMessage(Collections.singletonMap("prop", true)), bindingKey, instanceProperties);
assertFalse("Message that does not match selector routed to queue after rebind", result.hasRoutes());
}
Aggregations