001: //$Id: WebSphereExtendedJTATransactionLookup.java 11497 2007-05-09 14:55:01Z steve.ebersole@jboss.com $
002: package org.hibernate.transaction;
003:
004: import java.lang.reflect.InvocationHandler;
005: import java.lang.reflect.Method;
006: import java.lang.reflect.Proxy;
007: import java.util.Properties;
008:
009: import javax.naming.NamingException;
010: import javax.transaction.NotSupportedException;
011: import javax.transaction.RollbackException;
012: import javax.transaction.Status;
013: import javax.transaction.Synchronization;
014: import javax.transaction.SystemException;
015: import javax.transaction.Transaction;
016: import javax.transaction.TransactionManager;
017: import javax.transaction.xa.XAResource;
018:
019: import org.hibernate.HibernateException;
020: import org.hibernate.util.NamingHelper;
021:
022: /**
023: * TransactionManagerLookup implementation intended for use with WebSphere
024: * Application Server (WAS).
025: * <p/>
026: * WAS, unlike every other app server on the planet, does not allow direct
027: * access to the JTS TransactionManager. Instead, for common transaction-
028: * related tasks users must utilize a proprietary API known as
029: * ExtendedJTATransaction.
030: * <p/>
031: * Even more unfortunate, the exact TransactionManagerLookup to use inside of
032: * WAS is highly dependent upon (1) WAS version as well as (2) the WAS
033: * container in which Hibernate will be utilized.
034: * <p/>
035: * WebSphereExtendedJTATransactionLookup is reported to work on WAS version 6
036: * in any of the standard J2EE/JEE component containers.
037: *
038: * @author Gavin King
039: * @author <a href="mailto:jesper@udby.com>Jesper Udby</a>
040: */
041: public class WebSphereExtendedJTATransactionLookup implements
042: TransactionManagerLookup {
043:
044: public TransactionManager getTransactionManager(Properties props) {
045: return new TransactionManagerAdapter(props);
046: }
047:
048: public String getUserTransactionName() {
049: return "java:comp/UserTransaction";
050: }
051:
052: public static class TransactionManagerAdapter implements
053: TransactionManager {
054: private final Properties properties;
055: private final Class synchronizationCallbackClass;
056: private final Method registerSynchronizationMethod;
057: private final Method getLocalIdMethod;
058: private Object extendedJTATransaction;
059:
060: private TransactionManagerAdapter(Properties props)
061: throws HibernateException {
062: this .properties = props;
063: try {
064: synchronizationCallbackClass = Class
065: .forName("com.ibm.websphere.jtaextensions.SynchronizationCallback");
066: Class extendedJTATransactionClass = Class
067: .forName("com.ibm.websphere.jtaextensions.ExtendedJTATransaction");
068: registerSynchronizationMethod = extendedJTATransactionClass
069: .getMethod(
070: "registerSynchronizationCallbackForCurrentTran",
071: new Class[] { synchronizationCallbackClass });
072: getLocalIdMethod = extendedJTATransactionClass
073: .getMethod("getLocalId", null);
074:
075: } catch (ClassNotFoundException cnfe) {
076: throw new HibernateException(cnfe);
077: } catch (NoSuchMethodException nsme) {
078: throw new HibernateException(nsme);
079: }
080: }
081:
082: public void begin() throws NotSupportedException,
083: SystemException {
084: throw new UnsupportedOperationException();
085: }
086:
087: public void commit() throws UnsupportedOperationException {
088: throw new UnsupportedOperationException();
089: }
090:
091: public int getStatus() throws UnsupportedOperationException {
092: throw new UnsupportedOperationException();
093: }
094:
095: public Transaction getTransaction() throws SystemException {
096: return new TransactionAdapter(properties);
097: }
098:
099: public void resume(Transaction txn)
100: throws UnsupportedOperationException {
101: throw new UnsupportedOperationException();
102: }
103:
104: public void rollback() throws UnsupportedOperationException {
105: throw new UnsupportedOperationException();
106: }
107:
108: public void setRollbackOnly()
109: throws UnsupportedOperationException {
110: throw new UnsupportedOperationException();
111: }
112:
113: public void setTransactionTimeout(int i)
114: throws UnsupportedOperationException {
115: throw new UnsupportedOperationException();
116: }
117:
118: public Transaction suspend()
119: throws UnsupportedOperationException {
120: throw new UnsupportedOperationException();
121: }
122:
123: public class TransactionAdapter implements Transaction {
124:
125: private TransactionAdapter(Properties props) {
126: try {
127: if (extendedJTATransaction == null) {
128: extendedJTATransaction = NamingHelper
129: .getInitialContext(props)
130: .lookup(
131: "java:comp/websphere/ExtendedJTATransaction");
132: }
133: } catch (NamingException ne) {
134: throw new HibernateException(ne);
135: }
136: }
137:
138: public void registerSynchronization(
139: final Synchronization synchronization)
140: throws RollbackException, IllegalStateException,
141: SystemException {
142:
143: final InvocationHandler ih = new InvocationHandler() {
144:
145: public Object invoke(Object proxy, Method method,
146: Object[] args) throws Throwable {
147: if ("afterCompletion".equals(method.getName())) {
148: int status = args[2].equals(Boolean.TRUE) ? Status.STATUS_COMMITTED
149: : Status.STATUS_UNKNOWN;
150: synchronization.afterCompletion(status);
151: } else if ("beforeCompletion".equals(method
152: .getName())) {
153: synchronization.beforeCompletion();
154: } else if ("toString".equals(method.getName())) {
155: return synchronization.toString();
156: }
157: return null;
158: }
159:
160: };
161:
162: final Object synchronizationCallback = Proxy
163: .newProxyInstance(
164: getClass().getClassLoader(),
165: new Class[] { synchronizationCallbackClass },
166: ih);
167:
168: try {
169: registerSynchronizationMethod.invoke(
170: extendedJTATransaction,
171: new Object[] { synchronizationCallback });
172: } catch (Exception e) {
173: throw new HibernateException(e);
174: }
175:
176: }
177:
178: public int hashCode() {
179: return getLocalId().hashCode();
180: }
181:
182: public boolean equals(Object other) {
183: if (!(other instanceof TransactionAdapter))
184: return false;
185: TransactionAdapter that = (TransactionAdapter) other;
186: return getLocalId().equals(that.getLocalId());
187: }
188:
189: private Object getLocalId() throws HibernateException {
190: try {
191: return getLocalIdMethod.invoke(
192: extendedJTATransaction, null);
193: } catch (Exception e) {
194: throw new HibernateException(e);
195: }
196: }
197:
198: public void commit() throws UnsupportedOperationException {
199: throw new UnsupportedOperationException();
200: }
201:
202: public boolean delistResource(XAResource resource, int i)
203: throws UnsupportedOperationException {
204: throw new UnsupportedOperationException();
205: }
206:
207: public boolean enlistResource(XAResource resource)
208: throws UnsupportedOperationException {
209: throw new UnsupportedOperationException();
210: }
211:
212: public int getStatus() {
213: return new Integer(0).equals(getLocalId()) ? Status.STATUS_NO_TRANSACTION
214: : Status.STATUS_ACTIVE;
215: }
216:
217: public void rollback() throws UnsupportedOperationException {
218: throw new UnsupportedOperationException();
219: }
220:
221: public void setRollbackOnly()
222: throws UnsupportedOperationException {
223: throw new UnsupportedOperationException();
224: }
225: }
226:
227: }
228:
229: }
|