001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.sql.spy;
031:
032: import com.caucho.log.Log;
033: import com.caucho.util.L10N;
034:
035: import java.sql.*;
036: import java.util.Map;
037: import java.util.Properties;
038: import java.util.logging.*;
039:
040: /**
041: * Spying on a connection.
042: */
043: public class SpyConnection implements java.sql.Connection {
044: protected final static Logger log = Logger
045: .getLogger(SpyConnection.class.getName());
046: protected final static Logger logXA = Logger
047: .getLogger(SpyConnection.class.getName() + ".XA");
048: protected final static L10N L = new L10N(SpyConnection.class);
049:
050: private SpyDataSource _spyDataSource;
051:
052: private String _id;
053: private int _stmtIdCount;
054:
055: // The underlying connection
056: private Connection _conn;
057:
058: /**
059: * Creates a new SpyConnection.
060: */
061: public SpyConnection(Connection conn, SpyDataSource spyDataSource) {
062: _spyDataSource = spyDataSource;
063: _conn = conn;
064: }
065:
066: /**
067: * Creates a new SpyConnection.
068: */
069: public SpyConnection(Connection conn, SpyDataSource spyDataSource,
070: String id) {
071: _spyDataSource = spyDataSource;
072: _conn = conn;
073: _id = id;
074: }
075:
076: /**
077: * Returns the underlying connection.
078: */
079: public Connection getConnection() {
080: return _conn;
081: }
082:
083: /**
084: * Returns the id.
085: */
086: public String getId() {
087: if (_id == null)
088: _id = _spyDataSource.createConnectionId();
089:
090: return _id;
091: }
092:
093: /**
094: * Returns a new statement id.
095: */
096: public String createStatementId() {
097: return getId() + "." + _stmtIdCount++;
098: }
099:
100: /**
101: * JDBC api to return the connection's catalog.
102: *
103: * @return the JDBC catalog.
104: */
105: public String getCatalog() throws SQLException {
106: try {
107: String catalog = _conn.getCatalog();
108:
109: log.fine(getId() + ":getCatalog() -> " + catalog);
110:
111: return catalog;
112: } catch (SQLException e) {
113: log.fine(getId() + ":exn-getCatalog(" + e + ")");
114:
115: throw e;
116: }
117: }
118:
119: /**
120: * Sets the JDBC catalog.
121: */
122: public void setCatalog(String catalog) throws SQLException {
123: try {
124: log.fine(getId() + ":setCatalog(" + catalog + ")");
125:
126: _conn.setCatalog(catalog);
127: } catch (SQLException e) {
128: log.fine(getId() + ":exn-setCatalog(" + e + ")");
129: throw e;
130: }
131: }
132:
133: /**
134: * Gets the connection's metadata.
135: */
136: public DatabaseMetaData getMetaData() throws SQLException {
137: try {
138: DatabaseMetaData metaData = _conn.getMetaData();
139:
140: // Avoid logging result of metaData.toString() here
141: // because it may not be overloaded. The default
142: // toString() result contains a hex representation
143: // of the memory location that can't be matched in a
144: // regression test.
145:
146: String ident = metaData.getClass().getName();
147:
148: log.fine(getId() + ":getMetaData() -> " + ident);
149:
150: return metaData;
151: } catch (SQLException e) {
152: log.fine(getId() + ":exn-getMetaData(" + e + ")");
153: throw e;
154: }
155: }
156:
157: /**
158: * Returns the connection's type map.
159: */
160: public Map getTypeMap() throws SQLException {
161: try {
162: Map map = _conn.getTypeMap();
163:
164: log.fine(getId() + ":getTypeMap() -> " + map);
165:
166: return map;
167: } catch (SQLException e) {
168: log.fine(getId() + ":exn-getTypeMap(" + e + ")");
169: throw e;
170: }
171: }
172:
173: /**
174: * Sets the connection's type map.
175: */
176: public void setTypeMap(Map<String, Class<?>> map)
177: throws SQLException {
178: try {
179: log.fine(getId() + ":setTypeMap(" + map + ")");
180:
181: _conn.setTypeMap(map);
182: } catch (SQLException e) {
183: log.fine(getId() + ":exn-setTypeMap(" + e + ")");
184:
185: throw e;
186: }
187: }
188:
189: /**
190: * Calls the nativeSQL method for the connection.
191: */
192: public String nativeSQL(String sql) throws SQLException {
193: try {
194: String nativeSQL = _conn.nativeSQL(sql);
195:
196: log.fine(getId() + ":nativeSQL() -> " + nativeSQL);
197:
198: return nativeSQL;
199: } catch (SQLException e) {
200: log.fine(getId() + ":exn-nativeSQL(" + e + ")");
201:
202: throw e;
203: }
204: }
205:
206: public int getTransactionIsolation() throws SQLException {
207: try {
208: int isolation = _conn.getTransactionIsolation();
209:
210: log.fine(getId() + ":getTransactionIsolation() -> "
211: + isolation);
212:
213: return isolation;
214: } catch (SQLException e) {
215: log.fine(getId() + ":exn-getTransactionIsolation(" + e
216: + ")");
217:
218: throw e;
219: }
220: }
221:
222: public void setTransactionIsolation(int isolation)
223: throws SQLException {
224: try {
225: log.fine(getId() + ":setTransactionIsolation(" + isolation
226: + ")");
227:
228: _conn.setTransactionIsolation(isolation);
229: } catch (SQLException e) {
230: log.fine(getId() + ":exn-setTransactionIsolation(" + e
231: + ")");
232:
233: throw e;
234: }
235: }
236:
237: public SQLWarning getWarnings() throws SQLException {
238: try {
239: SQLWarning warning = _conn.getWarnings();
240:
241: log.fine(getId() + ":getWarnings() -> " + warning);
242:
243: return warning;
244: } catch (SQLException e) {
245: log.fine(getId() + ":exn-getWarnings(" + e + ")");
246:
247: throw e;
248: }
249: }
250:
251: public void clearWarnings() throws SQLException {
252: try {
253: log.fine(getId() + ":clearWarnings()");
254:
255: _conn.clearWarnings();
256: } catch (SQLException e) {
257: log.fine(getId() + ":exn-clearWarnings(" + e + ")");
258:
259: throw e;
260: }
261: }
262:
263: public void setReadOnly(boolean readOnly) throws SQLException {
264: try {
265: log.fine(getId() + ":setReadOnly(" + readOnly + ")");
266:
267: _conn.setReadOnly(readOnly);
268: } catch (SQLException e) {
269: log.fine(getId() + ":exn-setReadOnly(" + e + ")");
270:
271: throw e;
272: }
273: }
274:
275: public boolean isReadOnly() throws SQLException {
276: try {
277: boolean isReadOnly = _conn.isReadOnly();
278:
279: log.fine(getId() + "isReadOnly() -> " + isReadOnly);
280:
281: return isReadOnly;
282:
283: } catch (SQLException e) {
284: log.fine(getId() + ":exn-isReadOnly(" + e + ")");
285:
286: throw e;
287: }
288: }
289:
290: /**
291: * JDBC api to create a new statement. Any SQL exception thrown here
292: * will make the connection invalid, i.e. it can't be put back into
293: * the pool.
294: *
295: * @return a new JDBC statement.
296: */
297: public Statement createStatement() throws SQLException {
298: try {
299: String stmtId = null;
300:
301: if (log.isLoggable(Level.FINE)) {
302: stmtId = createStatementId();
303: log.fine(stmtId + ":createStatement()");
304: }
305:
306: Statement stmt;
307:
308: stmt = _conn.createStatement();
309:
310: return new SpyStatement(stmtId, this , stmt);
311: } catch (SQLException e) {
312: log.fine(getId() + ":exn-createStatement(" + e + ")");
313: throw e;
314: }
315: }
316:
317: /**
318: * JDBC api to create a new statement. Any SQL exception thrown here
319: * will make the connection invalid, i.e. it can't be put back into
320: * the pool.
321: *
322: * @return a new JDBC statement.
323: */
324: public Statement createStatement(int resultSetType,
325: int resultSetConcurrency) throws SQLException {
326: try {
327: String stmtId = null;
328:
329: if (log.isLoggable(Level.FINE)) {
330: stmtId = createStatementId();
331:
332: log.fine(stmtId + ":createStatement(type="
333: + resultSetType + ",concurrency="
334: + resultSetConcurrency + ")");
335: }
336:
337: Statement stmt;
338:
339: stmt = _conn.createStatement(resultSetType,
340: resultSetConcurrency);
341:
342: return new SpyStatement(stmtId, this , stmt);
343: } catch (SQLException e) {
344: log.fine(getId() + ":exn-createStatement(" + e + ")");
345: throw e;
346: }
347: }
348:
349: public Statement createStatement(int resultSetType,
350: int resultSetConcurrency, int resultSetHoldability)
351: throws SQLException {
352: try {
353: String stmtId = null;
354:
355: if (log.isLoggable(Level.FINE)) {
356: stmtId = createStatementId();
357:
358: log.fine(stmtId + ":createStatement(type="
359: + resultSetType + ",concurrency="
360: + resultSetConcurrency + ",holdability="
361: + resultSetHoldability + ")");
362: }
363:
364: Statement stmt;
365:
366: stmt = _conn.createStatement(resultSetType,
367: resultSetConcurrency, resultSetHoldability);
368:
369: return new SpyStatement(stmtId, this , stmt);
370: } catch (SQLException e) {
371: log.fine(getId() + ":exn-createStatement(" + e + ")");
372: throw e;
373: }
374: }
375:
376: public PreparedStatement prepareStatement(String sql)
377: throws SQLException {
378: try {
379: String stmtId = null;
380:
381: if (log.isLoggable(Level.FINE)) {
382: stmtId = createStatementId();
383: log.fine(stmtId + ":prepareStatement(" + sql + ")");
384: }
385:
386: PreparedStatement stmt;
387:
388: stmt = _conn.prepareStatement(sql);
389:
390: return new SpyPreparedStatement(stmtId, this , stmt, sql);
391: } catch (SQLException e) {
392: log.fine(getId() + ":exn-prepareStatement(" + e + ")");
393:
394: throw e;
395: }
396: }
397:
398: public PreparedStatement prepareStatement(String sql,
399: int resultSetType) throws SQLException {
400: try {
401: String stmtId = null;
402:
403: if (log.isLoggable(Level.FINE)) {
404: stmtId = createStatementId();
405: log.fine(stmtId + ":prepareStatement(" + sql + ",type="
406: + resultSetType + ")");
407: }
408:
409: PreparedStatement stmt;
410:
411: stmt = _conn.prepareStatement(sql, resultSetType);
412:
413: return new SpyPreparedStatement(stmtId, this , stmt, sql);
414: } catch (SQLException e) {
415: log.fine(getId() + ":exn-prepareStatement(" + e + ")");
416:
417: throw e;
418: }
419: }
420:
421: public PreparedStatement prepareStatement(String sql,
422: int resultSetType, int resultSetConcurrency)
423: throws SQLException {
424: try {
425: String stmtId = null;
426:
427: if (log.isLoggable(Level.FINE)) {
428: stmtId = createStatementId();
429:
430: log.fine(stmtId + ":prepareStatement(" + sql + ",type="
431: + resultSetType + ",concurrency="
432: + resultSetConcurrency + ")");
433: }
434:
435: PreparedStatement stmt;
436:
437: stmt = _conn.prepareStatement(sql, resultSetType,
438: resultSetConcurrency);
439:
440: return new SpyPreparedStatement(stmtId, this , stmt, sql);
441: } catch (SQLException e) {
442: log.fine(getId() + ":exn-prepareStatement(" + e + ")");
443:
444: throw e;
445: }
446: }
447:
448: public PreparedStatement prepareStatement(String sql,
449: int resultSetType, int resultSetConcurrency,
450: int resultSetHoldability) throws SQLException {
451: return null;
452: }
453:
454: public PreparedStatement prepareStatement(String sql,
455: int[] columnIndexes) throws SQLException {
456: return null;
457: }
458:
459: public PreparedStatement prepareStatement(String sql,
460: String[] columnNames) throws SQLException {
461: return null;
462: }
463:
464: public CallableStatement prepareCall(String sql)
465: throws SQLException {
466: try {
467: if (log.isLoggable(Level.FINE))
468: log.fine(getId() + ":prepareCall(" + sql + ")");
469:
470: CallableStatement stmt;
471:
472: stmt = _conn.prepareCall(sql);
473:
474: return stmt;
475: } catch (SQLException e) {
476: log.fine(getId() + ":exn-prepareCall(" + e + ")");
477:
478: throw e;
479: }
480: }
481:
482: public CallableStatement prepareCall(String sql, int resultSetType,
483: int resultSetConcurrency) throws SQLException {
484: try {
485: if (log.isLoggable(Level.FINE))
486: log.fine(getId() + ":prepareCall(" + sql + ",type="
487: + resultSetType + ",concurrency="
488: + resultSetConcurrency + ")");
489:
490: CallableStatement stmt;
491:
492: stmt = _conn.prepareCall(sql);
493:
494: return stmt;
495: } catch (SQLException e) {
496: log.fine(getId() + ":exn-prepareCall(" + e + ")");
497:
498: throw e;
499: }
500: }
501:
502: public CallableStatement prepareCall(String sql, int resultSetType,
503: int resultSetConcurrency, int resultSetHoldability)
504: throws SQLException {
505: return null;
506: }
507:
508: public boolean getAutoCommit() throws SQLException {
509: try {
510: boolean autoCommit = _conn.getAutoCommit();
511:
512: log.fine(getId() + ":getAutoCommit() -> " + autoCommit);
513:
514: return autoCommit;
515: } catch (SQLException e) {
516: log.fine(getId() + ":exn-getAutoCommit(" + e + ")");
517:
518: throw e;
519: }
520: }
521:
522: public void setAutoCommit(boolean autoCommit) throws SQLException {
523: try {
524: logXA.fine(getId() + ":setAutoCommit(" + autoCommit + ")");
525:
526: _conn.setAutoCommit(autoCommit);
527: } catch (SQLException e) {
528: logXA.fine(getId() + ":exn-setAutoCommit(" + e + ")");
529:
530: throw e;
531: }
532: }
533:
534: public void commit() throws SQLException {
535: try {
536: logXA.fine(getId() + ":commit()");
537:
538: _conn.commit();
539: } catch (SQLException e) {
540: logXA.fine(getId() + ":exn-commit(" + e + ")");
541:
542: throw e;
543: }
544: }
545:
546: public void rollback() throws SQLException {
547: try {
548: logXA.fine(getId() + ":rollback()");
549:
550: _conn.rollback();
551: } catch (SQLException e) {
552: logXA.fine(getId() + ":exn-rollback(" + e + ")");
553:
554: throw e;
555: }
556: }
557:
558: /**
559: * Returns true if the connection is closed.
560: */
561: public boolean isClosed() throws SQLException {
562: try {
563: boolean isClosed = _conn.isClosed();
564:
565: log.fine(getId() + ":isClosed() -> " + isClosed);
566:
567: return isClosed;
568: } catch (SQLException e) {
569: log.fine(getId() + ":exn-isClosed(" + e + ")");
570:
571: throw e;
572: }
573: }
574:
575: /**
576: * Reset the connection and return the underlying JDBC connection to
577: * the pool.
578: */
579: public void close() throws SQLException {
580: log.fine(getId() + ":close()");
581:
582: try {
583: _conn.close();
584: } catch (SQLException e) {
585: log.fine(getId() + ":exn-close(" + e + ")");
586:
587: throw e;
588: }
589: }
590:
591: public void setHoldability(int hold) throws SQLException {
592: _conn.setHoldability(hold);
593: }
594:
595: public int getHoldability() throws SQLException {
596: return _conn.getHoldability();
597: }
598:
599: public Savepoint setSavepoint() throws SQLException {
600: return _conn.setSavepoint();
601: }
602:
603: public Savepoint setSavepoint(String name) throws SQLException {
604: return _conn.setSavepoint(name);
605: }
606:
607: public void releaseSavepoint(Savepoint savepoint)
608: throws SQLException {
609: _conn.releaseSavepoint(savepoint);
610: }
611:
612: public void rollback(Savepoint savepoint) throws SQLException {
613: _conn.rollback(savepoint);
614: }
615:
616: public String toString() {
617: return "SpyConnection[id=" + getId() + ",conn=" + _conn + "]";
618: }
619:
620: public Clob createClob() throws SQLException {
621: throw new UnsupportedOperationException("Not supported yet.");
622: }
623:
624: public Blob createBlob() throws SQLException {
625: throw new UnsupportedOperationException("Not supported yet.");
626: }
627:
628: public NClob createNClob() throws SQLException {
629: throw new UnsupportedOperationException("Not supported yet.");
630: }
631:
632: public SQLXML createSQLXML() throws SQLException {
633: throw new UnsupportedOperationException("Not supported yet.");
634: }
635:
636: public boolean isValid(int timeout) throws SQLException {
637: throw new UnsupportedOperationException("Not supported yet.");
638: }
639:
640: public void setClientInfo(String name, String value)
641: throws SQLClientInfoException {
642: throw new UnsupportedOperationException("Not supported yet.");
643: }
644:
645: public void setClientInfo(Properties properties)
646: throws SQLClientInfoException {
647: throw new UnsupportedOperationException("Not supported yet.");
648: }
649:
650: public String getClientInfo(String name) throws SQLException {
651: throw new UnsupportedOperationException("Not supported yet.");
652: }
653:
654: public Properties getClientInfo() throws SQLException {
655: throw new UnsupportedOperationException("Not supported yet.");
656: }
657:
658: public Array createArrayOf(String typeName, Object[] elements)
659: throws SQLException {
660: throw new UnsupportedOperationException("Not supported yet.");
661: }
662:
663: public Struct createStruct(String typeName, Object[] attributes)
664: throws SQLException {
665: throw new UnsupportedOperationException("Not supported yet.");
666: }
667:
668: public <T> T unwrap(Class<T> iface) throws SQLException {
669: throw new UnsupportedOperationException("Not supported yet.");
670: }
671:
672: public boolean isWrapperFor(Class<?> iface) throws SQLException {
673: throw new UnsupportedOperationException("Not supported yet.");
674: }
675: }
|