001: // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002: // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003: // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005: // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008: // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009: // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010: // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011: // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012: // POSSIBILITY OF SUCH DAMAGE.
013: //
014: // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
015: package com.metaboss.enterprise.spi.inprocessimpl;
016:
017: import javax.naming.Context;
018: import javax.naming.NamingException;
019: import javax.transaction.Status;
020: import javax.transaction.SystemException;
021: import javax.transaction.Transaction;
022: import javax.transaction.TransactionManager;
023: import javax.transaction.UserTransaction;
024:
025: import tyrex.tm.RuntimeContext;
026:
027: import com.metaboss.enterprise.spi.JTAImplementationProvider;
028: import com.metaboss.enterprise.transaction.ExtendedTransactionStatus;
029:
030: /** Interface to the JDBC connection provider */
031: public class JTAImplementationProviderImpl implements
032: JTAImplementationProvider {
033: /** Method used to obtain JTA's user transaction */
034: public UserTransaction getUserTransaction() throws SystemException {
035: return TyrexUtil.getTransactionDomain().getUserTransaction();
036: }
037:
038: /** Method used to obtain JTA's transaction manager */
039: public TransactionManager getTransactionManager()
040: throws SystemException {
041: return TyrexUtil.getTransactionDomain().getTransactionManager();
042: }
043:
044: // The url where extended status will be stored
045: private static final String sExtendedTransactionStatusContextURL = "MetaBossExtendedTransactionStatus";
046:
047: private static class ExtendedTransactionStatusStorage {
048: public Transaction mTransaction = null;
049: public Throwable mRollbackCause = null;
050: }
051:
052: // This implementation of the extended transaction status is a singleton, which
053: // works out everything at the time it is called taking into consideration current transaction and current thread
054: private static ExtendedTransactionStatus sExtendedTransactionStatus = new ExtendedTransactionStatus() {
055: // Saves rollback cause. Can only be called once after transaction status is already set to rollback only. */
056: public void setRollbackCause(Throwable pCause)
057: throws javax.transaction.SystemException,
058: javax.transaction.NotSupportedException,
059: java.lang.IllegalStateException {
060: try {
061: // First make sure that we have a transaction and it is in the rolled back state
062: Transaction lTransaction = TyrexUtil
063: .getTransactionDomain().getTransactionManager()
064: .getTransaction();
065: if (lTransaction.getStatus() != Status.STATUS_MARKED_ROLLBACK)
066: throw new IllegalStateException(
067: "Transaction is not marked for rollback. RollbackCause can not be set.");
068: RuntimeContext lRuntimeContext = RuntimeContext
069: .getRuntimeContext();
070: Context lEnvContext = lRuntimeContext.getEnvContext();
071: ExtendedTransactionStatusStorage lStorage = null;
072: try {
073: lStorage = (ExtendedTransactionStatusStorage) lEnvContext
074: .lookup(sExtendedTransactionStatusContextURL);
075: if (lStorage != null) {
076: // Check transaction - clean up if not the same
077: if (lStorage.mTransaction.equals(lTransaction))
078: throw new IllegalStateException(
079: "It appears that Rollback Cause has already been set for the current transaction.");
080: // Different transaction - has to be the old one - clean it up
081: lEnvContext
082: .unbind(sExtendedTransactionStatusContextURL);
083: }
084: } catch (NamingException e) {
085: // Ignore - this means that there is no storage, which is to be expected
086: }
087: // We are ready to store rollback cause
088: lStorage = new ExtendedTransactionStatusStorage();
089: lStorage.mTransaction = lTransaction;
090: lStorage.mRollbackCause = pCause;
091: lEnvContext.bind(sExtendedTransactionStatusContextURL,
092: lStorage);
093: } catch (NamingException e) {
094: throw new SystemException("Caught unexpected exception"
095: + e.toString());
096: }
097: }
098:
099: // Retrieves rollback cause. Can be called at any time, but may return null meaning that
100: // cause has not been stored (eg. no one has actually stored the cause)
101: public Throwable getRollbackCause()
102: throws javax.transaction.SystemException,
103: javax.transaction.NotSupportedException,
104: java.lang.IllegalStateException {
105: try {
106: // First make sure that we have a transaction and it is in the rolled back state
107: Transaction lTransaction = TyrexUtil
108: .getTransactionDomain().getTransactionManager()
109: .getTransaction();
110: int lTransactionStatus = lTransaction.getStatus();
111: if (lTransactionStatus != Status.STATUS_MARKED_ROLLBACK
112: && lTransactionStatus != Status.STATUS_ROLLEDBACK
113: && lTransactionStatus != Status.STATUS_ROLLING_BACK)
114: throw new IllegalStateException(
115: "Transaction is not marked for rollback or rolledback. RollbackCause can not be obtained.");
116: RuntimeContext lRuntimeContext = RuntimeContext
117: .getRuntimeContext();
118: Context lEnvContext = lRuntimeContext.getEnvContext();
119: ExtendedTransactionStatusStorage lStorage = (ExtendedTransactionStatusStorage) lEnvContext
120: .lookup(sExtendedTransactionStatusContextURL);
121: if (lStorage != null) {
122: // Check transaction - clean up if not the same
123: if (lStorage.mTransaction.equals(lTransaction))
124: return lStorage.mRollbackCause;
125: // Different transaction - has to be the old one - clean it up
126: lEnvContext
127: .unbind(sExtendedTransactionStatusContextURL);
128: }
129: return null; // Cause has not been found
130: } catch (NamingException e) {
131: return null; // Cause has not been found
132: }
133: }
134: };
135:
136: /** Returns ExtendedTransactionStatus associated with current transaction */
137: public ExtendedTransactionStatus getExtendedTransactionStatus()
138: throws SystemException {
139: // This implementation returns exact same object every time
140: // When this object is called it will set / retrieeve transaction status
141: // based on current transaction
142: return sExtendedTransactionStatus;
143: }
144: }
|