001: package org.obe.server.j2ee.repository;
002:
003: import org.apache.commons.logging.Log;
004: import org.apache.commons.logging.LogFactory;
005: import org.obe.OBERuntimeException;
006: import org.obe.server.j2ee.TxHelperLocal;
007:
008: import javax.ejb.CreateException;
009: import javax.ejb.NoSuchObjectLocalException;
010: import java.util.Collections;
011: import java.util.HashMap;
012: import java.util.Map;
013:
014: /**
015: * A utility class to help in maintaining information relative to a transaction.
016: */
017: public class TransactionUtil {
018: private static final Log _logger = LogFactory
019: .getLog(TransactionUtil.class);
020: private static final Map _txHelperBeans = Collections
021: .synchronizedMap(new HashMap());
022:
023: // Inhibit construction.
024: private TransactionUtil() {
025: }
026:
027: /**
028: * Checks whether the current transaction has been marked read/write for a
029: * given entity tag.
030: *
031: * @param entityTag A string tag identifying a type of entity (or entities).
032: * @return <code>true</code> if the current transaction has been marked
033: * as read/write with the given entityTag.
034: * @see #markReadWrite(String)
035: */
036: public static boolean isReadWrite(String entityTag) {
037: TxHelperLocal txHelper = getTxHelper(false);
038: return txHelper != null && txHelper.isReadWrite(entityTag);
039: }
040:
041: /**
042: * Marks the current transaction as read/write for a given entity tag.
043: *
044: * @param entityTag A string tag identifying a type of entity (or entities).
045: * @see #isReadWrite
046: */
047: public static void markReadWrite(String entityTag) {
048: getTxHelper(true).markReadWrite(entityTag);
049: }
050:
051: /**
052: * Notification that a TxHelperEJB has been removed. Bean removal would
053: * typically be performed by the EJB container as the result of the bean
054: * timing out. <em>This is an internal method and should not be called.</em>
055: *
056: * @param threadId The unique thread ID passed to the bean when it was first
057: * created.
058: */
059: public static void cleanup(String threadId) {
060: _txHelperBeans.remove(threadId);
061: }
062:
063: /**
064: * Gets the transaction helper bean for the current thread
065: * (and transaction).
066: *
067: * @param create
068: * @return the local thread transaction information.
069: */
070: private static TxHelperLocal getTxHelper(boolean create) {
071: // Compute a unique identifier for this thread. The JavaDoc for
072: // j.l.Thread doesn't specify that name must be unique (or even that it
073: // must be set or have a non-null default value), so we append the
074: // thread's identity hash code in the expectation that the resulting
075: // string will be unique. According to the j.l.Object.hashCode()
076: // JavaDoc, identity hashcodes are unique but are not actually required
077: // by JLS to be so.
078: Thread t = Thread.currentThread();
079: String threadId = t.getName() + ':'
080: + System.identityHashCode(t);
081:
082: TxHelperLocal helper = (TxHelperLocal) _txHelperBeans
083: .get(threadId);
084: if (helper != null) {
085: try {
086: helper.ping();
087: } catch (NoSuchObjectLocalException e) {
088: // This exception means that the bean has timed out and been
089: // removed by the container. Unfortunately, the EJB spec. is
090: // unclear as to whether calling ping() (txn NotSupported) on
091: // a non-existent bean will cause the current transaction to be
092: // marked rollback only.
093: _logger
094: .debug("TxHelperEJB appears to have timed out and been removed without informing us - recreating.");
095: helper = null;
096: } catch (Exception e) {
097: if (_logger.isDebugEnabled())
098: _logger.error(
099: "Unexpected exception from TxHelperEJB", e);
100: else {
101: _logger
102: .warn("Unexpected exception from TxHelperEJB: "
103: + e.getClass().getName()
104: + ": "
105: + e.getMessage());
106: }
107: helper = null;
108: }
109: if (helper == null)
110: _txHelperBeans.remove(threadId);
111: }
112: if (helper == null && create) {
113: try {
114: helper = EJBLocalHelper.getTxHelperHome().create(
115: threadId);
116: } catch (CreateException e) {
117: throw new OBERuntimeException(e);
118: }
119: _txHelperBeans.put(threadId, helper);
120: }
121: return helper;
122: }
123: }
|