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: PersistentMessageHandle.java,v 1.17 2003/08/07 13:33:04 tanderson Exp $ 44 * 45 * Date Author Changes 46 * 3/1/2001 jima Created 47 */ 48 package org.exolab.jms.messagemgr; 49 50 import java.io.IOException; 51 import java.io.ObjectInput; 52 import java.io.ObjectOutput; 53 import java.sql.Connection; 54 55 import javax.jms.DeliveryMode; 56 import javax.jms.JMSException; 57 import javax.transaction.TransactionManager; 58 59 import org.exolab.core.foundation.PersistentObject; 60 import org.exolab.jms.client.JmsDestination; 61 import org.exolab.jms.client.JmsQueue; 62 import org.exolab.jms.client.JmsTopic; 63 import org.exolab.jms.message.MessageHandle; 64 import org.exolab.jms.message.MessageId; 65 import org.exolab.jms.message.MessageImpl; 66 import org.exolab.jms.persistence.DatabaseService; 67 import org.exolab.jms.persistence.PersistenceException; 68 69 70 /*** 71 * A persistent message handle extends {@link MessageHandle} and references a 72 * persistent message. These messages can be discarded from the cache and later 73 * faulted in through the 'resolve' method. 74 * 75 * @version $Revision: 1.17 $ $Date: 2003/08/07 13:33:04 $ 76 * @author <a href="mailto:jima@exoffice.com">Jim Alateras</a> 77 **/ 78 public class PersistentMessageHandle 79 extends PersistentObject 80 implements MessageHandle, Cloneable { 81 82 /*** 83 * Used for serialization 84 */ 85 static final long serialVersionUID = 1; 86 87 /*** 88 * This is the message id of the underlying message 89 */ 90 private MessageId _id = null; 91 92 /*** 93 * This is the priority of the inderlying message 94 */ 95 private int _priority; 96 97 /*** 98 * A flag indicating whether an attempt was made to deliver the message 99 */ 100 private boolean _delivered; 101 102 /*** 103 * a transient attribute, to associate this handle with an endpoint 104 */ 105 private transient long _clientId = -1; 106 107 /* 108 * The time that the underlying message was accepted by the server 109 */ 110 private long _acceptedTime; 111 112 /*** 113 * This is the sequence number assigned to it by the message manager 114 * that created this handle 115 */ 116 private long _sequenceNumber; 117 118 /*** 119 * The expiry time of this message. 0 if it doesn't expire 120 */ 121 private long _expiryTime; 122 123 /*** 124 * The name of the durable consumer that this handle belongs too 125 */ 126 private String _consumerName; 127 128 /*** 129 * The destination that this handle belongs too 130 */ 131 private JmsDestination _destination; 132 133 134 /*** 135 * Cache the hashcode for this object 136 */ 137 private transient int _hashCode = -1; 138 139 140 /*** 141 * Default constructor 142 */ 143 public PersistentMessageHandle() { 144 super(); 145 } 146 147 /*** 148 * Create a persistent handle from a message 149 * 150 * @param message - persistent message 151 * @exception JMSException - if the object cannot be constructed 152 */ 153 public PersistentMessageHandle(MessageImpl message) 154 throws JMSException { 155 super(); 156 157 if ((message != null) && 158 (message.getJMSDeliveryMode() == DeliveryMode.PERSISTENT)) { 159 _id = message.getMessageId(); 160 _priority = message.getJMSPriority(); 161 _delivered = message.getJMSRedelivered(); 162 _destination = (JmsDestination) message.getJMSDestination(); 163 _acceptedTime = message.getAcceptedTime(); 164 _expiryTime = message.getJMSExpiration(); 165 _sequenceNumber = message.getSequenceNumber(); 166 _clientId = message.getClientId(); 167 } else { 168 throw new JMSException( 169 "Cannot create persistent handle from non-persistent message"); 170 } 171 } 172 173 /*** 174 * Set the identity of the underlying message 175 * 176 * @param id - the message id 177 */ 178 public void setMessageId(MessageId id) { 179 _id = id; 180 } 181 182 /*** 183 * Return the identity of the underlying message 184 * 185 * @return MessageId 186 */ 187 public MessageId getMessageId() { 188 return _id; 189 } 190 191 /*** 192 * Return the associated message or null if it is invalid 193 * 194 * @return MessageImpl 195 */ 196 public MessageImpl getMessage() { 197 return (MessageImpl) MessageMgr.instance().getMessage(this); 198 } 199 200 /*** 201 * Set the messagee priority 202 * 203 * @param id the persistent id 204 */ 205 public void setPriority(int priority) { 206 _priority = priority; 207 } 208 209 /*** 210 * Return the priority of the corresponding message 211 * 212 * @return int 213 */ 214 public int getPriority() { 215 return _priority; 216 } 217 218 /*** 219 * Set the delivered flag for the underlying message. True if an attempt 220 * has been made to deliver the message 221 * 222 * @param value - true if delivered 223 */ 224 public void setDelivered(boolean value) { 225 _delivered = value; 226 } 227 228 /*** 229 * Return the delivered state of the message 230 * 231 * @return long 232 */ 233 public boolean getDelivered() { 234 return _delivered; 235 } 236 237 /*** 238 * Set the time that the message was accepted by the server 239 * 240 * @param long - time since epoch 241 */ 242 public void setAcceptedTime(long time) { 243 _acceptedTime = time; 244 } 245 246 /*** 247 * Return the time that the message was accepted by the server 248 * 249 * @return long - time in ms since epoch 250 */ 251 public long getAcceptedTime() { 252 return _acceptedTime; 253 } 254 255 /*** 256 * Set the message's sequence number 257 * 258 * @param seq - sequence time 259 */ 260 public void setSequenceNumber(long seq) { 261 _sequenceNumber = seq; 262 } 263 264 /*** 265 * Return message's sequence number 266 * 267 * @return long - the sequence number 268 */ 269 public long getSequenceNumber() { 270 return _sequenceNumber; 271 } 272 273 /*** 274 * Set the message expiry time 275 * 276 * @long time - time in ms since epoch 277 */ 278 public void setExpiryTime(long time) { 279 _expiryTime = time; 280 } 281 282 /*** 283 * Return the message expiry time 284 * 285 * @return long - time in ms since epoch 286 */ 287 public long getExpiryTime() { 288 return _expiryTime; 289 } 290 291 /*** 292 * Determines if the message has expired 293 * 294 * @return <code>true</code> if the message has expired, otherwise 295 * <code>false</code> 296 */ 297 public boolean hasExpired() { 298 return (_expiryTime != 0 && _expiryTime <= System.currentTimeMillis()); 299 } 300 301 // implementation of MessageHandle.setConsumerName 302 public void setConsumerName(String name) { 303 _consumerName = name; 304 } 305 306 // implementation of MessageHandle.getConsumerName 307 public String getConsumerName() { 308 return _consumerName; 309 } 310 311 // implementation of MessageHandle.isPersistent 312 public boolean isPersistent() { 313 return true; 314 } 315 316 /*** 317 * Set the destination that owns this handle 318 * 319 * @param destination - the destination 320 */ 321 public void setDestination(JmsDestination destination) { 322 _destination = destination; 323 } 324 325 /*** 326 * Return the destination for this handle 327 * 328 * @return JmsDestination 329 */ 330 public JmsDestination getDestination() { 331 return _destination; 332 } 333 334 /*** 335 * Set the client id, that owns this handle 336 * 337 * @param clientId - client identity 338 */ 339 public void setClientId(long clientId) { 340 _clientId = clientId; 341 } 342 343 /*** 344 * Retrieve the client identity associated with this handle 345 * 346 * @return long 347 */ 348 public long getClientId() { 349 return _clientId; 350 } 351 352 /*** 353 * Override the behaviour of the base class. I don't think we want to 354 * clear the handle unless there are definitely no more references. 355 */ 356 public void clear() { 357 } 358 359 /*** 360 * Destroy this handle 361 */ 362 public void destroy() { 363 // notify the message manager 364 MessageMgr.instance().handleDestroyed(this); 365 366 // remove the handle from the database 367 Connection connection = null; 368 TransactionManager tm = null; 369 370 try { 371 connection = DatabaseService.getConnection(); 372 DatabaseService.getAdapter().removeMessageHandle(connection, this); 373 connection.commit(); 374 } catch (PersistenceException exception) { 375 if (connection != null) { 376 try { 377 connection.rollback(); 378 } catch (Exception nested) { 379 // ignore 380 } 381 } 382 } catch (Exception exception) { 383 // ignore for the moment 384 } finally { 385 if (connection != null) { 386 try { 387 connection.close(); 388 } catch (Exception nested) { 389 // ignore 390 } 391 } 392 } 393 } 394 395 /*** 396 * Clone the persistent message handle object 397 * 398 * @return copy of a PersistentMessageHandle 399 * @throws CloneNotSupportedException 400 */ 401 public Object clone() throws CloneNotSupportedException { 402 PersistentMessageHandle handle = 403 (PersistentMessageHandle) super.clone(); 404 405 handle._id = new MessageId(_id.getId()); 406 handle._priority = _priority; 407 handle._delivered = _delivered; 408 handle._acceptedTime = _acceptedTime; 409 handle._expiryTime = _expiryTime; 410 handle._consumerName = _consumerName; 411 handle._sequenceNumber = _sequenceNumber; 412 413 // clone the destination 414 if (_destination instanceof JmsQueue) { 415 handle._destination = new JmsQueue(_destination.getName()); 416 } else { 417 handle._destination = new JmsTopic(_destination.getName()); 418 } 419 handle._destination.setPersistent(true); 420 421 return handle; 422 } 423 424 // override the definition of equals 425 public boolean equals(Object object) { 426 427 boolean result = false; 428 429 if ((object != null) && 430 (object instanceof PersistentMessageHandle)) { 431 432 PersistentMessageHandle mhdl = (PersistentMessageHandle) object; 433 if (mhdl._id.equals(_id)) { 434 result = true; 435 } 436 437 //if ((mhdl._id.equals(_id)) && 438 // (mhdl._consumerName.equals(_consumerName))) { 439 // result = true; 440 //} 441 } 442 443 return result; 444 } 445 446 // override the Object.toString() 447 public String toString() { 448 return ("Handle : " + _id.getId() + "@" + _consumerName + ":" + 449 _sequenceNumber + ":" + _acceptedTime + ":" + _priority); 450 } 451 452 453 // override the definition of hashCode 454 public int hashCode() { 455 if (_hashCode == -1) { 456 _hashCode = (_id + _consumerName).hashCode(); 457 } 458 459 return _hashCode; 460 } 461 462 /*** 463 * This is used to set the message as delivered. This can only be called 464 * by the delivery engine and should not be used anywhere else. This will 465 * mark the message as being delivered and also update the database 466 * <p> 467 * We do not really throw an exception here....and it seems that this is 468 * a very fine grained approach to dealing with this...basically translates to 469 * a transaction for every message. 470 */ 471 public void setDelivered() { 472 if (!_delivered) { 473 474 Connection connection = null; 475 TransactionManager tm = null; 476 477 try { 478 connection = DatabaseService.getConnection(); 479 480 DatabaseService.getAdapter().updateMessageHandle(connection, 481 this); 482 _delivered = true; 483 484 // commit the transactions 485 connection.commit(); 486 } catch (PersistenceException exception) { 487 System.err.println("Failed in setDelivereds b/c " + 488 exception.toString()); 489 if (connection != null) { 490 try { 491 connection.rollback(); 492 } catch (Exception nested) { 493 // ignore 494 } 495 } 496 } catch (Exception exception) { 497 // ignore for the moment 498 } finally { 499 if (connection != null) { 500 try { 501 connection.close(); 502 } catch (Exception nested) { 503 // ignore 504 } 505 } 506 } 507 } 508 } 509 510 // implementation of Externalizable.writeExternal 511 public void writeExternal(ObjectOutput stream) 512 throws IOException { 513 stream.writeLong(serialVersionUID); 514 stream.writeObject(_id); 515 stream.writeInt(_priority); 516 stream.writeBoolean(_delivered); 517 stream.writeLong(_acceptedTime); 518 stream.writeLong(_sequenceNumber); 519 stream.writeLong(_expiryTime); 520 stream.writeObject(_consumerName); 521 stream.writeObject(_destination); 522 super.writeExternal(stream); 523 } 524 525 // implementation of Externalizable.writeExternal 526 public void readExternal(ObjectInput stream) 527 throws IOException, ClassNotFoundException { 528 long version = stream.readLong(); 529 if (version == serialVersionUID) { 530 _id = (MessageId) stream.readObject(); 531 _priority = stream.readInt(); 532 _delivered = stream.readBoolean(); 533 _acceptedTime = stream.readLong(); 534 _sequenceNumber = stream.readLong(); 535 _expiryTime = stream.readLong(); 536 _consumerName = (String) stream.readObject(); 537 _destination = (JmsDestination) stream.readObject(); 538 super.readExternal(stream); 539 } else { 540 throw new IOException("PersistentMessageHandle with version " + 541 version + " is not supported."); 542 } 543 } 544 } 545

This page was automatically generated by Maven