1 10 11 package com.triactive.jdo; 12 13 import com.triactive.jdo.store.DatabaseAdapter; 14 import java.sql.Connection ; 15 import java.sql.SQLException ; 16 import javax.jdo.JDOFatalDataStoreException; 17 import javax.jdo.JDOUnsupportedOptionException; 18 import javax.jdo.PersistenceManager; 19 import javax.sql.DataSource ; 20 import javax.transaction.Status ; 21 import javax.transaction.Synchronization ; 22 import org.apache.log4j.Category; 23 24 25 class NonmanagedTransaction implements Transaction 26 { 27 32 public static final String USE_UPDATE_LOCK_PROPERTY = "com.triactive.jdo.useUpdateLock"; 33 34 private static final Category LOG = Category.getInstance(NonmanagedTransaction.class); 35 private static boolean useUpdateLockProperty = Boolean.getBoolean(USE_UPDATE_LOCK_PROPERTY); 36 37 private final PersistenceManagerImpl pm; 38 private final DatabaseAdapter dba; 39 private final DataSource tds; 40 private final DataSource ntds; 41 private final String userName; 42 private final String password; 43 44 private boolean retainValues; 45 private boolean restoreValues; 46 private boolean optimistic; 47 private boolean nontransactionalRead; 48 private boolean nontransactionalWrite; 49 private int isolationLevel; 50 private boolean useUpdateLock; 51 52 private Synchronization sync = null; 53 private Connection conn = null; 54 private boolean active = false; 55 private boolean completing = false; 56 57 public NonmanagedTransaction(PersistenceManagerImpl pm, String userName, String password) 58 { 59 this.pm = pm; 60 this.dba = pm.getStoreManager().getDatabaseAdapter(); 61 62 PersistenceManagerFactoryImpl pmf = (PersistenceManagerFactoryImpl)pm.getPersistenceManagerFactory(); 63 64 this.tds = pmf.getTransactionalDataSource(); 65 this.ntds = pmf.getNontransactionalDataSource(); 66 this.userName = userName; 67 this.password = password; 68 69 setRetainValues(pmf.getRetainValues()); 70 setRestoreValues(pmf.getRestoreValues()); 71 setOptimistic(pmf.getOptimistic()); 72 setNontransactionalRead(pmf.getNontransactionalRead()); 73 setNontransactionalWrite(pmf.getNontransactionalWrite()); 74 setTransactionIsolation(pmf.getTransactionIsolation()); 75 } 76 77 public PersistenceManager getPersistenceManager() 78 { 79 return pm; 80 } 81 82 83 public synchronized Connection getConnection(boolean forWriting) throws SQLException 84 { 85 if (active) 86 { 87 91 pm.flushDirty(); 92 } 93 else 94 { 95 if (!nontransactionalRead || (forWriting && !nontransactionalWrite)) 96 throw new TransactionNotActiveException(); 97 98 if (conn != null) 99 throw new ConnectionInUseException(); 100 101 conn = dba.getConnection(ntds, userName, password, Connection.TRANSACTION_NONE); 102 } 103 104 return conn; 105 } 106 107 108 public synchronized void releaseConnection(Connection conn) throws SQLException 109 { 110 if (conn == this.conn) 111 { 112 if (!active) 113 closeConnection(); 114 } 115 } 116 117 118 public boolean useUpdateLockOnFetch() 119 { 120 return active ? useUpdateLock : false; 121 } 122 123 124 private void closeConnection() throws SQLException 125 { 126 try 127 { 128 dba.closeConnection(conn); 129 } 130 finally 131 { 132 conn = null; 133 } 134 } 135 136 137 private void assertNotInUse() 138 { 139 if (active) 140 throw new TransactionActiveException(); 141 142 if (conn != null) 143 throw new ConnectionInUseException(); 144 } 145 146 147 private void assertNotCompleting() 148 { 149 if (completing) 150 throw new TransactionCompletionException(); 151 } 152 153 154 private void assertCanComplete() 155 { 156 assertNotCompleting(); 157 158 if (!active) 159 throw new TransactionNotActiveException(); 160 } 161 162 163 public synchronized void begin() 164 { 165 assertNotInUse(); 166 167 try 168 { 169 conn = dba.getConnection(tds, userName, password, isolationLevel); 170 171 active = true; 172 173 if (LOG.isDebugEnabled()) 174 LOG.debug("Transaction begun, connection = " + conn); 175 } 176 catch (SQLException e) 177 { 178 throw new JDOFatalDataStoreException("Failed beginning transaction", e); 179 } 180 } 181 182 183 public synchronized void commit() 184 { 185 assertCanComplete(); 186 187 completing = true; 188 189 try 190 { 191 boolean success = false; 192 193 try 194 { 195 try 196 { 197 if (LOG.isDebugEnabled()) 198 LOG.debug("Transaction committing, connection = " + conn); 199 200 pm.flushDirty(); 201 202 if (sync != null) 203 sync.beforeCompletion(); 204 205 conn.commit(); 206 207 success = true; 208 } 209 finally 210 { 211 if (!success) 212 { 213 try 214 { 215 pm.preRollback(); 216 } 217 finally 218 { 219 conn.rollback(); 220 } 221 } 222 } 223 } 224 finally 225 { 226 try 227 { 228 active = false; 229 closeConnection(); 230 } 231 finally 232 { 233 try 234 { 235 if (success) 236 pm.postCommit(); 237 } 238 finally 239 { 240 if (sync != null) 241 { 242 if (success) 243 sync.afterCompletion(Status.STATUS_COMMITTED); 244 else 245 sync.afterCompletion(Status.STATUS_ROLLEDBACK); 246 } 247 } 248 } 249 } 250 } 251 catch (SQLException e) 252 { 253 throw new JDOFatalDataStoreException("Failed committing transaction", e); 254 } 255 finally 256 { 257 completing = false; 258 } 259 } 260 261 262 public synchronized void rollback() 263 { 264 assertCanComplete(); 265 266 completing = true; 267 268 try 269 { 270 try 271 { 272 try 273 { 274 if (LOG.isDebugEnabled()) 275 LOG.debug("Transaction rolling back, connection = " + conn); 276 277 pm.preRollback(); 278 } 279 finally 280 { 281 conn.rollback(); 282 } 283 } 284 finally 285 { 286 try 287 { 288 active = false; 289 closeConnection(); 290 } 291 finally 292 { 293 if (sync != null) 294 sync.afterCompletion(Status.STATUS_ROLLEDBACK); 295 } 296 } 297 } 298 catch (SQLException e) 299 { 300 throw new JDOFatalDataStoreException("Failed rolling back transaction", e); 301 } 302 finally 303 { 304 completing = false; 305 } 306 } 307 308 309 public boolean isActive() 310 { 311 return active; 312 } 313 314 public synchronized void setNontransactionalRead(boolean nontransactionalRead) 315 { 316 assertNotCompleting(); 317 318 this.nontransactionalRead = nontransactionalRead; 319 } 320 321 public boolean getNontransactionalRead() 322 { 323 return nontransactionalRead; 324 } 325 326 public synchronized void setNontransactionalWrite(boolean nontransactionalWrite) 327 { 328 assertNotCompleting(); 329 330 if (nontransactionalWrite) 331 throw new JDOUnsupportedOptionException("Non-transactional write mode not (yet) supported"); 332 333 this.nontransactionalWrite = nontransactionalWrite; 334 } 335 336 public boolean getNontransactionalWrite() 337 { 338 return nontransactionalWrite; 339 } 340 341 public synchronized void setRetainValues(boolean retainValues) 342 { 343 assertNotCompleting(); 344 345 this.retainValues = retainValues; 346 347 if (retainValues) 348 nontransactionalRead = true; 349 } 350 351 public boolean getRetainValues() 352 { 353 return retainValues; 354 } 355 356 357 public synchronized void setRestoreValues(boolean restoreValues) 358 { 359 assertNotInUse(); 360 361 this.restoreValues = restoreValues; 362 } 363 364 365 public boolean getRestoreValues() 366 { 367 return restoreValues; 368 } 369 370 371 public synchronized void setOptimistic(boolean optimistic) 372 { 373 assertNotInUse(); 374 375 if (optimistic) 376 throw new JDOUnsupportedOptionException("Optimistic mode not (yet) supported"); 377 378 this.optimistic = optimistic; 379 } 380 381 public boolean getOptimistic() 382 { 383 return optimistic; 384 } 385 386 public synchronized void setTransactionIsolation(int isolationLevel) 387 { 388 assertNotInUse(); 389 390 switch (isolationLevel) 391 { 392 case Connection.TRANSACTION_READ_UNCOMMITTED: 393 case Connection.TRANSACTION_READ_COMMITTED: 394 useUpdateLock = useUpdateLockProperty; 395 break; 396 397 case Connection.TRANSACTION_REPEATABLE_READ: 398 case Connection.TRANSACTION_SERIALIZABLE: 399 useUpdateLock = false; 400 break; 401 402 default: 403 throw new IllegalArgumentException ("Illegal isolation level: " + isolationLevel); 404 } 405 406 this.isolationLevel = isolationLevel; 407 } 408 409 public int getTransactionIsolation() 410 { 411 return isolationLevel; 412 } 413 414 public synchronized void setSynchronization(Synchronization sync) 415 { 416 assertNotCompleting(); 417 418 this.sync = sync; 419 } 420 421 public Synchronization getSynchronization() 422 { 423 return sync; 424 } 425 } 426 | Popular Tags |