View Javadoc
1 /*** 2 * Redistribution and use of this software and associated documentation 3 * ("Software"), with or without modification, are permitted provided 4 * that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain copyright 7 * statements and notices. Redistributions must also contain a 8 * copy of this document. 9 * 10 * 2. Redistributions in binary form must reproduce the 11 * above copyright notice, this list of conditions and the 12 * following disclaimer in the documentation and/or other 13 * materials provided with the distribution. 14 * 15 * 3. The name "Exolab" must not be used to endorse or promote 16 * products derived from this Software without prior written 17 * permission of Exoffice Technologies. For written permission, 18 * please contact info@exolab.org. 19 * 20 * 4. Products derived from this Software may not be called "Exolab" 21 * nor may "Exolab" appear in their names without prior written 22 * permission of Exoffice Technologies. Exolab is a registered 23 * trademark of Exoffice Technologies. 24 * 25 * 5. Due credit should be given to the Exolab Project 26 * (http://www.exolab.org/). 27 * 28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 * OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Copyright 2001-2003 (C) Exoffice Technologies Inc. All Rights Reserved. 42 * 43 * $Id: QueueConsumerEndpoint.java,v 1.35 2003/08/17 01:32:24 tanderson Exp $ 44 * 45 * Date Author Changes 46 * 3/1/2001 jima Created 47 */ 48 package org.exolab.jms.messagemgr; 49 50 import java.sql.Connection; 51 52 import javax.jms.InvalidSelectorException; 53 import javax.jms.JMSException; 54 import javax.jms.Session; 55 import javax.transaction.TransactionManager; 56 57 import org.apache.commons.logging.Log; 58 import org.apache.commons.logging.LogFactory; 59 60 import org.exolab.jms.JMSErrorCodes; 61 import org.exolab.jms.client.JmsDestination; 62 import org.exolab.jms.client.JmsQueue; 63 import org.exolab.jms.message.MessageHandle; 64 import org.exolab.jms.message.MessageImpl; 65 import org.exolab.jms.persistence.PersistenceException; 66 import org.exolab.jms.scheduler.Scheduler; 67 import org.exolab.jms.server.ClientDisconnectionException; 68 import org.exolab.jms.server.JmsServerSession; 69 70 71 /*** 72 * A QueueConsumerEndpoint extends {@link ConsumerEndpoint}. This object 73 * shares access to a particular queue with other QueueConsumerEndpoint 74 * instances. 75 * 76 * @version $Revision: 1.35 $ $Date: 2003/08/17 01:32:24 $ 77 * @author <a href="mailto:jima@exoffice.com">Jim Alateras</a> 78 */ 79 public class QueueConsumerEndpoint 80 extends ConsumerEndpoint { 81 82 /*** 83 * The destination that this consumer subscribes too 84 */ 85 private QueueDestinationCache _cache = null; 86 87 /*** 88 * The queue that this endpoint is subscribed to 89 */ 90 private JmsQueue _queue = null; 91 92 /*** 93 * The maximum number of messages that a dispatch can deliver at any one 94 * time 95 */ 96 private final int MAX_MESSAGES = 200; 97 98 /*** 99 * The logger 100 */ 101 private static final Log _log = 102 LogFactory.getLog(QueueConsumerEndpoint.class); 103 104 105 /*** 106 * Construct a QueueConsumerEndpoint, that extends ConsumerEndpoint and 107 * is used to manage both synchronous and asynchronous message delivery 108 * for this consumer. 109 * 110 * @param session - the owning session 111 * @param clientId - uniquely identifies the remote client within session 112 * @param destination - destination that this object was created for 113 * @param selector - the selector attached to the consumer, if any. 114 * @param scheduler - used to schedule async message delivery. 115 * @exception InvalidSelectorException 116 */ 117 QueueConsumerEndpoint(JmsServerSession session, long clientId, 118 JmsQueue queue, String selector, Scheduler scheduler) 119 throws InvalidSelectorException { 120 super(session, clientId, selector, scheduler); 121 122 // now we should register the endpoint with the destination cache. If 123 // the destination cache does not exist then we should create it. 124 // All other methods in this class assume that a non-null cache 125 // exists. 126 if (queue != null) { 127 _queue = queue; 128 _cache = (QueueDestinationCache) 129 DestinationManager.instance().getDestinationCache(queue); 130 if (_cache == null) { 131 _cache = (QueueDestinationCache) 132 DestinationManager.instance().createDestinationCache(queue); 133 } 134 _cache.registerConsumer(this); 135 } 136 } 137 138 /*** 139 * Return the number of unsent messages 140 * 141 * @return the number of unsent messages 142 */ 143 public int getMessageCount() { 144 return _cache.getMessageCount(); 145 } 146 147 /*** 148 * Deliver messages in the cache to the consumer 149 * 150 * @return <code>true</code> if the endpoint should be rescheduled 151 */ 152 public boolean deliverMessages() { 153 boolean reschedule = true; 154 155 for (int index = 0; index < MAX_MESSAGES; index++) { 156 // check if we should exit the loop 157 if (stopDelivery()) { 158 reschedule = false; 159 break; 160 } 161 162 MessageHandle handle = null; 163 try { 164 handle = _cache.getMessage(this); 165 166 // if the handle is null then there are no more messages 167 // to remove so break 168 if (handle == null) { 169 reschedule = false; 170 break; 171 } 172 173 // set the delivered flag only when the message is 174 // processed in the session object. Send the message 175 // handle to the listener. 176 handle.setClientId(getClientId()); 177 _listener.onMessage(handle, true); 178 } catch (ClientDisconnectionException exception) { 179 if (handle != null) { 180 _cache.returnMessage(handle); 181 } 182 _listener = null; 183 _log.error(exception, exception); 184 } catch (JMSException exception) { 185 if (exception.getErrorCode().equals( 186 JMSErrorCodes.FailedToResolveHandle)) { 187 // do not return message back to the cache 188 _log.error("Dropping handle " + handle 189 + " since we cannot resolve it."); 190 } else { 191 _log.error(exception, exception); 192 if (handle != null) { 193 _cache.returnMessage(handle); 194 } 195 } 196 } catch (Exception exception) { 197 if (handle != null) { 198 _cache.returnMessage(handle); 199 } 200 _log.error(exception); 201 } 202 } 203 return reschedule; 204 } 205 206 // override ConsumerEndpoint.setMessageListener 207 public void setMessageListener(InternalMessageListener listener) { 208 // if the listener is null we unregister from the destination. If 209 // the listener is not null then we register with it. When we 210 // unregister we need to determine what happens to any messages 211 // in the sent and 212 if (listener == null) { 213 _cache.unregisterConsumer(this); 214 } else { 215 _cache.registerConsumer(this); 216 } 217 218 super.setMessageListener(listener); 219 } 220 221 // implementation of ConsumerEndpoint.receiveMessage 222 public MessageHandle receiveMessage(long wait) { 223 MessageHandle handle = getMessageFromCache(); 224 if ((handle == null) && 225 (wait >= 0)) { 226 227 // set a flag indicating that we are waiting 228 // for a message 229 setWaitingForMessage(); 230 231 // perform a double check and we receive a 232 // message then clear the previous set flag 233 handle = getMessageFromCache(); 234 if (handle != null) { 235 clearWaitingForMessage(); 236 } 237 } 238 239 return handle; 240 } 241 242 /*** 243 * Check whether a listener has been registered with this endpoint to 244 * support async message delivery 245 * 246 * @return boolean - true if it has 247 */ 248 public boolean hasMessageListener() { 249 return _listener != null; 250 } 251 252 // implementation of ConsumerEndpoint.unregister 253 public void unregister() { 254 _cache.unregisterConsumer(this); 255 } 256 257 // implementation of ConsumerEndpoint.getDestination 258 public JmsDestination getDestination() { 259 return _queue; 260 } 261 262 // override ConsumerEndpoint.messageAdded 263 public boolean messageAdded(MessageImpl message) { 264 if (_listener != null) { 265 schedule(); 266 } else { 267 // check to see whether the consumer is waiting to 268 // be notified 269 notifyMessageAvailable(); 270 } 271 272 return true; 273 } 274 275 // override ConsumerEndpoint.persistentMessageAdded 276 public boolean persistentMessageAdded(Connection connection, 277 MessageImpl message) 278 throws PersistenceException { 279 if (_listener != null) { 280 schedule(); 281 } else { 282 // check to see whether the consumer is waiting to 283 // be notified 284 notifyMessageAvailable(); 285 } 286 287 return true; 288 } 289 290 // override ConsumerEndpoint.messageRemoved 291 public synchronized boolean messageRemoved(MessageImpl message) { 292 return false; 293 } 294 295 /*** 296 * Closes this endpoint 297 */ 298 protected void doClose() { 299 // unregister from the DestinationCache 300 _cache.unregisterConsumer(this); 301 } 302 303 /*** 304 * Return a message from the corresponding cache for this consumer or 305 * null if one is not available 306 * 307 * @return MessageHandle - the handle or null 308 */ 309 private MessageHandle getMessageFromCache() { 310 MessageHandle handle = _cache.getMessage(this); 311 if (handle != null) { 312 handle.setClientId(getClientId()); 313 } 314 315 return handle; 316 } 317 318 } //-- QueueConsumerEndpoint 319

This page was automatically generated by Maven