001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999-2005 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: ManagedConnectionImpl.java 8651 2006-06-16 16:56:27Z ehardesty $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas.jdbc;
025:
026: import java.io.PrintWriter;
027: import java.sql.DriverManager;
028: import java.util.HashSet;
029: import java.util.Iterator;
030:
031: import javax.resource.ResourceException;
032: import javax.resource.spi.ConnectionEvent;
033: import javax.resource.spi.ConnectionEventListener;
034: import javax.resource.spi.ConnectionRequestInfo;
035: import javax.resource.spi.LocalTransaction;
036: import javax.resource.spi.ManagedConnection;
037: import javax.resource.spi.ManagedConnectionMetaData;
038: import javax.resource.spi.security.PasswordCredential;
039: import javax.security.auth.Subject;
040: import javax.sql.DataSource;
041: import javax.sql.PooledConnection;
042: import javax.sql.XAConnection;
043: import javax.transaction.xa.XAResource;
044:
045: import org.objectweb.util.monolog.api.BasicLevel;
046: import org.objectweb.util.monolog.api.Logger;
047:
048: /**
049: * @author Eric hardesty
050: */
051: public class ManagedConnectionImpl implements ManagedConnection,
052: javax.resource.spi.LocalTransaction {
053:
054: public Logger trace = null;
055:
056: protected PrintWriter out = null;
057:
058: protected DataSource factory = null;
059:
060: protected HashSet cels = null;
061:
062: protected boolean inLocalTransaction = false;
063:
064: ManagedConnectionFactoryImpl mcf = null;
065:
066: java.sql.Connection connection = null;
067:
068: PooledConnection poolCon = null;
069:
070: XAConnection xaCon = null;
071:
072: PasswordCredential pc = null;
073:
074: DriverWrapper wrapper = null;
075:
076: private XAResource xares;
077:
078: private boolean isAutoCommit = true;
079:
080: private boolean closed = false;
081:
082: private long[] sigList;
083:
084: private int maxSigs;
085:
086: private long signature;
087:
088: private long lastSig;
089:
090: /**
091: * Logging (debug enabled)
092: */
093: private final boolean isDebugOn;
094:
095: public ManagedConnectionImpl(ManagedConnectionFactoryImpl _mcf,
096: PasswordCredential _pc, java.sql.Connection _con,
097: PooledConnection _pcon, XAConnection _xa, DriverWrapper wrp) {
098:
099: mcf = _mcf;
100: pc = _pc;
101: connection = _con;
102: poolCon = _pcon;
103: xaCon = _xa;
104: wrapper = wrp;
105: xares = null;
106: out = mcf.pw;
107: cels = new HashSet();
108: maxSigs = 50;
109: sigList = new long[maxSigs];
110: signature = 0;
111: lastSig = 0;
112: trace = mcf.trace;
113: isDebugOn = trace.isLoggable(BasicLevel.DEBUG);
114: }
115:
116: public void signalEvent(int code, Object ch, Exception ex) {
117: ConnectionEvent ce = null;
118: if (ex == null) {
119: ce = new ConnectionEvent(this , code);
120: } else {
121: ce = new ConnectionEvent(this , code, ex);
122: }
123: if (ch != null) {
124: ce.setConnectionHandle(ch);
125: }
126: for (Iterator it = cels.iterator(); it.hasNext();) {
127: switch (code) {
128: case ConnectionEvent.CONNECTION_CLOSED:
129: ((ConnectionEventListener) it.next())
130: .connectionClosed(ce);
131: break;
132: case ConnectionEvent.LOCAL_TRANSACTION_STARTED:
133: ((ConnectionEventListener) it.next())
134: .localTransactionStarted(ce);
135: break;
136: case ConnectionEvent.LOCAL_TRANSACTION_COMMITTED:
137: ((ConnectionEventListener) it.next())
138: .localTransactionCommitted(ce);
139: break;
140: case ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK:
141: ((ConnectionEventListener) it.next())
142: .localTransactionRolledback(ce);
143: break;
144: case ConnectionEvent.CONNECTION_ERROR_OCCURRED:
145: ((ConnectionEventListener) it.next())
146: .connectionErrorOccurred(ce);
147: break;
148: default:
149: throw new IllegalArgumentException(
150: "Illegal eventType: " + code);
151: }
152: }
153: }
154:
155: public synchronized boolean getAutoCommit()
156: throws ResourceException {
157: return isAutoCommit;
158: }
159:
160: public synchronized void setAutoCommit(boolean ac)
161: throws ResourceException {
162: isAutoCommit = ac;
163: try {
164: if (connection != null) {
165: connection.setAutoCommit(ac);
166: }
167: } catch (Exception e) {
168: throw new ResourceException(e.getMessage());
169: }
170: }
171:
172: /**
173: * Adds a connection event listener.
174: */
175: public void addConnectionEventListener(
176: ConnectionEventListener listener) {
177: cels.add(listener);
178: }
179:
180: /**
181: * Change the association of a connection handle
182: */
183: public synchronized void associateConnection(Object con)
184: throws ResourceException {
185: if (isDebugOn) {
186: trace.log(BasicLevel.DEBUG, "connection:" + con);
187: }
188: if (con instanceof ConnectionImpl) {
189: ConnectionImpl ci = (ConnectionImpl) con;
190: long sig = getNewSignature(true);
191: ci.setSignature(sig);
192: } else {
193: throw new ResourceException(
194: "The managedConnection cannot associate this connection: "
195: + con);
196: }
197: }
198:
199: /**
200: * Cleanup the ManagedConnection instance.
201: */
202: public void cleanup() throws ResourceException {
203: if (inLocalTransaction)
204: throw new ResourceException(
205: "A local transaction is not complete");
206: clearSignature();
207: }
208:
209: /**
210: * Destroys the physical connection.
211: */
212: public synchronized void destroy() throws ResourceException {
213: if (isDebugOn) {
214: trace.log(BasicLevel.DEBUG, "destroy mc=" + this
215: + " with connection=" + connection);
216: }
217: try {
218: if (wrapper != null) {
219: DriverManager.deregisterDriver(wrapper);
220: }
221: } catch (Exception ex) {
222: trace.log(BasicLevel.ERROR,
223: "Unable to deregister Driver wrapper", ex);
224: }
225: if (connection != null) {
226: try {
227: connection.close();
228: } catch (Exception e) {
229: trace.log(BasicLevel.ERROR, "", e,
230: "ManagedConnectionImpl", "destroy");
231: throw new ResourceException(e);
232: }
233: connection = null;
234: poolCon = null;
235: xaCon = null;
236: xares = null;
237: }
238: }
239:
240: /**
241: * Create a connection handle
242: */
243: public Object getConnection(Subject subject,
244: ConnectionRequestInfo cxRequestInfo)
245: throws ResourceException {
246: if (isDebugOn) {
247: trace.log(BasicLevel.DEBUG, "subject:" + subject
248: + " connectionRequest:" + cxRequestInfo);
249: }
250:
251: long sig = getNewSignature(true);
252:
253: try {
254: return new ConnectionImpl(this , connection, sig, out);
255: } catch (Exception e) {
256: trace.log(BasicLevel.ERROR, "", e, "ManagedConnectionImpl",
257: "getConnection");
258: throw new ResourceException(e.getMessage());
259: }
260: }
261:
262: /**
263: * Returns an javax.resource.spi.LocalTransaction instance.
264: */
265: public LocalTransaction getLocalTransaction()
266: throws ResourceException {
267: return (LocalTransaction) this ;
268: }
269:
270: /**
271: * Gets the log writer for this ManagedConnection instance.
272: */
273: public PrintWriter getLogWriter() {
274: return out;
275: }
276:
277: /**
278: * Gets the metadata information for this connection's underlying EIS
279: * resource manager instance.
280: */
281: public ManagedConnectionMetaData getMetaData()
282: throws ResourceException {
283: return new MetaDataImpl(this );
284: }
285:
286: /**
287: * Check if the mc is in local transaction
288: */
289: public XAResource getXAResource() throws ResourceException {
290: if (isDebugOn) {
291: trace.log(BasicLevel.DEBUG, "");
292: }
293: if (inLocalTransaction)
294: throw new ResourceException(
295: "The managedConnection is already in a local transaction and an XA resource cannot be obtained");
296: if (xares == null) {
297: if (xaCon != null) {
298: try {
299: xares = xaCon.getXAResource();
300: } catch (Exception ex) {
301: throw new ResourceException(
302: "Unable to obtain XAResource: ", ex);
303: }
304: } else {
305: if (isDebugOn) {
306: trace.log(BasicLevel.DEBUG,
307: "JDBC driver doesn't support XA, simulate it with "
308: + xares);
309: }
310: }
311: xares = new XAResourceImpl(this , xares);
312: }
313: return xares;
314: }
315:
316: /**
317: * Removes an already registered connection event listener from the
318: * ManagedConnection instance
319: */
320: public void removeConnectionEventListener(
321: ConnectionEventListener listener) {
322: cels.remove(listener);
323: }
324:
325: /**
326: * Sets the log writer for this ManagedConnection instance.
327: */
328: public void setLogWriter(PrintWriter _out) {
329: out = _out;
330: }
331:
332: public void addSignature(long sig) {
333: int off = -1;
334: for (int i = 0; i < maxSigs; i++)
335: if (sigList[i] == 0) {
336: off = i;
337: break;
338: }
339:
340: if (off > -1)
341: sigList[off] = sig;
342: else {
343: maxSigs += 20;
344: long[] tmp = new long[maxSigs];
345: System.arraycopy(sigList, 0, tmp, 0, maxSigs - 20);
346: sigList = tmp;
347: sigList[maxSigs - 20] = sig;
348: }
349: }
350:
351: public void clearSignature() {
352: for (int i = 0; i < maxSigs; i++)
353: sigList[i] = 0;
354: signature = 0;
355: }
356:
357: public void clearSignature(long sig, boolean clear) {
358: for (int i = 0; i < maxSigs; i++) {
359: if (sig == sigList[i]) {
360: sigList[i] = 0;
361: break;
362: }
363: }
364: if (clear) {
365: signature = 0;
366: }
367: }
368:
369: public void setSignature(long sig) {
370: if (signature == 0) {
371: signature = sig;
372: }
373: }
374:
375: /**
376: * Gets the signature value passed in if found in the signature hash table
377: * @param long sig value to find in signature table
378: * @return long signature value or 0 if not found
379: */
380: public long getSignature(long sig) {
381: // find signature
382: long retSig = 0;
383: if (sig > 0) {
384: for (int i = 0; i < maxSigs; i++)
385: if (sig == sigList[i]) {
386: retSig = sig;
387: break;
388: }
389: }
390: return (retSig);
391: }
392:
393: /**
394: * Gets the current signature value
395: * @return long current signature value
396: */
397: public long getSignature() {
398: return (signature);
399: }
400:
401: /**
402: * Gets the next signature value
403: * @return long next signature value
404: */
405: public long getNewSignature(boolean setSig) {
406: long sig = System.currentTimeMillis();
407: if (sig <= lastSig && lastSig != 0) {
408: sig = lastSig++;
409: }
410: if (isDebugOn) {
411: trace.log(BasicLevel.DEBUG, "Sig is " + sig
412: + " last Sig was " + lastSig);
413: }
414: lastSig = sig;
415: addSignature(sig);
416: if (setSig) {
417: signature = sig;
418: }
419: return sig;
420: }
421:
422: public void close(ConnectionImpl ch) throws ResourceException {
423: clearSignature(ch.key, true);
424: signalEvent(ConnectionEvent.CONNECTION_CLOSED, ch, null);
425: }
426:
427: /** ******************************************************* */
428: /** IMPLEMENTATION OF INTERFACE LocalTransaction * */
429: /** ******************************************************* */
430: public void begin() throws ResourceException {
431: if (inLocalTransaction)
432: throw new ResourceException(
433: "The managedConnection is already in a LocalTransaction");
434: try {
435: inLocalTransaction = true;
436: connection.setAutoCommit(false);
437: } catch (Exception ex) {
438: }
439: }
440:
441: public void commit() throws ResourceException {
442: try {
443: connection.commit();
444: connection.setAutoCommit(true);
445: inLocalTransaction = false;
446: } catch (Exception ex) {
447: }
448: }
449:
450: public void rollback() throws ResourceException {
451: try {
452: connection.rollback();
453: connection.setAutoCommit(true);
454: inLocalTransaction = false;
455: } catch (Exception ex) {
456: }
457: }
458:
459: }
|