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 2005 (C) Exoffice Technologies Inc. All Rights Reserved. 42 * 43 * $Id: AbstractMessageHandle.java,v 1.2 2005/08/30 07:26:49 tanderson Exp $ 44 */ 45 package org.exolab.jms.messagemgr; 46 47 import javax.jms.IllegalStateException; 48 import javax.jms.JMSException; 49 import javax.jms.MessageConsumer; 50 51 import org.exolab.jms.client.JmsDestination; 52 import org.exolab.jms.message.MessageImpl; 53 import org.exolab.jms.server.ServerConnection; 54 55 56 /*** 57 * Abstract implementation of the {@link MessageHandle} interface. 58 * 59 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a> 60 * @version $Revision: 1.2 $ $Date: 2005/08/30 07:26:49 $ 61 */ 62 public abstract class AbstractMessageHandle implements MessageHandle { 63 64 /*** 65 * The cache that manages this handle. 66 */ 67 private DestinationCache _cache; 68 69 /*** 70 * The message reference. 71 */ 72 private MessageRef _reference; 73 74 /*** 75 * The message identifier. 76 */ 77 private final String _messageId; 78 79 /*** 80 * If <code>true</code>, indicates that the message associated with the 81 * handle has been delivered, but not acknowledged. 82 */ 83 private boolean _delivered = false; 84 85 /*** 86 * The message priority. 87 */ 88 private final int _priority; 89 90 /*** 91 * The time that the message was accepted by the server, in milliseconds. 92 */ 93 private long _acceptedTime; 94 95 /*** 96 * The message sequence number, assigned by the {@link MessageMgr}, used to 97 * help order the message. It also allows us to overcome the millisecond 98 * resolution problem of _acceptedTime, when ordering messages 99 */ 100 private final long _sequenceNumber; 101 102 /*** 103 * The time that the message expires, in milliseconds. 104 */ 105 private long _expiryTime; 106 107 /*** 108 * The destination that this handle belongs to. 109 */ 110 private final JmsDestination _destination; 111 112 /*** 113 * The identity of the {@link ConsumerEndpoint} associated with the message, 114 * or <code>-1</code> if it isn't associated with any consumer. 115 */ 116 private final long _consumerId; 117 118 /*** 119 * The identity of the {@link ServerConnection} associated with the message, 120 * or <code>-1</code> if it isn't associated with any connection. 121 */ 122 private final long _connectionId; 123 124 125 /*** 126 * Construct a new <code>AbstractMessageHandle</code>. 127 * 128 * @param cache the destination cache that owns this 129 * @param reference the reference to the message 130 * @param message the message for which the handle is created 131 * @throws JMSException if the handle cannot be constructed 132 */ 133 public AbstractMessageHandle(DestinationCache cache, MessageRef reference, 134 MessageImpl message) 135 throws JMSException { 136 if (cache == null) { 137 throw new IllegalArgumentException("Argument 'cache' is null"); 138 } 139 if (reference == null) { 140 throw new IllegalArgumentException("Argument 'reference' is null"); 141 } 142 if (message == null) { 143 throw new IllegalArgumentException("Argument 'message' is null"); 144 } 145 _cache = cache; 146 _messageId = message.getMessageId().getId(); 147 _delivered = message.getJMSRedelivered(); 148 _priority = message.getJMSPriority(); 149 _acceptedTime = message.getAcceptedTime(); 150 _sequenceNumber = message.getSequenceNumber(); 151 _expiryTime = message.getJMSExpiration(); 152 _destination = (JmsDestination) message.getJMSDestination(); 153 _consumerId = message.getConsumerId(); 154 _connectionId = message.getConnectionId(); 155 _reference = reference; 156 } 157 158 /*** 159 * Construct a new <code>AbstractMessageHandle</code>. 160 * 161 * @param messageId the message identifier 162 * @param priority the message priority 163 * @param acceptedTime the time the message was accepted by the server 164 * @param sequenceNumber the message sequence number 165 * @param expiryTime the time that the message will expire 166 */ 167 public AbstractMessageHandle(String messageId, int priority, 168 long acceptedTime, long sequenceNumber, 169 long expiryTime, JmsDestination destination) { 170 if (messageId == null) { 171 throw new IllegalArgumentException("Argument 'messageId' is null"); 172 } 173 if (destination == null) { 174 throw new IllegalArgumentException( 175 "Argument 'destination' is null"); 176 } 177 _messageId = messageId; 178 _priority = priority; 179 _acceptedTime = acceptedTime; 180 _sequenceNumber = sequenceNumber; 181 _expiryTime = expiryTime; 182 _destination = destination; 183 _consumerId = -1; 184 _connectionId = -1; 185 } 186 187 /*** 188 * Returns the message identifier. 189 * 190 * @return the message identifier 191 */ 192 public String getMessageId() { 193 return _messageId; 194 } 195 196 /*** 197 * Returns the message associated with this handle. 198 * 199 * @return the associated message, or <code>null</code> if the handle is no 200 * longer valid 201 * @throws JMSException for any error 202 */ 203 public MessageImpl getMessage() throws JMSException { 204 if (_reference == null) { 205 throw new JMSException("Cannot get message with identifier=" 206 + _messageId + ": MessageRef null"); 207 } 208 return _reference.getMessage(); 209 } 210 211 212 /*** 213 * Indicates if a message has been delivered to a {@link MessageConsumer}, 214 * but not acknowledged. 215 * 216 * @param delivered if <code>true</code> indicates that an attempt has been 217 * made to deliver the message 218 */ 219 public void setDelivered(boolean delivered) { 220 _delivered = delivered; 221 } 222 223 /*** 224 * Returns if an attempt has already been made to deliver the message. 225 * 226 * @return <code>true</code> if delivery has been attempted 227 */ 228 public boolean getDelivered() { 229 return _delivered; 230 } 231 232 /*** 233 * Returns the priority of the message. 234 * 235 * @return the message priority 236 */ 237 public int getPriority() { 238 return _priority; 239 } 240 241 /*** 242 * Returns the time that the corresponding message was accepted, in 243 * milliseconds. 244 * 245 * @return the time that the corresponding message was accepted 246 */ 247 public long getAcceptedTime() { 248 return _acceptedTime; 249 } 250 251 /*** 252 * Returns the time that the message expires. 253 * 254 * @return the expiry time 255 */ 256 public long getExpiryTime() { 257 return _expiryTime; 258 } 259 260 /*** 261 * Determines if the message has expired. 262 * 263 * @return <code>true</code> if the message has expired, otherwise 264 * <code>false</code> 265 */ 266 public boolean hasExpired() { 267 return (_expiryTime != 0 && _expiryTime <= System.currentTimeMillis()); 268 } 269 270 /*** 271 * Returns the handle's sequence number. 272 * 273 * @return the sequence number 274 */ 275 public long getSequenceNumber() { 276 return _sequenceNumber; 277 } 278 279 /*** 280 * Returns the message destination. 281 * 282 * @return the message destination 283 */ 284 public JmsDestination getDestination() { 285 return _destination; 286 } 287 288 /*** 289 * Returns the consumer identity associated with the message. 290 * 291 * @return the consumer identity associated with the message, or * 292 * <code>-1</code> if the message isn't associated with a consumer 293 */ 294 public long getConsumerId() { 295 return _consumerId; 296 } 297 298 /*** 299 * Returns the persistent identity of the the consumer endpoint that owns 300 * this handle. If it is set, then a consumer owns it exclusively, otherwise 301 * the handle may be shared across a number of consumers. 302 * 303 * @return <code>null</code> 304 */ 305 public String getConsumerPersistentId() { 306 return null; 307 } 308 309 /*** 310 * Returns the connection identity associated with this handle. 311 * 312 * @return the connection identity associated with this handle, or 313 * <code>-1</code> if this isn't associated with a connection 314 */ 315 public long getConnectionId() { 316 return _connectionId; 317 } 318 319 /*** 320 * Determines if the handle is persistent. 321 * 322 * @return <code>false</code> 323 */ 324 public boolean isPersistent() { 325 return false; 326 } 327 328 /*** 329 * Indicates whether some other object is "equal to" this one. 330 * 331 * @param object the reference object with which to compare. 332 * @return <code>true</code> if <code>object</code> is a MessageHandle, and 333 * has the same {@link #getMessageId() 334 */ 335 public boolean equals(Object object) { 336 boolean result = (object instanceof MessageHandle); 337 if (result) { 338 result 339 = _messageId.equals( 340 ((MessageHandle) object).getMessageId()); 341 } 342 return result; 343 } 344 345 /*** 346 * Returns a hash code value for the object. 347 * 348 * @return a hash code value for this object 349 */ 350 public int hashCode() { 351 return _messageId.hashCode(); 352 } 353 354 /*** 355 * Return a stringified version of the handle. 356 * 357 * @return a stringified version of the handle 358 */ 359 public String toString() { 360 return "MessageHandle : " + _priority + ":" + getAcceptedTime() + 361 ":" + getSequenceNumber() + ":" + _messageId; 362 } 363 364 /*** 365 * Destroy this handle. If this is the last handle to reference the message, 366 * also destroys the message. 367 * 368 * @throws JMSException for any error 369 */ 370 public void destroy() throws JMSException { 371 getMessageRef().dereference(); 372 } 373 374 /*** 375 * Release the message handle back to the cache, to recover an unsent or 376 * unacknowledged message. 377 * 378 * @throws JMSException for any error 379 */ 380 public void release() throws JMSException { 381 if (_cache == null) { 382 throw new IllegalStateException( 383 "Can't release message: not associated with any cache"); 384 } 385 _cache.returnMessageHandle(this); 386 } 387 388 /*** 389 * Returns the message reference. 390 * 391 * @return the message reference, or <code>null</code> if none has been set 392 */ 393 public MessageRef getMessageRef() { 394 return _reference; 395 } 396 397 /*** 398 * Sets the message reference. 399 * 400 * @param reference the reference to the message 401 */ 402 protected void setMessageRef(MessageRef reference) { 403 _reference = reference; 404 } 405 406 /*** 407 * Sets the destination cache. 408 * 409 * @param cache the destination cache 410 */ 411 protected void setDestinationCache(DestinationCache cache) { 412 _cache = cache; 413 } 414 415 /*** 416 * Release the message handle back to the cache, to recover an unsent or 417 * unacknowledged message. 418 * <p/> 419 * This should be used when the parent in a chain of handles needs to be 420 * released. 421 * 422 * @param handle the handle to release 423 * @throws JMSException for any error 424 */ 425 protected void release(MessageHandle handle) throws JMSException { 426 if (_cache == null) { 427 throw new IllegalStateException( 428 "Can't release message: not associated with any cache"); 429 } 430 _cache.returnMessageHandle(handle); 431 } 432 433 434 435 }