use of org.apache.qpid.server.message.RoutingResult in project qpid-broker-j by apache.
the class AbstractExchange method route.
@Override
public <M extends ServerMessage<? extends StorableMessageMetaData>> RoutingResult<M> route(final M message, final String routingAddress, final InstanceProperties instanceProperties) {
if (_virtualHost.getState() != State.ACTIVE) {
throw new VirtualHostUnavailableException(this._virtualHost);
}
final RoutingResult<M> routingResult = new RoutingResult<>(message);
Map<AbstractExchange<?>, Set<String>> currentThreadMap = CURRENT_ROUTING.get();
boolean topLevel = currentThreadMap == null;
try {
if (topLevel) {
currentThreadMap = new HashMap<>();
CURRENT_ROUTING.set(currentThreadMap);
}
Set<String> existingRoutes = currentThreadMap.get(this);
if (existingRoutes == null) {
currentThreadMap.put(this, Collections.singleton(routingAddress));
} else if (existingRoutes.contains(routingAddress)) {
return routingResult;
} else {
existingRoutes = new HashSet<>(existingRoutes);
existingRoutes.add(routingAddress);
currentThreadMap.put(this, existingRoutes);
}
_receivedMessageCount.incrementAndGet();
_receivedMessageSize.addAndGet(message.getSizeIncludingHeader());
doRoute(message, routingAddress, instanceProperties, routingResult);
if (!routingResult.hasRoutes()) {
MessageDestination alternateBindingDestination = getAlternateBindingDestination();
if (alternateBindingDestination != null) {
routingResult.add(alternateBindingDestination.route(message, routingAddress, instanceProperties));
}
}
if (routingResult.hasRoutes()) {
_routedMessageCount.incrementAndGet();
_routedMessageSize.addAndGet(message.getSizeIncludingHeader());
} else {
_droppedMessageCount.incrementAndGet();
_droppedMessageSize.addAndGet(message.getSizeIncludingHeader());
}
return routingResult;
} finally {
if (topLevel) {
CURRENT_ROUTING.set(null);
}
}
}
use of org.apache.qpid.server.message.RoutingResult in project qpid-broker-j by apache.
the class DefaultDestination method route.
@Override
public <M extends ServerMessage<? extends StorableMessageMetaData>> RoutingResult<M> route(M message, String routingAddress, InstanceProperties instanceProperties) {
RoutingResult<M> result = new RoutingResult<>(message);
DestinationAddress destinationAddress = new DestinationAddress(_virtualHost, routingAddress);
MessageDestination messageDestination = destinationAddress.getMessageDestination();
if (messageDestination != null) {
result.add(messageDestination.route(message, destinationAddress.getRoutingKey(), instanceProperties));
}
return result;
}
use of org.apache.qpid.server.message.RoutingResult 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.RoutingResult in project qpid-broker-j by apache.
the class AMQChannelTest method testPublishContentHeaderWhenMessageAuthorizationSucceeds.
public void testPublishContentHeaderWhenMessageAuthorizationSucceeds() throws Exception {
when(_virtualHost.getDefaultDestination()).thenReturn(_messageDestination);
when(_virtualHost.getMessageStore()).thenReturn(new NullMessageStore() {
@Override
public <T extends StorableMessageMetaData> MessageHandle<T> addMessage(final T metaData) {
MessageHandle messageHandle = new StoredMemoryMessage(1, metaData);
return messageHandle;
}
});
final ArgumentCaptor<ServerMessage> messageCaptor = ArgumentCaptor.forClass(ServerMessage.class);
doAnswer(new Answer() {
@Override
public Object answer(final InvocationOnMock invocation) throws Throwable {
ServerMessage message = messageCaptor.getValue();
return new RoutingResult(message);
}
}).when(_messageDestination).route(messageCaptor.capture(), eq(ROUTING_KEY.toString()), any(InstanceProperties.class));
AMQChannel channel = new AMQChannel(_amqConnection, 1, _virtualHost.getMessageStore());
BasicContentHeaderProperties properties = new BasicContentHeaderProperties();
properties.setUserId(_amqConnection.getAuthorizedPrincipal().getName());
channel.receiveBasicPublish(AMQShortString.EMPTY_STRING, ROUTING_KEY, false, false);
channel.receiveMessageHeader(properties, 0);
verify(_messageDestination).route((ServerMessage) any(), eq(ROUTING_KEY.toString()), any(InstanceProperties.class));
}
use of org.apache.qpid.server.message.RoutingResult 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();
}
}
Aggregations