use of org.apache.qpid.server.filter.MessageFilter in project qpid-broker-j by apache.
the class AbstractQueue method onOpen.
@Override
protected void onOpen() {
super.onOpen();
final Map<String, Object> attributes = getActualAttributes();
final LinkedHashMap<String, Object> arguments = new LinkedHashMap<>(attributes);
arguments.put(Queue.EXCLUSIVE, _exclusive);
arguments.put(Queue.LIFETIME_POLICY, getLifetimePolicy());
_arguments = Collections.synchronizedMap(arguments);
_queueHouseKeepingTask = new AdvanceConsumersTask();
final Set<SessionPrincipal> sessionPrincipals = getSessionPrincipals();
final AMQPSession<?, ?> session;
if (sessionPrincipals.isEmpty()) {
session = null;
} else {
final SessionPrincipal sessionPrincipal = sessionPrincipals.iterator().next();
session = sessionPrincipal.getSession();
}
if (session != null) {
switch(_exclusive) {
case PRINCIPAL:
_exclusiveOwner = session.getAMQPConnection().getAuthorizedPrincipal();
break;
case CONTAINER:
_exclusiveOwner = session.getAMQPConnection().getRemoteContainerName();
break;
case CONNECTION:
_exclusiveOwner = session.getAMQPConnection();
addExclusivityConstraint(session.getAMQPConnection());
break;
case SESSION:
_exclusiveOwner = session;
addExclusivityConstraint(session);
break;
case NONE:
case LINK:
case SHARED_SUBSCRIPTION:
break;
default:
throw new ServerScopedRuntimeException("Unknown exclusivity policy: " + _exclusive + " this is a coding error inside Qpid");
}
} else if (_exclusive == ExclusivityPolicy.PRINCIPAL) {
if (attributes.get(Queue.OWNER) != null) {
final String owner = String.valueOf(attributes.get(Queue.OWNER));
Principal ownerPrincipal;
try {
ownerPrincipal = new GenericPrincipal(owner);
} catch (IllegalArgumentException e) {
ownerPrincipal = new GenericPrincipal(owner + "@('')");
}
_exclusiveOwner = new AuthenticatedPrincipal(ownerPrincipal);
}
} else if (_exclusive == ExclusivityPolicy.CONTAINER) {
if (attributes.get(Queue.OWNER) != null) {
_exclusiveOwner = String.valueOf(attributes.get(Queue.OWNER));
}
}
if (getLifetimePolicy() == LifetimePolicy.DELETE_ON_CONNECTION_CLOSE) {
if (session != null) {
addLifetimeConstraint(session.getAMQPConnection());
} else {
throw new IllegalArgumentException("Queues created with a lifetime policy of " + getLifetimePolicy() + " must be created from a connection.");
}
} else if (getLifetimePolicy() == LifetimePolicy.DELETE_ON_SESSION_END) {
if (session != null) {
addLifetimeConstraint(session);
} else {
throw new IllegalArgumentException("Queues created with a lifetime policy of " + getLifetimePolicy() + " must be created from a connection.");
}
} else if (getLifetimePolicy() == LifetimePolicy.DELETE_ON_CREATING_LINK_CLOSE) {
if (_creatingLinkInfo != null) {
final LinkModel link;
if (_creatingLinkInfo.isSendingLink()) {
link = _virtualHost.getSendingLink(_creatingLinkInfo.getRemoteContainerId(), _creatingLinkInfo.getLinkName());
} else {
link = _virtualHost.getReceivingLink(_creatingLinkInfo.getRemoteContainerId(), _creatingLinkInfo.getLinkName());
}
addLifetimeConstraint(link);
} else {
throw new IllegalArgumentException("Queues created with a lifetime policy of " + getLifetimePolicy() + " must be created from a AMQP 1.0 link.");
}
}
switch(getMessageGroupType()) {
case NONE:
_messageGroupManager = null;
break;
case STANDARD:
_messageGroupManager = new AssignedConsumerMessageGroupManager(getMessageGroupKeyOverride(), getMaximumDistinctGroups());
break;
case SHARED_GROUPS:
_messageGroupManager = new DefinedGroupMessageGroupManager(getMessageGroupKeyOverride(), getMessageGroupDefaultGroup(), this);
break;
default:
throw new IllegalArgumentException("Unknown messageGroupType type " + _messageGroupType);
}
_mimeTypeToFileExtension = getContextValue(Map.class, MAP_OF_STRING_STRING, MIME_TYPE_TO_FILE_EXTENSION);
_messageConversionExceptionHandlingPolicy = getContextValue(MessageConversionExceptionHandlingPolicy.class, MESSAGE_CONVERSION_EXCEPTION_HANDLING_POLICY);
_flowToDiskThreshold = getAncestor(Broker.class).getFlowToDiskThreshold();
if (_defaultFilters != null) {
final QpidServiceLoader qpidServiceLoader = new QpidServiceLoader();
final Map<String, MessageFilterFactory> messageFilterFactories = qpidServiceLoader.getInstancesByType(MessageFilterFactory.class);
for (Map.Entry<String, Map<String, List<String>>> entry : _defaultFilters.entrySet()) {
final String name = String.valueOf(entry.getKey());
final Map<String, List<String>> filterValue = entry.getValue();
if (filterValue.size() == 1) {
final String filterTypeName = String.valueOf(filterValue.keySet().iterator().next());
final MessageFilterFactory filterFactory = messageFilterFactories.get(filterTypeName);
if (filterFactory != null) {
final List<String> filterArguments = filterValue.values().iterator().next();
// check the arguments are valid
filterFactory.newInstance(filterArguments);
_defaultFiltersMap.put(name, new Callable<MessageFilter>() {
@Override
public MessageFilter call() {
return filterFactory.newInstance(filterArguments);
}
});
} else {
throw new IllegalArgumentException("Unknown filter type " + filterTypeName + ", known types are: " + messageFilterFactories.keySet());
}
} else {
throw new IllegalArgumentException("Filter value should be a map with one entry, having the type as key and the value being the filter arguments, not " + filterValue);
}
}
}
if (isHoldOnPublishEnabled()) {
_holdMethods.add(new HoldMethod() {
@Override
public boolean isHeld(final MessageReference<?> messageReference, final long evaluationTime) {
return messageReference.getMessage().getMessageHeader().getNotValidBefore() >= evaluationTime;
}
});
}
if (getAlternateBinding() != null) {
final String alternateDestination = getAlternateBinding().getDestination();
_alternateBindingDestination = getOpenedMessageDestination(alternateDestination);
if (_alternateBindingDestination != null) {
_alternateBindingDestination.addReference(this);
} else {
LOGGER.warn("Cannot find alternate binding destination '{}' for queue '{}'", alternateDestination, toString());
}
}
createOverflowPolicyHandlers(_overflowPolicy);
updateAlertChecks();
}
use of org.apache.qpid.server.filter.MessageFilter in project qpid-broker-j by apache.
the class ServerSessionDelegate method messageSubscribe.
@Override
public void messageSubscribe(ServerSession session, MessageSubscribe method) {
/*
TODO - work around broken Python tests
Correct code should read like
if not hasAcceptMode() exception ILLEGAL_ARGUMENT "Accept-mode not supplied"
else if not method.hasAcquireMode() exception ExecutionErrorCode.ILLEGAL_ARGUMENT, "Acquire-mode not supplied"
*/
if (!method.hasAcceptMode()) {
method.setAcceptMode(MessageAcceptMode.EXPLICIT);
}
if (!method.hasAcquireMode()) {
method.setAcquireMode(MessageAcquireMode.PRE_ACQUIRED);
}
if (!method.hasQueue()) {
exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not supplied");
} else {
String destination = method.getDestination();
if (destination == null) {
exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Subscriber must provide a destination. The protocol specification marking the destination argument as optional is considered a mistake.");
} else if (session.getSubscription(destination) != null) {
exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Subscription already exists with destination '" + destination + "'");
} else {
String queueName = method.getQueue();
NamedAddressSpace addressSpace = getAddressSpace(session);
final Collection<MessageSource> sources = new HashSet<>();
final MessageSource queue = addressSpace.getAttainedMessageSource(queueName);
if (method.getArguments() != null && method.getArguments().get("x-multiqueue") instanceof Collection) {
for (Object object : (Collection<Object>) method.getArguments().get("x-multiqueue")) {
String sourceName = String.valueOf(object);
sourceName = sourceName.trim();
if (sourceName.length() != 0) {
MessageSource source = addressSpace.getAttainedMessageSource(sourceName);
if (source == null) {
sources.clear();
break;
} else {
sources.add(source);
}
}
}
queueName = method.getArguments().get("x-multiqueue").toString();
} else if (queue != null) {
sources.add(queue);
}
if (sources.isEmpty()) {
exception(session, method, ExecutionErrorCode.NOT_FOUND, "Queue: " + queueName + " not found");
} else if (!verifySessionAccess(session, sources)) {
exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
} else {
ProtocolEngine protocolEngine = getServerConnection(session).getAmqpConnection();
FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L, 0L);
FilterManager filterManager = null;
try {
filterManager = FilterManagerFactory.createManager(method.getArguments());
} catch (AMQInvalidArgumentException amqe) {
exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "Exception Creating FilterManager");
return;
}
if (method.hasArguments() && method.getArguments().containsKey(AMQPFilterTypes.REPLAY_PERIOD.toString())) {
Object value = method.getArguments().get(AMQPFilterTypes.REPLAY_PERIOD.toString());
final long period;
if (value instanceof Number) {
period = ((Number) value).longValue();
} else if (value instanceof String) {
try {
period = Long.parseLong(value.toString());
} catch (NumberFormatException e) {
exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "Cannot parse value " + value + " as a number for filter " + AMQPFilterTypes.REPLAY_PERIOD.toString());
return;
}
} else {
exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "Cannot parse value " + value + " as a number for filter " + AMQPFilterTypes.REPLAY_PERIOD.toString());
return;
}
final long startingFrom = System.currentTimeMillis() - (1000l * period);
if (filterManager == null) {
filterManager = new FilterManager();
}
MessageFilter filter = new ArrivalTimeFilter(startingFrom, period == 0);
filterManager.add(filter.getName(), filter);
}
boolean multiQueue = sources.size() > 1;
ConsumerTarget_0_10 target = new ConsumerTarget_0_10(session, destination, method.getAcceptMode(), method.getAcquireMode(), MessageFlowMode.WINDOW, creditManager, method.getArguments(), multiQueue);
Integer priority = null;
if (method.hasArguments() && method.getArguments().containsKey("x-priority")) {
Object value = method.getArguments().get("x-priority");
if (value instanceof Number) {
priority = ((Number) value).intValue();
} else if (value instanceof String) {
try {
priority = Integer.parseInt(value.toString());
} catch (NumberFormatException e) {
}
}
}
session.register(destination, target);
try {
EnumSet<ConsumerOption> options = EnumSet.noneOf(ConsumerOption.class);
if (method.getAcquireMode() == MessageAcquireMode.PRE_ACQUIRED) {
options.add(ConsumerOption.ACQUIRES);
}
if (method.getAcquireMode() != MessageAcquireMode.NOT_ACQUIRED || method.getAcceptMode() == MessageAcceptMode.EXPLICIT) {
options.add(ConsumerOption.SEES_REQUEUES);
}
if (method.getExclusive()) {
options.add(ConsumerOption.EXCLUSIVE);
}
for (MessageSource source : sources) {
source.addConsumer(target, filterManager, MessageTransferMessage.class, destination, options, priority);
}
target.updateNotifyWorkDesired();
} catch (Queue.ExistingExclusiveConsumer existing) {
exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an exclusive consumer");
} catch (Queue.ExistingConsumerPreventsExclusive exclusive) {
exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an existing consumer - can't subscribe exclusively");
} catch (AccessControlException e) {
exception(session, method, ExecutionErrorCode.UNAUTHORIZED_ACCESS, e.getMessage());
} catch (MessageSource.ConsumerAccessRefused consumerAccessRefused) {
exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an incompatible exclusivity policy");
} catch (MessageSource.QueueDeleted queueDeleted) {
exception(session, method, ExecutionErrorCode.NOT_FOUND, "Queue was deleted");
}
}
}
}
}
use of org.apache.qpid.server.filter.MessageFilter in project qpid-broker-j by apache.
the class AbstractQueue method addConsumerInternal.
private <T extends ConsumerTarget<T>> QueueConsumerImpl<T> addConsumerInternal(final T target, FilterManager filters, final Class<? extends ServerMessage> messageClass, final String consumerName, EnumSet<ConsumerOption> optionSet, final Integer priority) throws ExistingExclusiveConsumer, ConsumerAccessRefused, ExistingConsumerPreventsExclusive, QueueDeleted {
if (isDeleted()) {
throw new QueueDeleted();
}
if (hasExclusiveConsumer()) {
throw new ExistingExclusiveConsumer();
}
Object exclusiveOwner = _exclusiveOwner;
final AMQPSession<?, T> session = target.getSession();
switch(_exclusive) {
case CONNECTION:
if (exclusiveOwner == null) {
exclusiveOwner = session.getAMQPConnection();
addExclusivityConstraint(session.getAMQPConnection());
} else {
if (exclusiveOwner != session.getAMQPConnection()) {
throw new ConsumerAccessRefused();
}
}
break;
case SESSION:
if (exclusiveOwner == null) {
exclusiveOwner = session;
addExclusivityConstraint(session);
} else {
if (exclusiveOwner != session) {
throw new ConsumerAccessRefused();
}
}
break;
case LINK:
if (getConsumerCount() != 0) {
throw new ConsumerAccessRefused();
}
break;
case PRINCIPAL:
Principal currentAuthorizedPrincipal = session.getAMQPConnection().getAuthorizedPrincipal();
if (exclusiveOwner == null) {
exclusiveOwner = currentAuthorizedPrincipal;
} else {
if (!Objects.equals(((Principal) exclusiveOwner).getName(), currentAuthorizedPrincipal.getName())) {
throw new ConsumerAccessRefused();
}
}
break;
case CONTAINER:
if (exclusiveOwner == null) {
exclusiveOwner = session.getAMQPConnection().getRemoteContainerName();
} else {
if (!exclusiveOwner.equals(session.getAMQPConnection().getRemoteContainerName())) {
throw new ConsumerAccessRefused();
}
}
break;
case SHARED_SUBSCRIPTION:
break;
case NONE:
break;
default:
throw new ServerScopedRuntimeException("Unknown exclusivity policy " + _exclusive);
}
boolean exclusive = optionSet.contains(ConsumerOption.EXCLUSIVE);
boolean isTransient = optionSet.contains(ConsumerOption.TRANSIENT);
if (_noLocal && !optionSet.contains(ConsumerOption.NO_LOCAL)) {
optionSet = EnumSet.copyOf(optionSet);
optionSet.add(ConsumerOption.NO_LOCAL);
}
if (exclusive && getConsumerCount() != 0) {
throw new ExistingConsumerPreventsExclusive();
}
if (!_defaultFiltersMap.isEmpty()) {
if (filters == null) {
filters = new FilterManager();
}
for (Map.Entry<String, Callable<MessageFilter>> filter : _defaultFiltersMap.entrySet()) {
if (!filters.hasFilter(filter.getKey())) {
MessageFilter f;
try {
f = filter.getValue().call();
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
// Should never happen
throw new ServerScopedRuntimeException(e);
}
}
filters.add(filter.getKey(), f);
}
}
}
if (_ensureNondestructiveConsumers) {
optionSet = EnumSet.copyOf(optionSet);
optionSet.removeAll(EnumSet.of(ConsumerOption.SEES_REQUEUES, ConsumerOption.ACQUIRES));
}
QueueConsumerImpl<T> consumer = new QueueConsumerImpl<>(this, target, consumerName, filters, messageClass, optionSet, priority);
_exclusiveOwner = exclusiveOwner;
if (exclusive && !isTransient) {
_exclusiveSubscriber = consumer;
}
QueueContext queueContext;
if (filters == null || !filters.startAtTail()) {
queueContext = new QueueContext(getEntries().getHead());
} else {
queueContext = new QueueContext(getEntries().getTail());
}
consumer.setQueueContext(queueContext);
if (_maximumLiveConsumers > 0 && !incrementNumberOfLiveConsumersIfApplicable()) {
consumer.setNonLive(true);
}
_queueConsumerManager.addConsumer(consumer);
if (consumer.isNotifyWorkDesired()) {
_activeSubscriberCount.incrementAndGet();
}
childAdded(consumer);
consumer.addChangeListener(_deletedChildListener);
session.consumerAdded(consumer);
addChangeListener(new AbstractConfigurationChangeListener() {
@Override
public void childRemoved(final ConfiguredObject<?> object, final ConfiguredObject<?> child) {
if (child.equals(consumer)) {
session.consumerRemoved(consumer);
removeChangeListener(this);
}
}
});
return consumer;
}
use of org.apache.qpid.server.filter.MessageFilter in project qpid-broker-j by apache.
the class QueueConsumerImpl method createAttributeMap.
private static Map<String, Object> createAttributeMap(final AMQPSession<?, ?> session, String linkName, FilterManager filters, EnumSet<ConsumerOption> optionSet, Integer priority) {
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(ID, UUID.randomUUID());
String name = session.getAMQPConnection().getConnectionId() + "|" + session.getChannelId() + "|" + linkName;
attributes.put(NAME, name);
attributes.put(EXCLUSIVE, optionSet.contains(ConsumerOption.EXCLUSIVE));
attributes.put(NO_LOCAL, optionSet.contains(ConsumerOption.NO_LOCAL));
attributes.put(DISTRIBUTION_MODE, optionSet.contains(ConsumerOption.ACQUIRES) ? "MOVE" : "COPY");
attributes.put(DURABLE, optionSet.contains(ConsumerOption.DURABLE));
attributes.put(LIFETIME_POLICY, LifetimePolicy.DELETE_ON_SESSION_END);
if (priority != null) {
attributes.put(PRIORITY, priority);
}
if (filters != null) {
Iterator<MessageFilter> iter = filters.filters();
while (iter.hasNext()) {
MessageFilter filter = iter.next();
if (filter instanceof JMSSelectorFilter) {
attributes.put(SELECTOR, ((JMSSelectorFilter) filter).getSelector());
break;
}
}
}
return attributes;
}
use of org.apache.qpid.server.filter.MessageFilter in project qpid-broker-j by apache.
the class AMQChannel method consumeFromSource.
/**
* Subscribe to a queue. We register all subscriptions in the channel so that if the channel is closed we can clean
* up all subscriptions, even if the client does not explicitly unsubscribe from all queues.
*
* @param tag the tag chosen by the client (if null, server will generate one)
* @param sources the queues to subscribe to
* @param acks Are acks enabled for this subscriber
* @param arguments Filters to apply to this subscriber
*
* @param exclusive Flag requesting exclusive access to the queue
* @return the consumer tag. This is returned to the subscriber and used in subsequent unsubscribe requests
*/
private AMQShortString consumeFromSource(AMQShortString tag, Collection<MessageSource> sources, boolean acks, FieldTable arguments, boolean exclusive, boolean noLocal) throws MessageSource.ExistingConsumerPreventsExclusive, MessageSource.ExistingExclusiveConsumer, AMQInvalidArgumentException, MessageSource.ConsumerAccessRefused, ConsumerTagInUseException, MessageSource.QueueDeleted {
if (tag == null) {
tag = AMQShortString.createAMQShortString("sgen_" + getNextConsumerTag());
}
if (_tag2SubscriptionTargetMap.containsKey(tag)) {
throw new ConsumerTagInUseException("Consumer already exists with same tag: " + tag);
}
ConsumerTarget_0_8 target;
EnumSet<ConsumerOption> options = EnumSet.noneOf(ConsumerOption.class);
final boolean multiQueue = sources.size() > 1;
if (arguments != null && Boolean.TRUE.equals(arguments.get(AMQPFilterTypes.NO_CONSUME.getValue()))) {
target = ConsumerTarget_0_8.createBrowserTarget(this, tag, arguments, INFINITE_CREDIT_CREDIT_MANAGER, multiQueue);
} else if (acks) {
target = ConsumerTarget_0_8.createAckTarget(this, tag, arguments, _creditManager, multiQueue);
options.add(ConsumerOption.ACQUIRES);
options.add(ConsumerOption.SEES_REQUEUES);
} else {
target = ConsumerTarget_0_8.createNoAckTarget(this, tag, arguments, INFINITE_CREDIT_CREDIT_MANAGER, multiQueue);
options.add(ConsumerOption.ACQUIRES);
options.add(ConsumerOption.SEES_REQUEUES);
}
if (exclusive) {
options.add(ConsumerOption.EXCLUSIVE);
}
// So to keep things straight we put before the call and catch all exceptions from the register and tidy up.
// We add before we register as the Async Delivery process may AutoClose the subscriber
// so calling _cT2QM.remove before we have done put which was after the register succeeded.
// So to keep things straight we put before the call and catch all exceptions from the register and tidy up.
_tag2SubscriptionTargetMap.put(tag, target);
try {
FilterManager filterManager = FilterManagerFactory.createManager(FieldTable.convertToMap(arguments));
if (noLocal) {
if (filterManager == null) {
filterManager = new FilterManager();
}
MessageFilter filter = new NoLocalFilter();
filterManager.add(filter.getName(), filter);
}
if (arguments != null && arguments.containsKey(AMQPFilterTypes.REPLAY_PERIOD.toString())) {
Object value = arguments.get(AMQPFilterTypes.REPLAY_PERIOD.toString());
final long period;
if (value instanceof Number) {
period = ((Number) value).longValue();
} else if (value instanceof String) {
try {
period = Long.parseLong(value.toString());
} catch (NumberFormatException e) {
throw new AMQInvalidArgumentException("Cannot parse value " + value + " as a number for filter " + AMQPFilterTypes.REPLAY_PERIOD.toString());
}
} else {
throw new AMQInvalidArgumentException("Cannot parse value " + value + " as a number for filter " + AMQPFilterTypes.REPLAY_PERIOD.toString());
}
final long startingFrom = System.currentTimeMillis() - (1000l * period);
if (filterManager == null) {
filterManager = new FilterManager();
}
MessageFilter filter = new ArrivalTimeFilter(startingFrom, period == 0);
filterManager.add(filter.getName(), filter);
}
Integer priority = null;
if (arguments != null && arguments.containsKey("x-priority")) {
Object value = arguments.get("x-priority");
if (value instanceof Number) {
priority = ((Number) value).intValue();
} else if (value instanceof String || value instanceof AMQShortString) {
try {
priority = Integer.parseInt(value.toString());
} catch (NumberFormatException e) {
// use default vlaue
}
}
}
for (MessageSource source : sources) {
source.addConsumer(target, filterManager, AMQMessage.class, AMQShortString.toString(tag), options, priority);
}
target.updateNotifyWorkDesired();
} catch (AccessControlException | MessageSource.ExistingExclusiveConsumer | MessageSource.ExistingConsumerPreventsExclusive | MessageSource.QueueDeleted | AMQInvalidArgumentException | MessageSource.ConsumerAccessRefused e) {
_tag2SubscriptionTargetMap.remove(tag);
throw e;
}
return tag;
}
Aggregations