1 23 24 package org.apache.slide.store.txfile; 25 26 import org.apache.commons.transaction.file.ResourceManager; 27 import org.apache.commons.transaction.file.ResourceManagerException; 28 import org.apache.slide.common.*; 29 import org.apache.slide.store.*; 30 import org.apache.slide.structure.*; 31 32 import org.apache.slide.security.*; 33 import org.apache.slide.util.logger.Logger; 34 import org.apache.slide.lock.*; 35 import org.apache.slide.content.*; 36 37 import java.util.Collection ; 38 import java.util.Enumeration ; 39 import java.util.HashMap ; 40 import java.util.Hashtable ; 41 import java.util.Iterator ; 42 import java.util.Map ; 43 44 import javax.transaction.xa.XAException ; 45 import javax.transaction.xa.Xid ; 46 47 56 public class TxXMLFileDescriptorsStore 57 extends AbstractTxFileStoreService 58 implements NodeStore, LockStore, RevisionDescriptorsStore, RevisionDescriptorStore, SecurityStore { 59 60 protected static final String LOG_CHANNEL = "file-meta-store"; 61 62 protected static final int DEBUG_LEVEL = Logger.DEBUG; 63 64 protected static final String ENCODING_PARAMETER = "encoding"; 65 66 protected static final String DEFER_SAVING_PARAMETER = "defer-saving"; 67 68 protected String characterEncoding = "UTF-8"; protected boolean deferSaving = false; 71 protected Map suspendedContexts = new HashMap (); 72 protected Map activeContexts = new HashMap (); 73 74 public void setParameters(Hashtable parameters) 75 throws ServiceParameterErrorException, ServiceParameterMissingException { 76 77 super.setParameters(parameters); 78 79 String encoding = (String ) parameters.get(ENCODING_PARAMETER); 80 if (encoding != null) { 81 characterEncoding = encoding; 82 } 83 84 String deferSavingString = (String ) parameters.get(DEFER_SAVING_PARAMETER); 85 if (deferSavingString != null) { 86 deferSaving = Boolean.valueOf(deferSavingString).booleanValue(); 87 if (deferSaving) { 88 getLogger().log( 89 "Enabling deferred saving", 90 LOG_CHANNEL, 91 Logger.INFO); 92 } 93 } 94 } 95 96 101 102 public ObjectNode retrieveObject(Uri uri) throws ServiceAccessException, ObjectNotFoundException { 103 XMLResourceDescriptor xfd = getFileDescriptor(uri); 104 ObjectNode object = xfd.retrieveObject(); 105 return object; 106 } 107 108 public void storeObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectNotFoundException { 109 XMLResourceDescriptor xfd = getFileDescriptor(uri); 110 xfd.storeObject(object); 111 if (deferSaving) { 112 xfd.registerForSaving(); 113 } else { 114 xfd.save(); 115 } 116 } 117 118 public void createObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectAlreadyExistsException { 119 try { 120 XMLResourceDescriptor xfd = getFileDescriptor(uri); 121 xfd.create(); 122 xfd.storeObject(object); 123 if (deferSaving) { 124 xfd.registerForSaving(); 125 TxContext txContext = getActiveTxContext(); 126 if (txContext != null) { 127 txContext.register(uri, xfd); 128 } 129 } else { 130 xfd.save(); 131 } 132 } catch (ObjectNotFoundException e) { 133 throwInternalError("Newly created file vanished"); 135 } 136 } 137 138 public void removeObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectNotFoundException { 139 XMLResourceDescriptor xfd = getFileDescriptor(uri); 140 xfd.delete(); 141 if (deferSaving) { 142 TxContext txContext = getActiveTxContext(); 143 if (txContext != null) { 144 txContext.deregister(uri); 145 } 146 } 147 } 148 149 154 155 public void grantPermission(Uri uri, NodePermission permission) throws ServiceAccessException { 156 try { 157 XMLResourceDescriptor xfd = getFileDescriptor(uri); 158 xfd.grantPermission(permission); 159 if (deferSaving) { 160 xfd.registerForSaving(); 161 } else { 162 xfd.save(); 163 } 164 } catch (ObjectNotFoundException e) { 165 throwInternalError(e); 166 } 167 } 168 169 public void revokePermission(Uri uri, NodePermission permission) throws ServiceAccessException { 170 try { 171 XMLResourceDescriptor xfd = getFileDescriptor(uri); 172 xfd.revokePermission(permission); 173 if (deferSaving) { 174 xfd.registerForSaving(); 175 } else { 176 xfd.save(); 177 } 178 } catch (ObjectNotFoundException e) { 179 throwInternalError(e); 180 } 181 } 182 183 public void revokePermissions(Uri uri) throws ServiceAccessException { 184 try { 185 XMLResourceDescriptor xfd = getFileDescriptor(uri); 186 xfd.revokePermissions(); 187 if (deferSaving) { 188 xfd.registerForSaving(); 189 } else { 190 xfd.save(); 191 } 192 } catch (ObjectNotFoundException e) { 193 throwInternalError(e); 194 } 195 } 196 197 public Enumeration enumeratePermissions(Uri uri) throws ServiceAccessException { 198 try { 199 XMLResourceDescriptor xfd = getFileDescriptor(uri); 200 return xfd.enumeratePermissions(); 201 } catch (ObjectNotFoundException e) { 202 throwInternalError(e); 203 return null; } 205 } 206 207 212 213 public void putLock(Uri uri, NodeLock lock) throws ServiceAccessException { 214 try { 215 XMLResourceDescriptor xfd = getFileDescriptor(uri); 216 xfd.putLock(lock); 217 if (deferSaving) { 218 xfd.registerForSaving(); 219 } else { 220 xfd.save(); 221 } 222 } catch (ObjectNotFoundException e) { 223 throwInternalError(e); 224 } 225 } 226 227 public void renewLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException { 228 try { 229 XMLResourceDescriptor xfd = getFileDescriptor(uri); 230 xfd.renewLock(lock); 231 if (deferSaving) { 232 xfd.registerForSaving(); 233 } else { 234 xfd.save(); 235 } 236 } catch (ObjectNotFoundException e) { 237 throwInternalError(e); 238 } 239 } 240 241 public void removeLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException { 242 try { 243 XMLResourceDescriptor xfd = getFileDescriptor(uri); 244 xfd.removeLock(lock); 245 if (deferSaving) { 246 xfd.registerForSaving(); 247 } else { 248 xfd.save(); 249 } 250 } catch (ObjectNotFoundException e) { 251 throw new LockTokenNotFoundException(lock); 252 } 253 } 254 255 public void killLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException { 256 removeLock(uri, lock); 257 } 258 259 public Enumeration enumerateLocks(Uri uri) throws ServiceAccessException { 260 try { 261 XMLResourceDescriptor xfd = getFileDescriptor(uri); 262 return xfd.enumerateLocks(); 263 } catch (ObjectNotFoundException e) { 264 throwInternalError(e); 265 return null; } 267 } 268 269 274 275 public NodeRevisionDescriptors retrieveRevisionDescriptors(Uri uri) 276 throws ServiceAccessException, RevisionDescriptorNotFoundException { 277 try { 278 XMLResourceDescriptor xfd = getFileDescriptor(uri); 279 return xfd.retrieveRevisionDescriptors(); 280 } catch (ObjectNotFoundException e) { 281 throw new RevisionDescriptorNotFoundException(uri.toString()); 282 } 283 } 284 285 public void createRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors) 286 throws ServiceAccessException { 287 try { 288 XMLResourceDescriptor xfd = getFileDescriptor(uri); 289 xfd.createRevisionDescriptors(revisionDescriptors); 290 if (deferSaving) { 291 xfd.registerForSaving(); 292 } else { 293 xfd.save(); 294 } 295 } catch (ObjectNotFoundException e) { 296 throwInternalError(e); 297 } 298 } 299 300 public void storeRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors) 301 throws ServiceAccessException, RevisionDescriptorNotFoundException { 302 try { 303 XMLResourceDescriptor xfd = getFileDescriptor(uri); 304 xfd.storeRevisionDescriptors(revisionDescriptors); 305 if (deferSaving) { 306 xfd.registerForSaving(); 307 } else { 308 xfd.save(); 309 } 310 } catch (ObjectNotFoundException e) { 311 throw new RevisionDescriptorNotFoundException(uri.toString()); 312 } 313 } 314 315 public void removeRevisionDescriptors(Uri uri) throws ServiceAccessException { 316 try { 317 XMLResourceDescriptor xfd = getFileDescriptor(uri); 318 xfd.removeRevisionDescriptors(); 319 if (deferSaving) { 320 xfd.registerForSaving(); 321 } else { 322 xfd.save(); 323 } 324 } catch (ObjectNotFoundException e) { 325 throwInternalError(e); 326 } 327 } 328 329 334 335 public NodeRevisionDescriptor retrieveRevisionDescriptor(Uri uri, NodeRevisionNumber revisionNumber) 336 throws ServiceAccessException, RevisionDescriptorNotFoundException { 337 try { 338 XMLResourceDescriptor xfd = getFileDescriptor(uri); 339 return xfd.retrieveRevisionDescriptor(revisionNumber); 340 } catch (ObjectNotFoundException e) { 341 throw new RevisionDescriptorNotFoundException(uri.toString()); 342 } 343 } 344 345 public void createRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor) 346 throws ServiceAccessException { 347 try { 348 XMLResourceDescriptor xfd = getFileDescriptor(uri); 349 xfd.createRevisionDescriptor(revisionDescriptor); 350 if (deferSaving) { 351 xfd.registerForSaving(); 352 } else { 353 xfd.save(); 354 } 355 } catch (ObjectNotFoundException e) { 356 throwInternalError(e); 357 } 358 } 359 360 public void storeRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor) 361 throws ServiceAccessException, RevisionDescriptorNotFoundException { 362 try { 363 XMLResourceDescriptor xfd = getFileDescriptor(uri); 364 xfd.storeRevisionDescriptor(revisionDescriptor); 365 if (deferSaving) { 366 xfd.registerForSaving(); 367 } else { 368 xfd.save(); 369 } 370 } catch (ObjectNotFoundException e) { 371 throw new RevisionDescriptorNotFoundException(uri.toString()); 372 } 373 } 374 375 public void removeRevisionDescriptor(Uri uri, NodeRevisionNumber number) throws ServiceAccessException { 376 try { 377 XMLResourceDescriptor xfd = getFileDescriptor(uri); 378 xfd.removeRevisionDescriptor(number); 379 if (deferSaving) { 380 xfd.registerForSaving(); 381 } else { 382 xfd.save(); 383 } 384 } catch (ObjectNotFoundException e) { 385 throwInternalError(e); 386 } 387 } 388 389 public String toString() { 390 return "TxXMLFileDescriptorsStore at " + storeDir + " working on " + workDir; 391 } 392 393 public synchronized void commit(Xid xid, boolean onePhase) throws XAException { 394 try { 395 super.commit(xid, onePhase); 396 } finally { 397 Object txId = wrap(xid); 398 activeContexts.remove(txId); 399 suspendedContexts.remove(txId); 400 activeTransactionBranch.set(null); 401 } 402 } 403 404 public synchronized void rollback(Xid xid) throws XAException { 405 try { 406 super.rollback(xid); 407 } finally { 408 Object txId = wrap(xid); 409 activeContexts.remove(txId); 410 suspendedContexts.remove(txId); 411 activeTransactionBranch.set(null); 412 } 413 } 414 415 public synchronized int prepare(Xid xid) throws XAException { 416 Object txId = wrap(xid); 417 getLogger().log( 418 "Thread " + Thread.currentThread() + " prepares transaction branch " + txId, 419 LOG_CHANNEL, 420 Logger.DEBUG); 421 try { 422 if (deferSaving) { 423 TxContext txContext = (TxContext) activeContexts.get(txId); 425 if (txContext == null) txContext = (TxContext) suspendedContexts.get(txId); 426 if (txContext != null) { 428 try { 429 txContext.saveDescriptors(); 430 } catch (ObjectNotFoundException onfe) { 431 getLogger().log( 432 "Thread " + Thread.currentThread() + " failed to prepare transaction branch " + txId, 433 onfe, 434 LOG_CHANNEL, 435 Logger.CRITICAL); 436 throw new XAException (onfe.toString()); 437 } catch (ServiceAccessException sae) { 438 getLogger().log( 439 "Thread " + Thread.currentThread() + " failed to prepare transaction branch " + txId, 440 sae, 441 LOG_CHANNEL, 442 Logger.CRITICAL); 443 throw new XAException (sae.toString()); 444 } 445 } else { 446 getLogger().log( 447 "Thread " + Thread.currentThread() + " could prepare *unknown* transaction branch " + txId, 448 LOG_CHANNEL, 449 Logger.WARNING); 450 } 451 } 452 int status = rm.prepareTransaction(txId); 453 switch (status) { 454 case ResourceManager.PREPARE_SUCCESS_READONLY : 455 return XA_RDONLY; 456 case ResourceManager.PREPARE_SUCCESS : 457 return XA_OK; 458 default : 459 throw new XAException (XAException.XA_RBROLLBACK); 460 } 461 } catch (ResourceManagerException e) { 462 getLogger().log( 463 "Thread " + Thread.currentThread() + " failed to prepare transaction branch " + txId, 464 e, 465 LOG_CHANNEL, 466 Logger.CRITICAL); 467 throw createXAException(e); 468 } 469 } 470 471 public synchronized void end(Xid xid, int flags) throws XAException { 472 if (getActiveTxId() == null) { 473 throw new XAException (XAException.XAER_INVAL); 474 } 475 Object txId = wrap(xid); 476 Thread currentThread = Thread.currentThread(); 477 getLogger().log( 478 "Thread " 479 + currentThread 480 + (flags == TMSUSPEND ? " suspends" : flags == TMFAIL ? " fails" : " ends") 481 + " work on behalf of transaction branch " 482 + txId, 483 LOG_CHANNEL, 484 DEBUG_LEVEL); 485 486 switch (flags) { 487 case TMSUSPEND : 488 suspendedContexts.put(txId, getActiveTxContext()); 489 activeContexts.remove(txId); 490 activeTransactionBranch.set(null); 491 break; 492 case TMFAIL : 493 try { 494 rm.markTransactionForRollback(wrap(xid)); 495 } catch (ResourceManagerException e) { 496 throw createXAException(e); 497 } 498 activeTransactionBranch.set(null); 499 break; 500 case TMSUCCESS : 501 activeTransactionBranch.set(null); 502 break; 503 } 504 } 505 506 public synchronized void start(Xid xid, int flags) throws XAException { 507 Object txId = wrap(xid); 508 Thread currentThread = Thread.currentThread(); 509 getLogger().log( 510 "Thread " 511 + currentThread 512 + (flags == TMNOFLAGS ? " starts" : flags == TMJOIN ? " joins" : " resumes") 513 + " work on behalf of transaction branch " 514 + txId, 515 LOG_CHANNEL, 516 DEBUG_LEVEL); 517 518 switch (flags) { 519 case TMNOFLAGS : 521 if (getActiveTxId() != null) { 522 throw new XAException (XAException.XAER_INVAL); 523 } 524 try { 525 rm.startTransaction(txId); 526 TxContext txContext = new TxContext(txId); 527 activeTransactionBranch.set(txContext); 528 activeContexts.put(txId, txContext); 529 } catch (ResourceManagerException e) { 530 throw createXAException(e); 531 } 532 break; 533 case TMJOIN : 534 if (getActiveTxId() != null) { 535 throw new XAException (XAException.XAER_INVAL); 536 } 537 try { 538 if (rm.getTransactionState(txId) == STATUS_NO_TRANSACTION) { 539 throw new XAException (XAException.XAER_INVAL); 540 } 541 } catch (ResourceManagerException e) { 542 throw createXAException(e); 543 } 544 TxContext txContext = new TxContext(txId); 545 activeTransactionBranch.set(txContext); 546 activeContexts.put(txId, txContext); 547 break; 548 case TMRESUME : 549 if (getActiveTxId() != null) { 550 throw new XAException (XAException.XAER_INVAL); 551 } 552 txContext = (TxContext) suspendedContexts.remove(txId); 553 if (txContext == null) { 554 throw new XAException (XAException.XAER_NOTA); 555 } 556 activeTransactionBranch.set(txContext); 557 break; 558 } 559 } 560 561 566 567 570 protected XMLResourceDescriptor getFileDescriptor(Uri uri) throws ServiceAccessException, ObjectNotFoundException { 571 TxContext txContext = getActiveTxContext(); 572 XMLResourceDescriptor xfd; 573 if (txContext != null) { 574 xfd = txContext.lookup(uri); 575 if (xfd == null) { 576 Object txId = txContext.xid; 577 xfd = new XMLResourceDescriptor(uri, this, rm, txId, characterEncoding); 578 xfd.load(); 579 if (txId != null) { 580 txContext.register(uri, xfd); 581 } 582 } 583 } else { 584 xfd = new XMLResourceDescriptor(uri, this, rm, null, characterEncoding); 585 xfd.load(); 586 } 587 if (!xfd.getUri().equals(uri.toString())) { 588 throw new ObjectNotFoundException(uri); 591 } 592 return xfd; 593 } 594 595 protected TxContext getActiveTxContext() { 596 TxContext context = (TxContext)activeTransactionBranch.get(); 597 return context; 598 } 599 600 protected Object getActiveTxId() { 601 TxContext context = (TxContext) activeTransactionBranch.get(); 602 return (context == null ? null : context.xid); 603 } 604 605 protected String getLogChannel() { 606 return LOG_CHANNEL; 607 } 608 609 private static class TxContext { 610 public Object xid; 611 public Map descriptors = new HashMap (); 612 613 public TxContext(Object xid) { 614 this.xid = xid; 615 } 616 617 public void register(Uri uri, XMLResourceDescriptor xfd) { 618 descriptors.put(uri.toString(), xfd); 619 } 620 621 public void deregister(Uri uri) { 622 descriptors.remove(uri.toString()); 623 } 624 625 public XMLResourceDescriptor lookup(Uri uri) { 626 return (XMLResourceDescriptor) descriptors.get(uri.toString()); 627 } 628 629 public Collection list() { 630 return descriptors.values(); 631 } 632 633 public void saveDescriptors() throws ObjectNotFoundException, ServiceAccessException { 634 for (Iterator it = list().iterator(); it.hasNext();) { 635 XMLResourceDescriptor xfd = (XMLResourceDescriptor) it.next(); 636 if (xfd.isRegisteredForSaving()) xfd.save(); 637 } 638 } 639 640 } 641 } 642 | Popular Tags |