1 23 24 package org.apache.slide.store.impl.rdbms; 25 26 import java.lang.reflect.Constructor ; 27 import java.sql.Connection ; 28 import java.sql.SQLException ; 29 import java.util.Enumeration ; 30 import java.util.Hashtable ; 31 32 import javax.transaction.xa.XAException ; 33 import javax.transaction.xa.XAResource ; 34 import javax.transaction.xa.Xid ; 35 36 import org.apache.commons.transaction.util.xa.AbstractTransactionalResource; 37 import org.apache.commons.transaction.util.xa.TransactionalResource; 38 import org.apache.slide.common.AbstractXAServiceBase; 39 import org.apache.slide.common.Service; 40 import org.apache.slide.common.ServiceAccessException; 41 import org.apache.slide.common.ServiceConnectionFailedException; 42 import org.apache.slide.common.ServiceDisconnectionFailedException; 43 import org.apache.slide.common.ServiceInitializationFailedException; 44 import org.apache.slide.common.ServiceParameterErrorException; 45 import org.apache.slide.common.ServiceParameterMissingException; 46 import org.apache.slide.common.ServiceResetFailedException; 47 import org.apache.slide.common.Uri; 48 import org.apache.slide.content.NodeRevisionContent; 49 import org.apache.slide.content.NodeRevisionDescriptor; 50 import org.apache.slide.content.NodeRevisionDescriptors; 51 import org.apache.slide.content.NodeRevisionNumber; 52 import org.apache.slide.content.RevisionAlreadyExistException; 53 import org.apache.slide.content.RevisionDescriptorNotFoundException; 54 import org.apache.slide.content.RevisionNotFoundException; 55 import org.apache.slide.lock.LockTokenNotFoundException; 56 import org.apache.slide.lock.NodeLock; 57 import org.apache.slide.search.basic.BasicExpressionFactory; 58 import org.apache.slide.search.basic.IBasicExpressionFactory; 59 import org.apache.slide.search.basic.IBasicExpressionFactoryProvider; 60 import org.apache.slide.security.NodePermission; 61 import org.apache.slide.store.ContentStore; 62 import org.apache.slide.store.LockStore; 63 import org.apache.slide.store.NodeStore; 64 import org.apache.slide.store.RevisionDescriptorStore; 65 import org.apache.slide.store.RevisionDescriptorsStore; 66 import org.apache.slide.store.SecurityStore; 67 import org.apache.slide.store.SequenceStore; 68 import org.apache.slide.store.impl.rdbms.expression.RDBMSExpressionFactory; 69 import org.apache.slide.structure.ObjectAlreadyExistsException; 70 import org.apache.slide.structure.ObjectNode; 71 import org.apache.slide.structure.ObjectNotFoundException; 72 import org.apache.slide.util.logger.Logger; 73 74 80 public abstract class AbstractRDBMSStore 81 extends AbstractXAServiceBase 82 implements 83 LockStore, 84 NodeStore, 85 RevisionDescriptorsStore, 86 RevisionDescriptorStore, 87 SecurityStore, 88 ContentStore, 89 SequenceStore, 90 IBasicExpressionFactoryProvider { 91 92 protected static final String LOG_CHANNEL = AbstractRDBMSStore.class.getName(); 93 94 protected RDBMSAdapter adapter; 95 96 protected boolean alreadyInitialized = false; 97 98 protected int isSequenceSupported = 0; 99 100 protected boolean useRdbmsExpressionFactory; 101 102 107 protected boolean tmCommits = false; 108 109 117 public void setParameters(Hashtable parameters) 118 throws ServiceParameterErrorException, ServiceParameterMissingException { 119 120 String value = (String ) parameters.get("adapter"); 122 if (value == null) { 123 adapter = new StandardRDBMSAdapter(this, getLogger()); 124 } else { 125 try { 126 Class adapterClass = Class.forName(value); 127 Constructor ctor = adapterClass.getConstructor(new Class [] { Service.class, Logger.class }); 128 adapter = (RDBMSAdapter) ctor.newInstance(new Object [] { this, getLogger()}); 129 } catch (Exception e) { 130 getLogger().log( 132 "Error instantiating Adapter '" + value + "' (" + e.getMessage() + ")", 133 LOG_CHANNEL, 134 Logger.ERROR); 135 } 136 } 137 138 if (adapter != null) { 139 adapter.setParameters(parameters); 140 } 141 142 value = (String ) parameters.get("use-rdbms-expression-factory"); 144 this.useRdbmsExpressionFactory = Boolean.valueOf(value).booleanValue(); 145 146 try { 148 initialize(null); 149 } catch (ServiceInitializationFailedException e) { 150 throw new ServiceParameterErrorException(this, e.getMessage()); 152 } 153 } 154 155 160 public void connect() throws ServiceConnectionFailedException { 161 } 162 163 166 public boolean isConnected() { 167 return true; 168 } 169 170 176 public void disconnect() throws ServiceDisconnectionFailedException { 177 } 178 179 184 public void reset() throws ServiceResetFailedException { 185 186 } 187 188 189 191 196 public int getTransactionTimeout() throws XAException { 197 return 0; 198 } 199 200 203 public boolean setTransactionTimeout(int timeout) throws XAException { 204 return false; 205 } 206 207 public Xid [] recover(int flag) throws XAException { 208 209 getLogger().log("recover() for thread: " + Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG); 210 TransactionalResource id = getCurrentlyActiveTransactionalResource(); 211 212 if (id != null && id.getStatus() == STATUS_PREPARED) { 213 Xid [] xids = new Xid [1]; 214 xids[0] = id.getXid(); 215 return xids; 216 } else 217 return new Xid [0]; 218 } 219 220 public boolean isSameRM(XAResource xares) throws XAException { 221 return (xares == this); 222 } 223 224 226 public IBasicExpressionFactory getBasicExpressionFactory() { 227 if (this.useRdbmsExpressionFactory) { 228 return new RDBMSExpressionFactory(this); 229 } 230 else { 231 return new BasicExpressionFactory(); 232 } 233 } 234 235 237 240 public boolean createSequence(String sequenceName) throws ServiceAccessException { 241 if (!isSequenceSupported()) { 242 throw new ServiceAccessException(this, "Sequences not supported"); 243 } 244 Connection connection = null; 245 try { 246 connection = getNewConnection(); 247 return ((SequenceAdapter) adapter).createSequence(connection, sequenceName); 248 } catch (SQLException e) { 249 throw new ServiceAccessException(this, e); 250 } finally { 251 if (connection != null) { 252 try { 253 if (!tmCommits) { 254 connection.commit(); 255 } 256 } catch (SQLException e) { 257 throw new ServiceAccessException(this, e); 258 } finally { 259 try { 260 connection.close(); 261 } catch (SQLException e) { 262 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 263 } 264 } 265 } 266 } 267 } 268 269 272 public boolean isSequenceSupported() { 273 if (isSequenceSupported > 0) 276 return true; 277 if (isSequenceSupported < 0) 278 return false; 279 Connection connection = null; 280 try { 281 connection = getNewConnection(); 282 if (adapter instanceof SequenceAdapter && ((SequenceAdapter) adapter).isSequenceSupported(connection)) { 283 isSequenceSupported = 1; 284 return true; 285 } else { 286 isSequenceSupported = -1; 287 return false; 288 } 289 } catch (SQLException e) { 290 getLogger().log( 291 "Error while trying to check for sequence support. Assuming false", 292 e, 293 LOG_CHANNEL, 294 Logger.ERROR); 295 isSequenceSupported = -1; 296 return false; 297 } finally { 298 if (connection != null) { 299 try { 300 if (!tmCommits) { 301 connection.commit(); 302 } 303 } catch (SQLException e) { 304 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 305 } finally { 306 try { 307 connection.close(); 308 } catch (SQLException e) { 309 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 310 } 311 } 312 } 313 } 314 } 315 316 319 public long nextSequenceValue(String sequenceName) throws ServiceAccessException { 320 if (!isSequenceSupported()) { 321 throw new ServiceAccessException(this, "Sequences not supported"); 322 } 323 Connection connection = null; 324 try { 325 connection = getNewConnection(); 326 return ((SequenceAdapter) adapter).nextSequenceValue(connection, sequenceName); 327 } catch (SQLException e) { 328 throw new ServiceAccessException(this, e); 329 } finally { 330 if (connection != null) { 331 try { 332 if (!tmCommits) { 333 connection.commit(); 334 } 335 } catch (SQLException e) { 336 throw new ServiceAccessException(this, e); 337 } finally { 338 try { 339 connection.close(); 340 } catch (SQLException e) { 341 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 342 } 343 } 344 } 345 } 346 } 347 348 351 public boolean sequenceExists(String sequenceName) throws ServiceAccessException { 352 if (!isSequenceSupported()) { 353 throw new ServiceAccessException(this, "Sequences not supported"); 354 } 355 Connection connection = null; 356 try { 357 connection = getNewConnection(); 358 return ((SequenceAdapter) adapter).sequenceExists(connection, sequenceName); 359 } catch (SQLException e) { 360 throw new ServiceAccessException(this, e); 361 } finally { 362 if (connection != null) { 363 try { 364 if (!tmCommits) { 365 connection.commit(); 366 } 367 } catch (SQLException e) { 368 throw new ServiceAccessException(this, e); 369 } finally { 370 try { 371 connection.close(); 372 } catch (SQLException e) { 373 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 374 } 375 } 376 } 377 } 378 } 379 380 382 389 public ObjectNode retrieveObject(Uri uri) throws ServiceAccessException, ObjectNotFoundException { 390 391 if (getCurrentlyActiveTransactionalResource() == null) { 392 Connection connection = null; 393 try { 394 connection = getNewConnection(); 395 return adapter.retrieveObject(connection, uri); 396 } catch (SQLException e) { 397 throw new ServiceAccessException(this, e); 398 } finally { 399 if (connection != null) { 400 try { 401 if (!tmCommits) { 402 connection.commit(); 403 } 404 } catch (SQLException e) { 405 throw new ServiceAccessException(this, e); 406 } finally { 407 try { 408 connection.close(); 409 } catch (SQLException e) { 410 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 411 } 412 } 413 } 414 } 415 } else { 416 return adapter.retrieveObject(getCurrentConnection(), uri); 417 } 418 } 419 420 427 public void storeObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectNotFoundException { 428 429 adapter.storeObject(getCurrentConnection(), uri, object); 430 } 431 432 441 public void createObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectAlreadyExistsException { 442 443 adapter.createObject(getCurrentConnection(), uri, object); 444 } 445 446 453 public void removeObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectNotFoundException { 454 455 adapter.removeObject(getCurrentConnection(), uri, object); 456 } 457 458 460 466 public void grantPermission(Uri uri, NodePermission permission) throws ServiceAccessException { 467 468 adapter.grantPermission(getCurrentConnection(), uri, permission); 469 } 470 471 477 public void revokePermission(Uri uri, NodePermission permission) throws ServiceAccessException { 478 479 adapter.revokePermission(getCurrentConnection(), uri, permission); 480 } 481 482 488 public void revokePermissions(Uri uri) throws ServiceAccessException { 489 490 adapter.revokePermissions(getCurrentConnection(), uri); 491 } 492 493 499 public Enumeration enumeratePermissions(Uri uri) throws ServiceAccessException { 500 if (getCurrentlyActiveTransactionalResource() == null) { 501 Connection connection = null; 502 try { 503 connection = getNewConnection(); 504 return adapter.enumeratePermissions(connection, uri); 505 } catch (SQLException e) { 506 throw new ServiceAccessException(this, e); 507 } finally { 508 if (connection != null) { 509 try { 510 if (!tmCommits) { 511 connection.commit(); 512 } 513 } catch (SQLException e) { 514 throw new ServiceAccessException(this, e); 515 } finally { 516 try { 517 connection.close(); 518 } catch (SQLException e) { 519 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 520 } 521 } 522 } 523 } 524 } else { 525 return adapter.enumeratePermissions(getCurrentConnection(), uri); 526 } 527 } 528 529 531 537 public void putLock(Uri uri, NodeLock lock) throws ServiceAccessException { 538 539 adapter.putLock(getCurrentConnection(), uri, lock); 540 } 541 542 549 public void renewLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException { 550 551 adapter.renewLock(getCurrentConnection(), uri, lock); 552 } 553 554 561 public void removeLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException { 562 563 adapter.removeLock(getCurrentConnection(), uri, lock); 564 } 565 566 573 public void killLock(Uri uri, NodeLock lock) throws ServiceAccessException, LockTokenNotFoundException { 574 575 adapter.killLock(getCurrentConnection(), uri, lock); 576 } 577 578 585 public Enumeration enumerateLocks(Uri uri) throws ServiceAccessException { 586 if (getCurrentlyActiveTransactionalResource() == null) { 587 Connection connection = null; 588 try { 589 connection = getNewConnection(); 590 return adapter.enumerateLocks(connection, uri); 591 } catch (SQLException e) { 592 throw new ServiceAccessException(this, e); 593 } finally { 594 if (connection != null) { 595 try { 596 if (!tmCommits) { 597 connection.commit(); 598 } 599 } catch (SQLException e) { 600 throw new ServiceAccessException(this, e); 601 } finally { 602 try { 603 connection.close(); 604 } catch (SQLException e) { 605 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 606 } 607 } 608 } 609 } 610 } else { 611 return adapter.enumerateLocks(getCurrentConnection(), uri); 612 } 613 } 614 615 617 625 public NodeRevisionDescriptors retrieveRevisionDescriptors(Uri uri) 626 throws ServiceAccessException, RevisionDescriptorNotFoundException { 627 if (getCurrentlyActiveTransactionalResource() == null) { 628 Connection connection = null; 629 try { 630 connection = getNewConnection(); 631 return adapter.retrieveRevisionDescriptors(connection, uri); 632 } catch (SQLException e) { 633 throw new ServiceAccessException(this, e); 634 } finally { 635 if (connection != null) { 636 try { 637 if (!tmCommits) { 638 connection.commit(); 639 } 640 } catch (SQLException e) { 641 throw new ServiceAccessException(this, e); 642 } finally { 643 try { 644 connection.close(); 645 } catch (SQLException e) { 646 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 647 } 648 } 649 } 650 } 651 } else { 652 return adapter.retrieveRevisionDescriptors(getCurrentConnection(), uri); 653 } 654 } 655 656 663 public void createRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors) 664 throws ServiceAccessException { 665 666 adapter.createRevisionDescriptors(getCurrentConnection(), uri, revisionDescriptors); 667 } 668 669 678 public void storeRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors) 679 throws ServiceAccessException, RevisionDescriptorNotFoundException { 680 681 adapter.storeRevisionDescriptors(getCurrentConnection(), uri, revisionDescriptors); 682 } 683 684 690 public void removeRevisionDescriptors(Uri uri) throws ServiceAccessException { 691 692 adapter.removeRevisionDescriptors(getCurrentConnection(), uri); 693 } 694 695 697 703 public NodeRevisionDescriptor retrieveRevisionDescriptor(Uri uri, NodeRevisionNumber revisionNumber) 704 throws ServiceAccessException, RevisionDescriptorNotFoundException { 705 if (getCurrentlyActiveTransactionalResource() == null) { 706 Connection connection = null; 707 try { 708 connection = getNewConnection(); 709 return adapter.retrieveRevisionDescriptor(connection, uri, revisionNumber); 710 } catch (SQLException e) { 711 throw new ServiceAccessException(this, e); 712 } finally { 713 if (connection != null) { 714 try { 715 if (!tmCommits) { 716 connection.commit(); 717 } 718 } catch (SQLException e) { 719 throw new ServiceAccessException(this, e); 720 } finally { 721 try { 722 connection.close(); 723 } catch (SQLException e) { 724 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 725 } 726 } 727 } 728 } 729 } else { 730 return adapter.retrieveRevisionDescriptor(getCurrentConnection(), uri, revisionNumber); 731 } 732 } 733 734 741 public void createRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor) 742 throws ServiceAccessException { 743 744 adapter.createRevisionDescriptor(getCurrentConnection(), uri, revisionDescriptor); 745 } 746 747 756 public void storeRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor) 757 throws ServiceAccessException, RevisionDescriptorNotFoundException { 758 759 adapter.storeRevisionDescriptor(getCurrentConnection(), uri, revisionDescriptor); 760 } 761 762 769 public void removeRevisionDescriptor(Uri uri, NodeRevisionNumber revisionNumber) throws ServiceAccessException { 770 771 adapter.removeRevisionDescriptor(getCurrentConnection(), uri, revisionNumber); 772 } 773 774 776 782 public NodeRevisionContent retrieveRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor) 783 throws ServiceAccessException, RevisionNotFoundException { 784 if (getCurrentlyActiveTransactionalResource() == null) { 785 Connection connection = null; 786 try { 787 connection = getNewConnection(); 788 return adapter.retrieveRevisionContent(connection, uri, revisionDescriptor, true); 789 } catch (SQLException e) { 790 if (connection != null) { 793 try { 794 if (!tmCommits) { 795 connection.rollback(); 796 } 797 } catch (SQLException e2) { 798 throw new ServiceAccessException(this, e2); 799 } finally { 800 try { 801 connection.close(); 802 } catch (SQLException e2) { 803 getLogger().log(e2, LOG_CHANNEL, Logger.WARNING); 804 } 805 } 806 } 807 throw new ServiceAccessException(this, e); 808 } 809 } else { 810 return adapter.retrieveRevisionContent(getCurrentConnection(), uri, revisionDescriptor, false); 811 } 812 } 813 814 821 public void createRevisionContent( 822 Uri uri, 823 NodeRevisionDescriptor revisionDescriptor, 824 NodeRevisionContent revisionContent) 825 throws ServiceAccessException, RevisionAlreadyExistException { 826 827 adapter.createRevisionContent(getCurrentConnection(), uri, revisionDescriptor, revisionContent); 828 } 829 830 837 public void storeRevisionContent( 838 Uri uri, 839 NodeRevisionDescriptor revisionDescriptor, 840 NodeRevisionContent revisionContent) 841 throws ServiceAccessException, RevisionNotFoundException { 842 843 adapter.storeRevisionContent(getCurrentConnection(), uri, revisionDescriptor, revisionContent); 844 } 845 846 852 public void removeRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor) 853 throws ServiceAccessException { 854 855 adapter.removeRevisionContent(getCurrentConnection(), uri, revisionDescriptor); 856 } 857 858 860 protected TransactionalResource getCurrentlyActiveTransactionalResource() { 862 return super.getCurrentlyActiveTransactionalResource(); 863 } 864 865 868 protected Connection getCurrentConnection() throws ServiceAccessException { 869 870 getLogger().log("Getting current connection for thread " + Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG); 871 TransactionId id = (TransactionId) getCurrentlyActiveTransactionalResource(); 872 if (id == null) { 873 getLogger().log("No id for current thread - called outside transaction?", LOG_CHANNEL, Logger.DEBUG); 874 return null; 875 } 876 return id.connection; 877 } 878 879 abstract protected Connection getNewConnection() throws SQLException ; 880 881 protected TransactionalResource createTransactionResource(Xid xid) throws SQLException { 882 return new TransactionId(xid); 883 } 884 885 private class TransactionId extends AbstractTransactionalResource { 886 Xid xid; 887 int status; 888 Connection connection; 889 890 TransactionId(Xid xid) throws SQLException { 891 super(xid); 892 893 status = STATUS_ACTIVE; 894 connection = getNewConnection(); 895 } 896 897 public void commit() throws XAException { 898 try { 899 if (!tmCommits) { 900 connection.commit(); 901 } 902 } catch (SQLException e) { 903 throw new XAException (XAException.XA_RBCOMMFAIL); 904 } finally { 905 try { 906 connection.close(); 907 } catch (SQLException e) { 908 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 909 } 910 } 911 } 912 913 public void rollback() throws XAException { 914 try { 915 if (!tmCommits) { 916 connection.rollback(); 917 } 918 } catch (SQLException e) { 919 throw new XAException (XAException.XA_RBCOMMFAIL); 920 } finally { 921 try { 922 connection.close(); 923 } catch (SQLException e) { 924 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 925 } 926 } 927 } 928 929 public int prepare() throws XAException { 930 return XA_OK; 932 } 933 934 public void begin() throws XAException { 935 } 936 937 public void suspend() throws XAException { 938 } 939 940 public void resume() throws XAException { 941 } 942 943 } 944 945 } 946 | Popular Tags |