001/*
002 * Copyright 2002-2016 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.jms.support.destination;
018
019import javax.jms.Destination;
020import javax.jms.JMSException;
021import javax.jms.Message;
022import javax.jms.MessageConsumer;
023import javax.jms.Session;
024
025import org.springframework.jms.support.JmsAccessor;
026import org.springframework.lang.Nullable;
027import org.springframework.util.Assert;
028
029/**
030 * Base class for {@link org.springframework.jms.core.JmsTemplate} and other
031 * JMS-accessing gateway helpers, adding destination-related properties to
032 * {@link JmsAccessor JmsAccessor's} common properties.
033 *
034 * <p>Not intended to be used directly.
035 * See {@link org.springframework.jms.core.JmsTemplate}.
036 *
037 * @author Juergen Hoeller
038 * @since 1.2.5
039 * @see org.springframework.jms.support.JmsAccessor
040 * @see org.springframework.jms.core.JmsTemplate
041 */
042public abstract class JmsDestinationAccessor extends JmsAccessor {
043
044        /**
045         * Timeout value indicating that a receive operation should
046         * check if a message is immediately available without blocking.
047         * @since 4.3
048         */
049        public static final long RECEIVE_TIMEOUT_NO_WAIT = -1;
050
051        /**
052         * Timeout value indicating a blocking receive without timeout.
053         * @since 4.3
054         */
055        public static final long RECEIVE_TIMEOUT_INDEFINITE_WAIT = 0;
056
057
058        private DestinationResolver destinationResolver = new DynamicDestinationResolver();
059
060        private boolean pubSubDomain = false;
061
062
063        /**
064         * Set the {@link DestinationResolver} that is to be used to resolve
065         * {@link javax.jms.Destination} references for this accessor.
066         * <p>The default resolver is a DynamicDestinationResolver. Specify a
067         * JndiDestinationResolver for resolving destination names as JNDI locations.
068         * @see org.springframework.jms.support.destination.DynamicDestinationResolver
069         * @see org.springframework.jms.support.destination.JndiDestinationResolver
070         */
071        public void setDestinationResolver(DestinationResolver destinationResolver) {
072                Assert.notNull(destinationResolver, "'destinationResolver' must not be null");
073                this.destinationResolver = destinationResolver;
074        }
075
076        /**
077         * Return the DestinationResolver for this accessor (never {@code null}).
078         */
079        public DestinationResolver getDestinationResolver() {
080                return this.destinationResolver;
081        }
082
083        /**
084         * Configure the destination accessor with knowledge of the JMS domain used.
085         * Default is Point-to-Point (Queues).
086         * <p>This setting primarily indicates what type of destination to resolve
087         * if dynamic destinations are enabled.
088         * @param pubSubDomain "true" for the Publish/Subscribe domain ({@link javax.jms.Topic Topics}),
089         * "false" for the Point-to-Point domain ({@link javax.jms.Queue Queues})
090         * @see #setDestinationResolver
091         */
092        public void setPubSubDomain(boolean pubSubDomain) {
093                this.pubSubDomain = pubSubDomain;
094        }
095
096        /**
097         * Return whether the Publish/Subscribe domain ({@link javax.jms.Topic Topics}) is used.
098         * Otherwise, the Point-to-Point domain ({@link javax.jms.Queue Queues}) is used.
099         */
100        public boolean isPubSubDomain() {
101                return this.pubSubDomain;
102        }
103
104
105        /**
106         * Resolve the given destination name into a JMS {@link Destination},
107         * via this accessor's {@link DestinationResolver}.
108         * @param session the current JMS {@link Session}
109         * @param destinationName the name of the destination
110         * @return the located {@link Destination}
111         * @throws javax.jms.JMSException if resolution failed
112         * @see #setDestinationResolver
113         */
114        protected Destination resolveDestinationName(Session session, String destinationName) throws JMSException {
115                return getDestinationResolver().resolveDestinationName(session, destinationName, isPubSubDomain());
116        }
117
118        /**
119         * Actually receive a message from the given consumer.
120         * @param consumer the JMS MessageConsumer to receive with
121         * @param timeout the receive timeout (a negative value indicates
122         * a no-wait receive; 0 indicates an indefinite wait attempt)
123         * @return the JMS Message received, or {@code null} if none
124         * @throws JMSException if thrown by JMS API methods
125         * @since 4.3
126         * @see #RECEIVE_TIMEOUT_NO_WAIT
127         * @see #RECEIVE_TIMEOUT_INDEFINITE_WAIT
128         */
129        @Nullable
130        protected Message receiveFromConsumer(MessageConsumer consumer, long timeout) throws JMSException {
131                if (timeout > 0) {
132                        return consumer.receive(timeout);
133                }
134                else if (timeout < 0) {
135                        return consumer.receiveNoWait();
136                }
137                else {
138                        return consumer.receive();
139                }
140        }
141
142}