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 2000-2003 (C) Exoffice Technologies Inc. All Rights Reserved. 42 */ 43 44 package org.exolab.jms.persistence; 45 46 import java.sql.Connection; 47 import java.sql.PreparedStatement; 48 import java.sql.ResultSet; 49 import java.util.HashMap; 50 import java.util.Iterator; 51 import java.util.Vector; 52 53 import org.exolab.jms.client.JmsDestination; 54 import org.exolab.jms.client.JmsQueue; 55 import org.exolab.jms.client.JmsTopic; 56 57 58 /*** 59 * This class provides persistency for JmsDestination objects 60 * in an RDBMS database 61 * 62 * @version $Revision: 1.10 $ $Date: 2003/08/07 13:33:06 $ 63 * @author <a href="mailto:tima@intalio.com">Tim Anderson</a> 64 * @see org.exolab.jms.client.JmsDestination 65 * @see org.exolab.jms.persistence.RDBMSAdapter 66 **/ 67 class Destinations { 68 69 /*** 70 * Cache of all destinations indexed on names 71 */ 72 private HashMap _destinations; 73 74 /*** 75 * Cache of all destinations indexed on identity 76 */ 77 private HashMap _ids; 78 79 /*** 80 * Singleton instance of this class 81 */ 82 private static Destinations _instance; 83 84 /*** 85 * This is used to synchronize the creation of the singleton 86 */ 87 private static final Object _block = new Object(); 88 89 /*** 90 * This is the name of the destination id generator, which uniquely created 91 * identities for destinations 92 */ 93 private static final String DESTINATION_ID_SEED = "destinationId"; 94 95 /*** 96 * Constructor 97 * 98 * @throws PersistenceException - if constructor fails 99 */ 100 private Destinations() 101 throws PersistenceException { 102 103 _destinations = new HashMap(); 104 _ids = new HashMap(); 105 } 106 107 /*** 108 * Returns the singleton instance. 109 * 110 * Note that initialise() must have been invoked first for this 111 * to return a valid instance. 112 * 113 * @return Destinations the singleton instance 114 */ 115 public static Destinations instance() { 116 return _instance; 117 } 118 119 /*** 120 * Initialise the singleton instance 121 * 122 * @param connection - the connection to use 123 * @return Destinations - the singleton instance 124 * @throws PersistenceException - if initialisation fails 125 */ 126 public static Destinations initialise(Connection connection) 127 throws PersistenceException { 128 129 if (_instance == null) { 130 synchronized (_block) { 131 if (_instance == null) { 132 _instance = new Destinations(); 133 _instance.load(connection); 134 } 135 } 136 } 137 return _instance; 138 } 139 140 /*** 141 * Add a new destination to the database. This method will also assign 142 * it a unique identity. 143 * 144 * @param connection - the connection to use. 145 * @param destination - the destination to add 146 * @throws PersistenceException - if the destination cannot be added 147 */ 148 public synchronized void add(Connection connection, 149 JmsDestination destination) 150 throws PersistenceException { 151 152 PreparedStatement insert = null; 153 try { 154 long Id = SeedGenerator.instance().next(connection, 155 DESTINATION_ID_SEED); 156 boolean isQueue = (destination instanceof JmsQueue); 157 158 insert = connection.prepareStatement( 159 "insert into destinations values (?, ?, ?)"); 160 insert.setString(1, destination.getName()); 161 insert.setBoolean(2, isQueue); 162 insert.setLong(3, Id); 163 insert.executeUpdate(); 164 cache(destination, Id); 165 } catch (Exception error) { 166 throw new PersistenceException("Destinations.add failed with " + 167 error.toString()); 168 } finally { 169 SQLHelper.close(insert); 170 } 171 } 172 173 /*** 174 * Remove a destination from the database. 175 * This removes all associated consumers, and messages. 176 * 177 * @param connection - the connection to use 178 * @param destination - the destination 179 * @return boolean - <tt>true</tt> if it was removed 180 * @throws PersistenceException - if the request fails 181 */ 182 public synchronized boolean remove(Connection connection, 183 JmsDestination destination) 184 throws PersistenceException { 185 186 boolean success = false; 187 PreparedStatement deleteDestinations = null; 188 PreparedStatement deleteMessages = null; 189 PreparedStatement deleteConsumers = null; 190 PreparedStatement deleteMessageHandles = null; 191 192 Pair pair = (Pair) _destinations.get(destination.getName()); 193 if (pair != null) { 194 try { 195 deleteDestinations = connection.prepareStatement( 196 "delete from destinations where name=?"); 197 deleteDestinations.setString(1, destination.getName()); 198 199 deleteMessages = connection.prepareStatement( 200 "delete from messages where destinationId=?"); 201 deleteMessages.setLong(1, pair.Id); 202 203 deleteMessageHandles = connection.prepareStatement( 204 "delete from message_handles where destinationId=?"); 205 deleteMessageHandles.setLong(1, pair.Id); 206 207 deleteConsumers = connection.prepareStatement( 208 "delete from consumers where destinationId=?"); 209 deleteConsumers.setLong(1, pair.Id); 210 211 212 deleteDestinations.executeUpdate(); 213 deleteMessages.executeUpdate(); 214 deleteMessageHandles.executeUpdate(); 215 deleteConsumers.executeUpdate(); 216 217 Consumers.instance().removeCached(pair.Id); 218 _destinations.remove(destination.getName()); 219 _ids.remove(new Long(pair.Id)); 220 success = true; 221 } catch (Exception error) { 222 throw new PersistenceException("Destinations.remove failed " + 223 error.toString()); 224 } finally { 225 SQLHelper.close(deleteDestinations); 226 SQLHelper.close(deleteMessages); 227 SQLHelper.close(deleteConsumers); 228 SQLHelper.close(deleteMessageHandles); 229 } 230 } 231 232 return success; 233 } 234 235 /*** 236 * Returns the destination associated with name 237 * 238 * @param name - the name of the destination 239 * @return JmsDestination - the destination, or null 240 */ 241 public synchronized JmsDestination get(String name) { 242 Pair pair = (Pair) _destinations.get(name); 243 return (pair != null) ? pair.destination : null; 244 } 245 246 /*** 247 * Returns the destination associated with Id 248 * 249 * @param id - the destination Id 250 * @return JmsDestination - the destination or null 251 */ 252 public synchronized JmsDestination get(long id) { 253 Pair pair = (Pair) _ids.get(new Long(id)); 254 return (pair != null) ? pair.destination : null; 255 } 256 257 /*** 258 * Returns the Id for a given destination name 259 * 260 * @param name - the destination name 261 * @return long - the destination Id, or 0 262 */ 263 public synchronized long getId(String name) { 264 Pair pair = (Pair) _destinations.get(name); 265 return (pair != null) ? pair.Id : 0; 266 } 267 268 /*** 269 * Returns the list of destination names 270 * 271 * @return Vector - list of destination names 272 */ 273 public synchronized Vector getNames() { 274 // return a Vector for legacy reasons. 275 Vector result = new Vector(_destinations.size()); 276 Iterator iter = _destinations.keySet().iterator(); 277 while (iter.hasNext()) { 278 result.add((String) iter.next()); 279 } 280 281 return result; 282 } 283 284 /*** 285 * Returns the list of destination objects 286 * 287 * @return Vector - list of destination objects 288 */ 289 public synchronized Vector getDestinations() { 290 // return a Vector for legacy reasons. 291 Vector result = new Vector(_destinations.size()); 292 Iterator iter = _destinations.values().iterator(); 293 while (iter.hasNext()) { 294 result.add(((Pair) iter.next()).destination); 295 } 296 297 return result; 298 } 299 300 /*** 301 * Deallocates resources owned or referenced by the instance 302 */ 303 public synchronized void close() { 304 _destinations.clear(); 305 _destinations = null; 306 307 _ids.clear(); 308 _ids = null; 309 310 _instance = null; 311 } 312 313 /*** 314 * Load all the destinations in memory. It uses the transaction service 315 * and the database service to access the appropriate resources. 316 * 317 * @param connection - the connection to use 318 * @throws PersistenceException - problems loading the destinations 319 */ 320 private void load(Connection connection) 321 throws PersistenceException { 322 323 PreparedStatement select = null; 324 ResultSet set = null; 325 try { 326 select = connection.prepareStatement( 327 "select * from destinations"); 328 329 set = select.executeQuery(); 330 while (set.next()) { 331 String name = set.getString("name"); 332 boolean isQueue = set.getBoolean("isQueue"); 333 JmsDestination destination = (isQueue) 334 ? (JmsDestination) new JmsQueue(name) 335 : (JmsDestination) new JmsTopic(name); 336 long Id = set.getLong("destinationId"); 337 destination.setPersistent(true); 338 cache(destination, Id); 339 } 340 } catch (Exception error) { 341 throw new PersistenceException("Error in Destinations.load " + 342 error.toString()); 343 } finally { 344 if (select != null) { 345 SQLHelper.close(select); 346 } 347 348 if (set != null) { 349 SQLHelper.close(set); 350 } 351 } 352 } 353 354 /*** 355 * This method is used to cache a destination 356 * 357 * @param destination - the destination to cache 358 * @param Id - the destination identity 359 */ 360 private void cache(JmsDestination destination, long Id) { 361 Pair pair = new Pair(destination, Id); 362 363 _destinations.put(destination.getName(), pair); 364 _ids.put(new Long(Id), pair); 365 } 366 367 368 /*** 369 * This private static class holds the name and identity of the 370 * destination 371 */ 372 private static class Pair { 373 374 public Pair(JmsDestination destination, long Id) { 375 this.destination = destination; 376 this.Id = Id; 377 } 378 379 public JmsDestination destination; 380 public long Id; 381 } 382 }

This page was automatically generated by Maven