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.oldboss.framework.bo.impl;
016:
017: import java.util.ArrayList;
018: import java.util.Enumeration;
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.Map;
023: import java.util.Vector;
024:
025: import com.metaboss.enterprise.bo.BOException;
026: import com.metaboss.enterprise.bo.BOIllegalArgumentException;
027: import com.metaboss.enterprise.bo.BOObjectAlreadyInTransactionException;
028: import com.oldboss.framework.bo.BOTransaction;
029: import com.oldboss.framework.bo.BOTransactionIsNotActiveException;
030:
031: /* Base class for all BO Objects */
032: public class BOTransactionImpl implements BOTransaction {
033: public interface TransactionObject {
034: /* Must return unique object id. No objects with duplicate ids are allowed in one transaction */
035: public String getObjectId() throws BOException;
036:
037: /* Will add this object to transaction */
038: public void joinTransaction(BOTransactionImpl pTransaction)
039: throws BOException;
040:
041: /* Will remove this object from transaction */
042: public void disjoinTransaction(BOTransactionImpl pTransaction)
043: throws BOException;
044:
045: /* Called to actually do commit */
046: public void doCommit() throws BOException;
047:
048: /* Called after successfull commit */
049: public void onCommitSucceeded() throws BOException;
050:
051: /* Called to actually do rollback */
052: public void doRollback() throws BOException;
053: }
054:
055: private static Vector c_ActiveTransactions; /* Static list of the transaction objects */
056: private boolean m_isActive;
057: private Map mTransactionObjectsMap; /* Instance list of the associated transaction objects. Keys are object ids */
058: private List mTransactionObjectsList; /* Instance list of the associated transaction objects. In order of registration */
059:
060: /* Class Constructor */
061: static {
062: c_ActiveTransactions = new Vector(1);
063: }
064:
065: /* Returns an instance of the BOTransaction which has given interface */
066: public static BOTransactionImpl getBOTransaction( BOTransaction p_TransactionInterface ) throws BOException
067: {
068: if ( p_TransactionInterface == null )
069: {
070: throw new java.lang.IllegalArgumentException();
071: }
072: Enumeration enum = c_ActiveTransactions.elements();
073: while(enum.hasMoreElements())
074: {
075: BOTransactionImpl tranx = (BOTransactionImpl)enum.nextElement();
076: if ( ((BOTransaction)tranx) == p_TransactionInterface)
077: {
078: return tranx;
079: }
080: }
081: /* Unexpected situation - someone has an interface but there is no active transaction */
082: throw new BOTransactionIsNotActiveException();
083: }
084:
085: /* Constructor */
086: protected BOTransactionImpl() {
087: mTransactionObjectsMap = new HashMap();
088: mTransactionObjectsList = new ArrayList();
089: m_isActive = true;
090: /* Register this transaction as active one */
091: c_ActiveTransactions.addElement(this );
092: }
093:
094: /* This method adds object to the transaction */
095: protected void addTransactionObject(TransactionObject pObject)
096: throws BOException {
097: checkActive();
098: if (pObject == null)
099: throw new BOIllegalArgumentException(
100: "Object must not be null");
101: if (mTransactionObjectsMap.put(pObject.getObjectId(), pObject) != null)
102: throw new BOObjectAlreadyInTransactionException();
103: mTransactionObjectsList.add(pObject);
104: pObject.joinTransaction(this );
105: }
106:
107: /* This method removes Transaction from the transaction */
108: protected void removeTransactionObject(TransactionObject pObject)
109: throws BOException {
110: checkActive();
111: if (pObject == null)
112: throw new BOIllegalArgumentException(
113: "Object must not be null");
114: if (mTransactionObjectsMap.remove(pObject.getObjectId()) != null) {
115: mTransactionObjectsList.remove(pObject);
116: pObject.disjoinTransaction(this );
117: }
118: }
119:
120: /* This method commits all the changes to all BOs associated with this transaction */
121: public void doCommit() throws BOException {
122: checkActive();
123: /* Iterate through associated objects and call commit action on all of them */
124: {
125: Iterator lIter = mTransactionObjectsList.iterator();
126: while (lIter.hasNext()) {
127: ((TransactionObject) lIter.next()).doCommit();
128: }
129: }
130: /* Iterate through associated objects and call commit succeeded action */
131: {
132: Iterator lIter = mTransactionObjectsList.iterator();
133: while (lIter.hasNext()) {
134: ((TransactionObject) lIter.next()).onCommitSucceeded();
135: }
136: }
137: /* Iterate through associated objects and call disjoin */
138: {
139: Iterator lIter = mTransactionObjectsList.iterator();
140: while (lIter.hasNext()) {
141: ((TransactionObject) lIter.next())
142: .disjoinTransaction(this );
143: }
144: }
145: mTransactionObjectsMap.clear();
146: mTransactionObjectsList.clear();
147: /* Unregister this transaction as active one */
148: c_ActiveTransactions.removeElement(this );
149: m_isActive = false;
150: }
151:
152: /* This method rollsback all the changes to all BOs associated with this transaction */
153: public void doRollback() throws BOException {
154: checkActive();
155:
156: try {
157: {
158: Iterator lIter = mTransactionObjectsList.iterator();
159: while (lIter.hasNext()) {
160: ((TransactionObject) lIter.next()).doRollback();
161: }
162: }
163: } finally {
164: /* Iterate through associated objects and call disjoin */
165: {
166: Iterator lIter = mTransactionObjectsList.iterator();
167: while (lIter.hasNext()) {
168: ((TransactionObject) lIter.next())
169: .disjoinTransaction(this );
170: }
171: }
172: mTransactionObjectsMap.clear();
173: mTransactionObjectsList.clear();
174: /* Unregister this transaction as active one */
175: c_ActiveTransactions.removeElement(this );
176: m_isActive = false;
177: }
178: }
179:
180: /* This method retruns true if transaction is active, that is it has not been committed or rolled back yet */
181: public boolean isActive() {
182: return m_isActive;
183: }
184:
185: /* Checks if transaction object is active and can be used */
186: private void checkActive() throws BOException {
187: if (m_isActive == false) {
188: throw new BOTransactionIsNotActiveException();
189: }
190: }
191: }
|