00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 package org.objectweb.jonas.jdbc;
00027
00028 import java.io.PrintWriter;
00029 import java.sql.DriverManager;
00030 import java.util.HashSet;
00031 import java.util.Iterator;
00032
00033 import javax.resource.ResourceException;
00034 import javax.resource.spi.ConnectionEvent;
00035 import javax.resource.spi.ConnectionEventListener;
00036 import javax.resource.spi.ConnectionRequestInfo;
00037 import javax.resource.spi.LocalTransaction;
00038 import javax.resource.spi.ManagedConnection;
00039 import javax.resource.spi.ManagedConnectionMetaData;
00040 import javax.resource.spi.security.PasswordCredential;
00041 import javax.security.auth.Subject;
00042 import javax.sql.DataSource;
00043 import javax.sql.PooledConnection;
00044 import javax.sql.XAConnection;
00045 import javax.transaction.xa.XAResource;
00046
00047 import org.objectweb.util.monolog.api.BasicLevel;
00048 import org.objectweb.util.monolog.api.Logger;
00049
00050
00051 public class ManagedConnectionImpl
00052 implements ManagedConnection,
00053 javax.resource.spi.LocalTransaction {
00054
00055 public Logger trace = null;
00056
00057 protected PrintWriter out = null;
00058
00059 protected DataSource factory = null;
00060
00061 protected HashSet cels = null;
00062
00063 protected boolean inLocalTransaction = false;
00064
00065 ManagedConnectionFactoryImpl mcf = null;
00066 java.sql.Connection connection = null;
00067 PooledConnection poolCon = null;
00068 XAConnection xaCon = null;
00069 PasswordCredential pc = null;
00070 DriverWrapper wrapper = null;
00071
00072 private XAResource xares;
00073
00074 private boolean isAutoCommit = true;
00075 private boolean closed = false;
00076 private long [] sigList;
00077 private int maxSigs;
00078 private long signature;
00079 private long lastSig;
00080
00081 public ManagedConnectionImpl(ManagedConnectionFactoryImpl _mcf,
00082 PasswordCredential _pc,
00083 java.sql.Connection _con,
00084 PooledConnection _pcon, XAConnection _xa,
00085 DriverWrapper wrp) {
00086
00087 mcf = _mcf;
00088 pc = _pc;
00089 connection = _con;
00090 poolCon = _pcon;
00091 xaCon = _xa;
00092 wrapper = wrp;
00093 xares = null;
00094 out = mcf.pw;
00095 cels = new HashSet();
00096 maxSigs = 50;
00097 sigList = new long[maxSigs];
00098 signature = 0;
00099 lastSig = 0;
00100 trace = mcf.trace;
00101 }
00102
00103 public void signalEvent(int code, Object ch, Exception ex) {
00104 ConnectionEvent ce = null;
00105 if (ex == null) {
00106 ce = new ConnectionEvent(this, code);
00107 } else {
00108 ce = new ConnectionEvent(this, code, ex);
00109 }
00110 if (ch != null) {
00111 ce.setConnectionHandle(ch);
00112 }
00113 for (Iterator it=cels.iterator(); it.hasNext();) {
00114 switch (code) {
00115 case ConnectionEvent.CONNECTION_CLOSED:
00116 ((ConnectionEventListener) it.next()).connectionClosed(ce);
00117 break;
00118 case ConnectionEvent.LOCAL_TRANSACTION_STARTED:
00119 ((ConnectionEventListener) it.next()).localTransactionStarted(ce);
00120 break;
00121 case ConnectionEvent.LOCAL_TRANSACTION_COMMITTED:
00122 ((ConnectionEventListener) it.next()).localTransactionCommitted(ce);
00123 break;
00124 case ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK:
00125 ((ConnectionEventListener) it.next()).localTransactionRolledback(ce);
00126 break;
00127 case ConnectionEvent.CONNECTION_ERROR_OCCURRED:
00128 ((ConnectionEventListener) it.next()).connectionErrorOccurred(ce);
00129 break;
00130 default:
00131 throw new IllegalArgumentException("Illegal eventType: "+code);
00132 }
00133 }
00134 }
00135
00136 public synchronized boolean getAutoCommit() throws ResourceException {
00137 return isAutoCommit;
00138 }
00139
00140 public synchronized void setAutoCommit(boolean ac)
00141 throws ResourceException {
00142 isAutoCommit = ac;
00143 try {
00144 if (connection != null) {
00145 connection.setAutoCommit(ac);
00146 }
00147 } catch (Exception e) {
00148 throw new ResourceException(e.getMessage());
00149 }
00150 }
00151
00155 public void addConnectionEventListener(ConnectionEventListener listener) {
00156 cels.add(listener);
00157 }
00158
00162 public synchronized void associateConnection(Object con)
00163 throws ResourceException {
00164 trace.log(BasicLevel.DEBUG, "connection:"+con);
00165 if (con instanceof ConnectionImpl ) {
00166 ConnectionImpl ci = (ConnectionImpl) con;
00167 long sig = getNewSignature(true);
00168 ci.setSignature(sig);
00169 } else {
00170 throw new ResourceException(
00171 "The managedConnection cannot associate this connection: "+con);
00172 }
00173 }
00174
00178 public void cleanup() throws ResourceException {
00179 if (inLocalTransaction)
00180 throw new ResourceException("A local transaction is not complete");
00181 clearSignature();
00182 }
00183
00187 public synchronized void destroy() throws ResourceException {
00188 trace.log(BasicLevel.DEBUG, "destroy mc="+this+" with connection="+connection);
00189 try {
00190 if (wrapper != null) {
00191 DriverManager.deregisterDriver(wrapper);
00192 }
00193 } catch (Exception ex) {
00194 trace.log(BasicLevel.ERROR,"Unable to deregister Driver wrapper" + ex);
00195 }
00196 if (connection != null) {
00197 try {
00198 connection.close();
00199 } catch (Exception e) {
00200 trace.log(BasicLevel.ERROR,"",e,"ManagedConnectionImpl","destroy");
00201 throw new ResourceException(e.getMessage());
00202 }
00203 connection = null;
00204 }
00205 }
00206
00210 public Object getConnection(Subject subject,ConnectionRequestInfo cxRequestInfo)
00211 throws ResourceException {
00212
00213 trace.log(BasicLevel.DEBUG,"subject:"+subject+" connectionRequest:"+cxRequestInfo);
00214
00215 long sig = getNewSignature(true);
00216
00217 try {
00218 return new ConnectionImpl(this, connection, sig, out);
00219 } catch (Exception e) {
00220 trace.log(BasicLevel.ERROR,"",e,"ManagedConnectionImpl", "getConnection");
00221 throw new ResourceException(e.getMessage());
00222 }
00223 }
00224
00228 public LocalTransaction getLocalTransaction() throws ResourceException {
00229 return (LocalTransaction) this;
00230 }
00231
00235 public PrintWriter getLogWriter() {
00236 return out;
00237 }
00242 public ManagedConnectionMetaData getMetaData()
00243 throws ResourceException {
00244 return new MetaDataImpl(this);
00245 }
00246
00250 public XAResource getXAResource() throws ResourceException {
00251 trace.log(BasicLevel.DEBUG, "");
00252 if (inLocalTransaction)
00253 throw new ResourceException(
00254 "The managedConnection is already in a local transaction and an XA resource cannot be obtained");
00255 if (xares == null) {
00256 if (xaCon != null) {
00257 try {
00258 xares = xaCon.getXAResource();
00259 } catch (Exception ex) {
00260 throw new ResourceException(
00261 "Unable to obtain XAResource: "+ex.getMessage());
00262 }
00263 } else {
00264 trace.log(BasicLevel.DEBUG, "JDBC driver doesn't support XA, simulate it with "+xares);
00265 }
00266 xares = new XAResourceImpl(this, xares);
00267 }
00268 return xares;
00269 }
00270
00275 public void removeConnectionEventListener(
00276 ConnectionEventListener listener) {
00277 cels.remove(listener);
00278 }
00279
00283 public void setLogWriter(PrintWriter _out) {
00284 out = _out;
00285 }
00286
00287 public
00288 void addSignature(long sig)
00289 {
00290 int off = -1;
00291 for (int i=0;i<maxSigs;i++)
00292 if (sigList[i] == 0)
00293 {
00294 off = i;
00295 break;
00296 }
00297
00298 if (off > -1)
00299 sigList[off] = sig;
00300 else
00301 {
00302 maxSigs += 20;
00303 long [] tmp = new long[maxSigs];
00304 System.arraycopy(sigList, 0, tmp, 0, maxSigs-20);
00305 sigList = tmp;
00306 sigList[maxSigs-20] = sig;
00307 }
00308 }
00309
00310 public
00311 void clearSignature()
00312 {
00313 for (int i=0;i<maxSigs;i++)
00314 sigList[i] = 0;
00315 signature = 0;
00316 }
00317
00318 public
00319 void clearSignature(long sig, boolean clear)
00320 {
00321 for (int i=0;i<maxSigs;i++) {
00322 if (sig == sigList[i])
00323 {
00324 sigList[i] = 0;
00325 break;
00326 }
00327 }
00328 if (clear) {
00329 signature = 0;
00330 }
00331 }
00332
00333 public
00334 void setSignature(long sig)
00335 {
00336 if (signature == 0) {
00337 signature = sig;
00338 }
00339 }
00340
00347 public
00348 long getSignature(long sig)
00349 {
00350
00351 long retSig = 0;
00352 if (sig > 0)
00353 {
00354 for (int i=0;i<maxSigs;i++)
00355 if (sig == sigList[i])
00356 {
00357 retSig = sig;
00358 break;
00359 }
00360 }
00361 return (retSig);
00362 }
00363
00368 public
00369 long getSignature() {
00370 return (signature);
00371 }
00372
00377 public
00378 long getNewSignature(boolean setSig) {
00379 long sig = System.currentTimeMillis();
00380 if (sig <= lastSig && lastSig != 0) {
00381 sig = lastSig++;
00382 }
00383 trace.log(BasicLevel.DEBUG,"Sig is "+sig+" last Sig was "+lastSig);
00384 lastSig = sig;
00385 addSignature(sig);
00386 if (setSig) {
00387 signature = sig;
00388 }
00389 return sig;
00390 }
00391
00392
00393 public void close(ConnectionImpl ch) throws ResourceException {
00394 clearSignature(ch.key, true);
00395 signalEvent(ConnectionEvent.CONNECTION_CLOSED,ch,null);
00396 }
00397
00398
00400
00401 public void begin() throws ResourceException {
00402 if (inLocalTransaction)
00403 throw new ResourceException(
00404 "The managedConnection is already in a LocalTransaction");
00405 try {
00406 inLocalTransaction = true;
00407 connection.setAutoCommit(false);
00408 } catch (Exception ex) {
00409 }
00410 }
00411
00412 public void commit() throws ResourceException {
00413 try {
00414 connection.commit();
00415 connection.setAutoCommit(true);
00416 inLocalTransaction = false;
00417 } catch (Exception ex) {
00418 }
00419 }
00420
00421 public void rollback() throws ResourceException {
00422 try {
00423 connection.rollback();
00424 connection.setAutoCommit(true);
00425 inLocalTransaction = false;
00426 } catch (Exception ex) {
00427 }
00428 }
00429
00430 }