Search in sources :

Example 1 with ActiveMQQueueExistsException

use of org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException in project activemq-artemis by apache.

the class OpenWireConnection method addDestination.

public void addDestination(DestinationInfo info) throws Exception {
    boolean created = false;
    ActiveMQDestination dest = info.getDestination();
    if (!protocolManager.isSupportAdvisory() && AdvisorySupport.isAdvisoryTopic(dest)) {
        return;
    }
    SimpleString qName = SimpleString.toSimpleString(dest.getPhysicalName());
    if (server.locateQueue(qName) == null) {
        AddressSettings addressSettings = server.getAddressSettingsRepository().getMatch(dest.getPhysicalName());
        AddressInfo addressInfo = new AddressInfo(qName, dest.isTopic() ? RoutingType.MULTICAST : RoutingType.ANYCAST);
        if (AdvisorySupport.isAdvisoryTopic(dest) && protocolManager.isSuppressInternalManagementObjects()) {
            addressInfo.setInternal(true);
        }
        if (dest.isQueue() && (addressSettings.isAutoCreateQueues() || dest.isTemporary())) {
            try {
                internalSession.createQueue(addressInfo, qName, null, dest.isTemporary(), !dest.isTemporary(), !dest.isTemporary());
                created = true;
            } catch (ActiveMQQueueExistsException exists) {
            // The queue may have been created by another thread in the mean time.  Catch and do nothing.
            }
        } else if (dest.isTopic() && (addressSettings.isAutoCreateAddresses() || dest.isTemporary())) {
            try {
                internalSession.createAddress(addressInfo, !dest.isTemporary());
                created = true;
            } catch (ActiveMQAddressExistsException exists) {
            // The address may have been created by another thread in the mean time.  Catch and do nothing.
            }
        }
    }
    if (dest.isTemporary()) {
        // Openwire needs to store the DestinationInfo in order to send
        // Advisory messages to clients
        this.state.addTempDestination(info);
    }
    if (created && !AdvisorySupport.isAdvisoryTopic(dest)) {
        AMQConnectionContext context = getContext();
        DestinationInfo advInfo = new DestinationInfo(context.getConnectionId(), DestinationInfo.ADD_OPERATION_TYPE, dest);
        ActiveMQTopic topic = AdvisorySupport.getDestinationAdvisoryTopic(dest);
        protocolManager.fireAdvisory(context, topic, advInfo);
    }
}
Also used : AddressSettings(org.apache.activemq.artemis.core.settings.impl.AddressSettings) DestinationInfo(org.apache.activemq.command.DestinationInfo) ActiveMQTopic(org.apache.activemq.command.ActiveMQTopic) ActiveMQAddressExistsException(org.apache.activemq.artemis.api.core.ActiveMQAddressExistsException) AMQConnectionContext(org.apache.activemq.artemis.core.protocol.openwire.amq.AMQConnectionContext) ActiveMQQueueExistsException(org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ActiveMQDestination(org.apache.activemq.command.ActiveMQDestination) AddressInfo(org.apache.activemq.artemis.core.server.impl.AddressInfo)

Example 2 with ActiveMQQueueExistsException

use of org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException in project activemq-artemis by apache.

the class AMQPSessionCallback method addressQuery.

public AddressQueryResult addressQuery(SimpleString addressName, RoutingType routingType, boolean autoCreate) throws Exception {
    AddressQueryResult addressQueryResult = addressQueryCache.getResult(addressName);
    if (addressQueryResult != null) {
        return addressQueryResult;
    }
    addressQueryResult = serverSession.executeAddressQuery(addressName);
    if (!addressQueryResult.isExists() && addressQueryResult.isAutoCreateAddresses() && autoCreate) {
        try {
            serverSession.createAddress(addressName, routingType, true);
        } catch (ActiveMQQueueExistsException e) {
        // The queue may have been created by another thread in the mean time.  Catch and do nothing.
        }
        addressQueryResult = serverSession.executeAddressQuery(addressName);
    }
    addressQueryCache.setResult(addressName, addressQueryResult);
    return addressQueryResult;
}
Also used : AddressQueryResult(org.apache.activemq.artemis.core.server.AddressQueryResult) ActiveMQQueueExistsException(org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException)

Example 3 with ActiveMQQueueExistsException

use of org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException in project activemq-artemis by apache.

the class ProtonServerSenderContext method initialise.

/**
 * create the actual underlying ActiveMQ Artemis Server Consumer
 */
@SuppressWarnings("unchecked")
@Override
public void initialise() throws Exception {
    super.initialise();
    Source source = (Source) sender.getRemoteSource();
    SimpleString queue = null;
    String selector = null;
    final Map<Symbol, Object> supportedFilters = new HashMap<>();
    // Match the settlement mode of the remote instead of relying on the default of MIXED.
    sender.setSenderSettleMode(sender.getRemoteSenderSettleMode());
    // We don't currently support SECOND so enforce that the answer is anlways FIRST
    sender.setReceiverSettleMode(ReceiverSettleMode.FIRST);
    if (source != null) {
        // We look for message selectors on every receiver, while in other cases we might only
        // consume the filter depending on the subscription type.
        Map.Entry<Symbol, DescribedType> filter = AmqpSupport.findFilter(source.getFilter(), AmqpSupport.JMS_SELECTOR_FILTER_IDS);
        if (filter != null) {
            selector = filter.getValue().getDescribed().toString();
            // Validate the Selector.
            try {
                SelectorParser.parse(selector);
            } catch (FilterException e) {
                throw new ActiveMQAMQPException(AmqpError.INVALID_FIELD, "Invalid filter", ActiveMQExceptionType.INVALID_FILTER_EXPRESSION);
            }
            supportedFilters.put(filter.getKey(), filter.getValue());
        }
    }
    if (source == null) {
        // Attempt to recover a previous subscription happens when a link reattach happens on a
        // subscription queue
        String clientId = getClientId();
        String pubId = sender.getName();
        global = hasRemoteDesiredCapability(sender, GLOBAL);
        queue = createQueueName(connection.isUseCoreSubscriptionNaming(), clientId, pubId, true, global, false);
        QueueQueryResult result = sessionSPI.queueQuery(queue, RoutingType.MULTICAST, false);
        multicast = true;
        routingTypeToUse = RoutingType.MULTICAST;
        // the lifetime policy and capabilities of the new subscription.
        if (result.isExists()) {
            source = new org.apache.qpid.proton.amqp.messaging.Source();
            source.setAddress(queue.toString());
            source.setDurable(TerminusDurability.UNSETTLED_STATE);
            source.setExpiryPolicy(TerminusExpiryPolicy.NEVER);
            source.setDistributionMode(COPY);
            source.setCapabilities(TOPIC);
            SimpleString filterString = result.getFilterString();
            if (filterString != null) {
                selector = filterString.toString();
                boolean noLocal = false;
                String remoteContainerId = sender.getSession().getConnection().getRemoteContainer();
                String noLocalFilter = MessageUtil.CONNECTION_ID_PROPERTY_NAME.toString() + "<>'" + remoteContainerId + "'";
                if (selector.endsWith(noLocalFilter)) {
                    if (selector.length() > noLocalFilter.length()) {
                        noLocalFilter = " AND " + noLocalFilter;
                        selector = selector.substring(0, selector.length() - noLocalFilter.length());
                    } else {
                        selector = null;
                    }
                    noLocal = true;
                }
                if (noLocal) {
                    supportedFilters.put(AmqpSupport.NO_LOCAL_NAME, AmqpNoLocalFilter.NO_LOCAL);
                }
                if (selector != null && !selector.trim().isEmpty()) {
                    supportedFilters.put(AmqpSupport.JMS_SELECTOR_NAME, new AmqpJmsSelectorFilter(selector));
                }
            }
            sender.setSource(source);
        } else {
            throw new ActiveMQAMQPNotFoundException("Unknown subscription link: " + sender.getName());
        }
    } else if (source.getDynamic()) {
        // if dynamic we have to create the node (queue) and set the address on the target, the
        // node is temporary and  will be deleted on closing of the session
        queue = SimpleString.toSimpleString(java.util.UUID.randomUUID().toString());
        tempQueueName = queue;
        try {
            sessionSPI.createTemporaryQueue(queue, RoutingType.ANYCAST);
        // protonSession.getServerSession().createQueue(queue, queue, null, true, false);
        } catch (Exception e) {
            throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.errorCreatingTemporaryQueue(e.getMessage());
        }
        source.setAddress(queue.toString());
    } else {
        SimpleString addressToUse;
        SimpleString queueNameToUse = null;
        shared = hasCapabilities(SHARED, source);
        global = hasCapabilities(GLOBAL, source);
        // find out if we have an address made up of the address and queue name, if yes then set queue name
        if (CompositeAddress.isFullyQualified(source.getAddress())) {
            CompositeAddress compositeAddress = CompositeAddress.getQueueName(source.getAddress());
            addressToUse = new SimpleString(compositeAddress.getAddress());
            queueNameToUse = new SimpleString(compositeAddress.getQueueName());
        } else {
            addressToUse = new SimpleString(source.getAddress());
        }
        // check to see if the client has defined how we act
        boolean clientDefined = hasCapabilities(TOPIC, source) || hasCapabilities(QUEUE, source);
        if (clientDefined) {
            multicast = hasCapabilities(TOPIC, source);
            AddressQueryResult addressQueryResult = null;
            try {
                addressQueryResult = sessionSPI.addressQuery(addressToUse, multicast ? RoutingType.MULTICAST : RoutingType.ANYCAST, true);
            } catch (ActiveMQSecurityException e) {
                throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.securityErrorCreatingConsumer(e.getMessage());
            } catch (ActiveMQAMQPException e) {
                throw e;
            } catch (Exception e) {
                throw new ActiveMQAMQPInternalErrorException(e.getMessage(), e);
            }
            if (!addressQueryResult.isExists()) {
                throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.sourceAddressDoesntExist();
            }
            Set<RoutingType> routingTypes = addressQueryResult.getRoutingTypes();
            // if the client defines 1 routing type and the broker another then throw an exception
            if (multicast && !routingTypes.contains(RoutingType.MULTICAST)) {
                throw new ActiveMQAMQPIllegalStateException("Address " + addressToUse + " is not configured for topic support");
            } else if (!multicast && !routingTypes.contains(RoutingType.ANYCAST)) {
                throw new ActiveMQAMQPIllegalStateException("Address " + addressToUse + " is not configured for queue support");
            }
        } else {
            // if not we look up the address
            AddressQueryResult addressQueryResult = null;
            try {
                addressQueryResult = sessionSPI.addressQuery(addressToUse, defaultRoutingType, true);
            } catch (ActiveMQSecurityException e) {
                throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.securityErrorCreatingConsumer(e.getMessage());
            } catch (ActiveMQAMQPException e) {
                throw e;
            } catch (Exception e) {
                throw new ActiveMQAMQPInternalErrorException(e.getMessage(), e);
            }
            if (!addressQueryResult.isExists()) {
                throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.sourceAddressDoesntExist();
            }
            Set<RoutingType> routingTypes = addressQueryResult.getRoutingTypes();
            if (routingTypes.contains(RoutingType.MULTICAST) && routingTypes.size() == 1) {
                multicast = true;
            } else {
                // todo add some checks if both routing types are supported
                multicast = false;
            }
        }
        routingTypeToUse = multicast ? RoutingType.MULTICAST : RoutingType.ANYCAST;
        // messages to, however there has to be a queue bound to it so we need to check this.
        if (multicast) {
            Map.Entry<Symbol, DescribedType> filter = AmqpSupport.findFilter(source.getFilter(), AmqpSupport.NO_LOCAL_FILTER_IDS);
            if (filter != null) {
                String remoteContainerId = sender.getSession().getConnection().getRemoteContainer();
                String noLocalFilter = MessageUtil.CONNECTION_ID_PROPERTY_NAME.toString() + "<>'" + remoteContainerId + "'";
                if (selector != null) {
                    selector += " AND " + noLocalFilter;
                } else {
                    selector = noLocalFilter;
                }
                supportedFilters.put(filter.getKey(), filter.getValue());
            }
            queue = getMatchingQueue(queueNameToUse, addressToUse, RoutingType.MULTICAST);
            SimpleString simpleStringSelector = SimpleString.toSimpleString(selector);
            // if the address specifies a broker configured queue then we always use this, treat it as a queue
            if (queue != null) {
                multicast = false;
            } else if (TerminusDurability.UNSETTLED_STATE.equals(source.getDurable()) || TerminusDurability.CONFIGURATION.equals(source.getDurable())) {
                // if we are a subscription and durable create a durable queue using the container
                // id and link name
                String clientId = getClientId();
                String pubId = sender.getName();
                queue = createQueueName(connection.isUseCoreSubscriptionNaming(), clientId, pubId, shared, global, false);
                QueueQueryResult result = sessionSPI.queueQuery(queue, routingTypeToUse, false);
                if (result.isExists()) {
                    // filter value, selector or address then we must recreate the queue (JMS semantics).
                    if (!Objects.equals(result.getFilterString(), simpleStringSelector) || (sender.getSource() != null && !sender.getSource().getAddress().equals(result.getAddress().toString()))) {
                        if (result.getConsumerCount() == 0) {
                            sessionSPI.deleteQueue(queue);
                            sessionSPI.createUnsharedDurableQueue(addressToUse, RoutingType.MULTICAST, queue, simpleStringSelector);
                        } else {
                            throw new ActiveMQAMQPIllegalStateException("Unable to recreate subscription, consumers already exist");
                        }
                    }
                } else {
                    if (shared) {
                        sessionSPI.createSharedDurableQueue(addressToUse, RoutingType.MULTICAST, queue, simpleStringSelector);
                    } else {
                        sessionSPI.createUnsharedDurableQueue(addressToUse, RoutingType.MULTICAST, queue, simpleStringSelector);
                    }
                }
            } else {
                // otherwise we are a volatile subscription
                isVolatile = true;
                if (shared && sender.getName() != null) {
                    queue = createQueueName(connection.isUseCoreSubscriptionNaming(), getClientId(), sender.getName(), shared, global, isVolatile);
                    try {
                        sessionSPI.createSharedVolatileQueue(addressToUse, RoutingType.MULTICAST, queue, simpleStringSelector);
                    } catch (ActiveMQQueueExistsException e) {
                    // this is ok, just means its shared
                    }
                } else {
                    queue = SimpleString.toSimpleString(java.util.UUID.randomUUID().toString());
                    tempQueueName = queue;
                    try {
                        sessionSPI.createTemporaryQueue(addressToUse, queue, RoutingType.MULTICAST, simpleStringSelector);
                    } catch (Exception e) {
                        throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.errorCreatingTemporaryQueue(e.getMessage());
                    }
                }
            }
        } else {
            if (queueNameToUse != null) {
                SimpleString matchingAnycastQueue = getMatchingQueue(queueNameToUse, addressToUse, RoutingType.ANYCAST);
                if (matchingAnycastQueue != null) {
                    queue = matchingAnycastQueue;
                } else {
                    throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.sourceAddressDoesntExist();
                }
            } else {
                SimpleString matchingAnycastQueue = sessionSPI.getMatchingQueue(addressToUse, RoutingType.ANYCAST);
                if (matchingAnycastQueue != null) {
                    queue = matchingAnycastQueue;
                } else {
                    queue = addressToUse;
                }
            }
        }
        if (queue == null) {
            throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.sourceAddressNotSet();
        }
        try {
            if (!sessionSPI.queueQuery(queue, routingTypeToUse, !multicast).isExists()) {
                throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.sourceAddressDoesntExist();
            }
        } catch (ActiveMQAMQPNotFoundException e) {
            throw e;
        } catch (Exception e) {
            throw new ActiveMQAMQPInternalErrorException(e.getMessage(), e);
        }
    }
    // We need to update the source with any filters we support otherwise the client
    // is free to consider the attach as having failed if we don't send back what we
    // do support or if we send something we don't support the client won't know we
    // have not honored what it asked for.
    source.setFilter(supportedFilters.isEmpty() ? null : supportedFilters);
    boolean browseOnly = !multicast && source.getDistributionMode() != null && source.getDistributionMode().equals(COPY);
    try {
        brokerConsumer = (Consumer) sessionSPI.createSender(this, queue, multicast ? null : selector, browseOnly);
    } catch (ActiveMQAMQPResourceLimitExceededException e1) {
        throw new ActiveMQAMQPResourceLimitExceededException(e1.getMessage());
    } catch (ActiveMQSecurityException e) {
        throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.securityErrorCreatingConsumer(e.getMessage());
    } catch (Exception e) {
        throw ActiveMQAMQPProtocolMessageBundle.BUNDLE.errorCreatingConsumer(e.getMessage());
    }
}
Also used : ActiveMQAMQPInternalErrorException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInternalErrorException) Set(java.util.Set) HashMap(java.util.HashMap) Symbol(org.apache.qpid.proton.amqp.Symbol) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) QueueQueryResult(org.apache.activemq.artemis.core.server.QueueQueryResult) Source(org.apache.qpid.proton.amqp.messaging.Source) CompositeAddress(org.apache.activemq.artemis.utils.CompositeAddress) ActiveMQAMQPResourceLimitExceededException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPResourceLimitExceededException) ActiveMQQueueExistsException(org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException) ActiveMQSecurityException(org.apache.activemq.artemis.api.core.ActiveMQSecurityException) ActiveMQAMQPIllegalStateException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPIllegalStateException) AddressQueryResult(org.apache.activemq.artemis.core.server.AddressQueryResult) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ActiveMQAMQPNotFoundException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPNotFoundException) ActiveMQAMQPNotFoundException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPNotFoundException) ActiveMQAMQPException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException) FilterException(org.apache.activemq.artemis.selector.filter.FilterException) ActiveMQAMQPInternalErrorException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInternalErrorException) ActiveMQQueueExistsException(org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException) ActiveMQAMQPResourceLimitExceededException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPResourceLimitExceededException) ActiveMQAMQPIllegalStateException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPIllegalStateException) ActiveMQSecurityException(org.apache.activemq.artemis.api.core.ActiveMQSecurityException) Source(org.apache.qpid.proton.amqp.messaging.Source) DescribedType(org.apache.qpid.proton.amqp.DescribedType) FilterException(org.apache.activemq.artemis.selector.filter.FilterException) ActiveMQAMQPException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException) Map(java.util.Map) HashMap(java.util.HashMap)

Example 4 with ActiveMQQueueExistsException

use of org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException in project activemq-artemis by apache.

the class ActiveMQSession method internalCreateSharedConsumer.

/**
 * This is an internal method for shared consumers
 */
private ActiveMQMessageConsumer internalCreateSharedConsumer(final ActiveMQDestination dest, final String subscriptionName, String selectorString, ConsumerDurability durability) throws JMSException {
    try {
        if (dest.isQueue()) {
            // createSharedConsumer only accepts Topics by declaration
            throw new RuntimeException("Internal error: createSharedConsumer is only meant for Topics");
        }
        if (subscriptionName == null) {
            throw ActiveMQJMSClientBundle.BUNDLE.invalidSubscriptionName();
        }
        selectorString = "".equals(selectorString) ? null : selectorString;
        SimpleString coreFilterString = null;
        if (selectorString != null) {
            coreFilterString = new SimpleString(SelectorTranslator.convertToActiveMQFilterString(selectorString));
        }
        ClientConsumer consumer;
        SimpleString autoDeleteQueueName = null;
        AddressQuery response = session.addressQuery(dest.getSimpleAddress());
        if (!response.isExists() && !response.isAutoCreateAddresses()) {
            throw ActiveMQJMSClientBundle.BUNDLE.destinationDoesNotExist(dest.getSimpleAddress());
        }
        SimpleString queueName;
        if (dest.isTemporary() && durability == ConsumerDurability.DURABLE) {
            throw new InvalidDestinationException("Cannot create a durable subscription on a temporary topic");
        }
        queueName = ActiveMQDestination.createQueueNameForSubscription(durability == ConsumerDurability.DURABLE, connection.getClientID(), subscriptionName);
        try {
            if (durability == ConsumerDurability.DURABLE) {
                createSharedQueue(dest, RoutingType.MULTICAST, queueName, coreFilterString, true, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
            } else {
                createSharedQueue(dest, RoutingType.MULTICAST, queueName, coreFilterString, false, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
            }
        } catch (ActiveMQQueueExistsException ignored) {
        // We ignore this because querying and then creating the queue wouldn't be idempotent
        // we could also add a parameter to ignore existence what would require a bigger work around to avoid
        // compatibility.
        }
        consumer = session.createConsumer(queueName, null, false);
        ActiveMQMessageConsumer jbc = new ActiveMQMessageConsumer(options, connection, this, consumer, false, dest, selectorString, autoDeleteQueueName);
        consumers.add(jbc);
        return jbc;
    } catch (ActiveMQException e) {
        throw JMSExceptionHelper.convertFromActiveMQException(e);
    }
}
Also used : AddressQuery(org.apache.activemq.artemis.api.core.client.ClientSession.AddressQuery) ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) ActiveMQQueueExistsException(org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) InvalidDestinationException(javax.jms.InvalidDestinationException) ClientConsumer(org.apache.activemq.artemis.api.core.client.ClientConsumer)

Example 5 with ActiveMQQueueExistsException

use of org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException in project activemq-artemis by apache.

the class ActiveMQSession method createConsumer.

private ActiveMQMessageConsumer createConsumer(final ActiveMQDestination dest, final String subscriptionName, String selectorString, final boolean noLocal, ConsumerDurability durability) throws JMSException {
    try {
        selectorString = "".equals(selectorString) ? null : selectorString;
        if (noLocal) {
            connection.setHasNoLocal();
            String filter;
            if (connection.getClientID() != null) {
                filter = ActiveMQConnection.CONNECTION_ID_PROPERTY_NAME.toString() + "<>'" + connection.getClientID() + "'";
            } else {
                filter = ActiveMQConnection.CONNECTION_ID_PROPERTY_NAME.toString() + "<>'" + connection.getUID() + "'";
            }
            if (selectorString != null) {
                selectorString += " AND " + filter;
            } else {
                selectorString = filter;
            }
        }
        SimpleString coreFilterString = null;
        if (selectorString != null) {
            coreFilterString = new SimpleString(SelectorTranslator.convertToActiveMQFilterString(selectorString));
        }
        ClientConsumer consumer;
        SimpleString autoDeleteQueueName = null;
        if (dest.isQueue()) {
            AddressQuery response = session.addressQuery(dest.getSimpleAddress());
            /* The address query will send back exists=true even if the node only has a REMOTE binding for the destination.
             * Therefore, we must check if the queue names list contains the exact name of the address to know whether or
             * not a LOCAL binding for the address exists. If no LOCAL binding exists then it should be created here.
             */
            if (!response.isExists() || !response.getQueueNames().contains(dest.getSimpleAddress())) {
                if (response.isAutoCreateQueues()) {
                    try {
                        createQueue(dest, RoutingType.ANYCAST, dest.getSimpleAddress(), null, true, true, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
                    } catch (ActiveMQQueueExistsException e) {
                    // The queue was created by another client/admin between the query check and send create queue packet
                    }
                } else {
                    throw new InvalidDestinationException("Destination " + dest.getName() + " does not exist");
                }
            }
            connection.addKnownDestination(dest.getSimpleAddress());
            consumer = session.createConsumer(dest.getSimpleAddress(), coreFilterString, false);
        } else {
            AddressQuery response = session.addressQuery(dest.getSimpleAddress());
            if (!response.isExists()) {
                if (response.isAutoCreateAddresses()) {
                    session.createAddress(dest.getSimpleAddress(), RoutingType.MULTICAST, true);
                } else {
                    throw new InvalidDestinationException("Topic " + dest.getName() + " does not exist");
                }
            }
            connection.addKnownDestination(dest.getSimpleAddress());
            SimpleString queueName;
            if (subscriptionName == null) {
                if (durability != ConsumerDurability.NON_DURABLE)
                    throw new RuntimeException("Subscription name cannot be null for durable topic consumer");
                // Non durable sub
                queueName = new SimpleString(UUID.randomUUID().toString());
                createTemporaryQueue(dest, RoutingType.MULTICAST, queueName, coreFilterString, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
                consumer = session.createConsumer(queueName, null, false);
                autoDeleteQueueName = queueName;
            } else {
                // Durable sub
                if (durability != ConsumerDurability.DURABLE)
                    throw new RuntimeException("Subscription name must be null for non-durable topic consumer");
                if (connection.getClientID() == null) {
                    throw new IllegalStateException("Cannot create durable subscription - client ID has not been set");
                }
                if (dest.isTemporary()) {
                    throw new InvalidDestinationException("Cannot create a durable subscription on a temporary topic");
                }
                queueName = ActiveMQDestination.createQueueNameForSubscription(true, connection.getClientID(), subscriptionName);
                QueueQuery subResponse = session.queueQuery(queueName);
                if (!subResponse.isExists()) {
                    // durable subscription queues are not technically considered to be auto-created
                    createQueue(dest, RoutingType.MULTICAST, queueName, coreFilterString, true, false, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
                } else {
                    // Already exists
                    if (subResponse.getConsumerCount() > 0) {
                        throw new IllegalStateException("Cannot create a subscriber on the durable subscription since it already has subscriber(s)");
                    }
                    // From javax.jms.Session Javadoc (and also JMS 1.1 6.11.1):
                    // A client can change an existing durable subscription by
                    // creating a durable TopicSubscriber with the same name and
                    // a new topic and/or message selector.
                    // Changing a durable subscriber is equivalent to unsubscribing
                    // (deleting) the old one and creating a new one.
                    SimpleString oldFilterString = subResponse.getFilterString();
                    boolean selectorChanged = coreFilterString == null && oldFilterString != null || oldFilterString == null && coreFilterString != null || oldFilterString != null && coreFilterString != null && !oldFilterString.equals(coreFilterString);
                    SimpleString oldTopicName = subResponse.getAddress();
                    boolean topicChanged = !oldTopicName.equals(dest.getSimpleAddress());
                    if (selectorChanged || topicChanged) {
                        // Delete the old durable sub
                        session.deleteQueue(queueName);
                        // Create the new one
                        createQueue(dest, RoutingType.MULTICAST, queueName, coreFilterString, true, false, response.getDefaultMaxConsumers(), response.isDefaultPurgeOnNoConsumers(), response.isDefaultExclusive(), response.isDefaultLastValueQueue());
                    }
                }
                consumer = session.createConsumer(queueName, null, false);
            }
        }
        ActiveMQMessageConsumer jbc = new ActiveMQMessageConsumer(options, connection, this, consumer, noLocal, dest, selectorString, autoDeleteQueueName);
        consumers.add(jbc);
        return jbc;
    } catch (ActiveMQException e) {
        throw JMSExceptionHelper.convertFromActiveMQException(e);
    }
}
Also used : IllegalStateException(javax.jms.IllegalStateException) AddressQuery(org.apache.activemq.artemis.api.core.client.ClientSession.AddressQuery) ActiveMQException(org.apache.activemq.artemis.api.core.ActiveMQException) ActiveMQQueueExistsException(org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) InvalidDestinationException(javax.jms.InvalidDestinationException) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) ClientConsumer(org.apache.activemq.artemis.api.core.client.ClientConsumer) QueueQuery(org.apache.activemq.artemis.api.core.client.ClientSession.QueueQuery)

Aggregations

ActiveMQQueueExistsException (org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException)16 SimpleString (org.apache.activemq.artemis.api.core.SimpleString)13 ActiveMQException (org.apache.activemq.artemis.api.core.ActiveMQException)7 AddressSettings (org.apache.activemq.artemis.core.settings.impl.AddressSettings)5 InvalidDestinationException (javax.jms.InvalidDestinationException)4 ClientSession (org.apache.activemq.artemis.api.core.client.ClientSession)4 RoutingType (org.apache.activemq.artemis.api.core.RoutingType)3 AddressQuery (org.apache.activemq.artemis.api.core.client.ClientSession.AddressQuery)3 QueueQueryResult (org.apache.activemq.artemis.core.server.QueueQueryResult)3 IllegalStateException (javax.jms.IllegalStateException)2 ActiveMQAddressExistsException (org.apache.activemq.artemis.api.core.ActiveMQAddressExistsException)2 ClientConsumer (org.apache.activemq.artemis.api.core.client.ClientConsumer)2 ClientSessionFactory (org.apache.activemq.artemis.api.core.client.ClientSessionFactory)2 ServerLocator (org.apache.activemq.artemis.api.core.client.ServerLocator)2 CoreQueueConfiguration (org.apache.activemq.artemis.core.config.CoreQueueConfiguration)2 AddressQueryResult (org.apache.activemq.artemis.core.server.AddressQueryResult)2 BindingQueryResult (org.apache.activemq.artemis.core.server.BindingQueryResult)2 CompositeAddress (org.apache.activemq.artemis.utils.CompositeAddress)2 Test (org.junit.Test)2 ArrayList (java.util.ArrayList)1