001: /**
002: * EasyBeans
003: * Copyright (C) 2006 Bull S.A.S.
004: * Contact: easybeans@ow2.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: JStatement.java 1970 2007-10-16 11:49:25Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.component.jdbcpool;
025:
026: import java.io.InputStream;
027: import java.io.Reader;
028: import java.math.BigDecimal;
029: import java.net.URL;
030: import java.sql.Array;
031: import java.sql.Blob;
032: import java.sql.Clob;
033: import java.sql.Connection;
034: import java.sql.Date;
035: import java.sql.ParameterMetaData;
036: import java.sql.PreparedStatement;
037: import java.sql.Ref;
038: import java.sql.ResultSet;
039: import java.sql.ResultSetMetaData;
040: import java.sql.SQLException;
041: import java.sql.SQLWarning;
042: import java.sql.Time;
043: import java.sql.Timestamp;
044: import java.util.Calendar;
045:
046: import org.ow2.util.log.Log;
047: import org.ow2.util.log.LogFactory;
048:
049: /**
050: * Wrapper on a PreparedStatement. This wrapper is used to track close method in
051: * order to avoid closing the statement, and putting it instead in a pool.
052: * @author Philippe Durieux
053: * @author Florent Benoit
054: */
055: public class JStatement implements PreparedStatement {
056:
057: /**
058: * Properties of this statement has been changed ? Needs to be be cleared when reused.
059: */
060: private boolean changed = false;
061:
062: /**
063: * Is that this statement is opened ?
064: */
065: private boolean opened = false;
066:
067: /**
068: * Being closed. (in close method).
069: */
070: private boolean closing = false;
071:
072: /**
073: * Physical PreparedStatement object on which the wrapper is.
074: */
075: private PreparedStatement ps;
076:
077: /**
078: * Managed Connection the Statement belongs to.
079: */
080: private JManagedConnection mc;
081:
082: /**
083: * Hashcode computed in constructor.
084: */
085: private int hashCode;
086:
087: /**
088: * SQL used as statement.
089: */
090: private String sql;
091:
092: /**
093: * Logger.
094: */
095: private Log logger = LogFactory.getLog(JStatement.class);
096:
097: /**
098: * Builds a new statement with the given wrapped statement of given connection and given sql query.
099: * @param ps the prepared statement.
100: * @param mc managed connection
101: * @param sql query.
102: */
103: public JStatement(final PreparedStatement ps,
104: final JManagedConnection mc, final String sql) {
105: this .ps = ps;
106: this .mc = mc;
107: this .sql = sql;
108: hashCode = sql.hashCode();
109: opened = true;
110: }
111:
112: /**
113: * @return Sql query used.
114: */
115: public String getSql() {
116: return sql;
117: }
118:
119: /**
120: * @return hashcode of the object
121: */
122: @Override
123: public int hashCode() {
124: return hashCode;
125: }
126:
127: /**
128: * @param stmt given statement for comparing it
129: * @return true if given object is equals to this current object
130: */
131: @Override
132: public boolean equals(final Object stmt) {
133: if (stmt == null) {
134: return false;
135: }
136: // different hashcode, cannot be equals
137: if (this .hashCode != stmt.hashCode()) {
138: return false;
139: }
140:
141: // if got same hashcode, try to see if cast is ok.
142: if (!(stmt instanceof JStatement)) {
143: logger.warn("Bad class {0}", stmt);
144: return false;
145: }
146: JStatement psw = (JStatement) stmt;
147: if (sql == null && psw.getSql() != null) {
148: return false;
149: }
150: if (sql != null && !sql.equals(psw.getSql())) {
151: return false;
152: }
153: try {
154: if (psw.getResultSetType() != getResultSetType()) {
155: return false;
156: }
157: if (psw.getResultSetConcurrency() != getResultSetConcurrency()) {
158: return false;
159: }
160: } catch (SQLException e) {
161: logger.warn("Cannot compare statements", e);
162: return false;
163: }
164: logger.debug("Found");
165: return true;
166: }
167:
168: /**
169: * Force a close on the Prepare Statement. Usually, it's the caller that did
170: * not close it explicitly
171: * @return true if it was open
172: */
173: public boolean forceClose() {
174: if (opened) {
175: logger.debug("Statements should be closed explicitly.");
176: opened = false;
177: return true;
178: }
179: return false;
180: }
181:
182: /**
183: * Reuses this statement so reset properties.
184: * @throws SQLException if reset fails
185: */
186: public void reuse() throws SQLException {
187: ps.clearParameters();
188: ps.clearWarnings();
189: opened = true;
190: if (changed) {
191: logger
192: .debug("Properties statement have been changed, reset default properties");
193: ps.clearBatch();
194: ps.setFetchDirection(ResultSet.FETCH_FORWARD);
195: ps.setMaxFieldSize(0);
196: ps.setMaxRows(0);
197: ps.setQueryTimeout(0);
198: changed = false;
199: }
200: }
201:
202: /**
203: * @return true if this statement has been closed, else false.
204: */
205: public boolean isClosed() {
206: return !opened && !closing;
207: }
208:
209: /**
210: * Physically close this Statement.
211: * @throws SQLException
212: */
213: public void forget() {
214: try {
215: ps.close();
216: } catch (SQLException e) {
217: logger.error("Cannot close the PreparedStatement", e);
218: }
219: }
220:
221: /**
222: * {@inheritDoc}
223: */
224: public int executeUpdate() throws SQLException {
225: return ps.executeUpdate();
226: }
227:
228: /**
229: * {@inheritDoc}
230: */
231: public void addBatch() throws SQLException {
232: changed = true;
233: ps.addBatch();
234: }
235:
236: /**
237: * {@inheritDoc}
238: */
239: public void clearParameters() throws SQLException {
240: ps.clearParameters();
241: }
242:
243: /**
244: * {@inheritDoc}
245: */
246: public boolean execute() throws SQLException {
247: return ps.execute();
248: }
249:
250: /**
251: * {@inheritDoc}
252: */
253: public void setByte(final int parameterIndex, final byte x)
254: throws SQLException {
255: ps.setByte(parameterIndex, x);
256: }
257:
258: /**
259: * {@inheritDoc}
260: */
261: public void setDouble(final int parameterIndex, final double x)
262: throws SQLException {
263: ps.setDouble(parameterIndex, x);
264: }
265:
266: /**
267: * {@inheritDoc}
268: */
269: public void setFloat(final int parameterIndex, final float x)
270: throws SQLException {
271: ps.setFloat(parameterIndex, x);
272: }
273:
274: /**
275: * {@inheritDoc}
276: */
277: public void setInt(final int parameterIndex, final int x)
278: throws SQLException {
279: ps.setInt(parameterIndex, x);
280: }
281:
282: /**
283: * {@inheritDoc}
284: */
285: public void setNull(final int parameterIndex, final int sqlType)
286: throws SQLException {
287: ps.setNull(parameterIndex, sqlType);
288: }
289:
290: /**
291: * {@inheritDoc}
292: */
293: public void setLong(final int parameterIndex, final long x)
294: throws SQLException {
295: ps.setLong(parameterIndex, x);
296: }
297:
298: /**
299: * {@inheritDoc}
300: */
301: public void setShort(final int parameterIndex, final short x)
302: throws SQLException {
303: ps.setShort(parameterIndex, x);
304: }
305:
306: /**
307: * {@inheritDoc}
308: */
309: public void setBoolean(final int parameterIndex, final boolean x)
310: throws SQLException {
311: ps.setBoolean(parameterIndex, x);
312: }
313:
314: /**
315: * {@inheritDoc}
316: */
317: public void setBytes(final int parameterIndex, final byte[] x)
318: throws SQLException {
319: ps.setBytes(parameterIndex, x);
320: }
321:
322: /**
323: * {@inheritDoc}
324: */
325: public void setAsciiStream(final int parameterIndex,
326: final InputStream x, final int length) throws SQLException {
327: ps.setAsciiStream(parameterIndex, x, length);
328: }
329:
330: /**
331: * {@inheritDoc}
332: */
333: public void setBinaryStream(final int parameterIndex,
334: final InputStream x, final int length) throws SQLException {
335: ps.setBinaryStream(parameterIndex, x, length);
336: }
337:
338: /**
339: * {@inheritDoc}
340: */
341: @SuppressWarnings("deprecation")
342: public void setUnicodeStream(final int parameterIndex,
343: final InputStream x, final int length) throws SQLException {
344: ps.setUnicodeStream(parameterIndex, x, length);
345: }
346:
347: /**
348: * {@inheritDoc}
349: */
350: public void setCharacterStream(final int parameterIndex,
351: final Reader reader, final int length) throws SQLException {
352: ps.setCharacterStream(parameterIndex, reader, length);
353: }
354:
355: /**
356: * {@inheritDoc}
357: */
358: public void setObject(final int parameterIndex, final Object x)
359: throws SQLException {
360: ps.setObject(parameterIndex, x);
361: }
362:
363: /**
364: * {@inheritDoc}
365: */
366: public void setObject(final int parameterIndex, final Object x,
367: final int targetSqlType) throws SQLException {
368: ps.setObject(parameterIndex, x, targetSqlType);
369: }
370:
371: /**
372: * {@inheritDoc}
373: */
374: public void setObject(final int parameterIndex, final Object x,
375: final int targetSqlType, final int scale)
376: throws SQLException {
377: ps.setObject(parameterIndex, x, targetSqlType, scale);
378: }
379:
380: /**
381: * {@inheritDoc}
382: */
383: public void setNull(final int paramIndex, final int sqlType,
384: final String typeName) throws SQLException {
385: ps.setNull(paramIndex, sqlType, typeName);
386: }
387:
388: /**
389: * {@inheritDoc}
390: */
391: public void setString(final int parameterIndex, final String x)
392: throws SQLException {
393: ps.setString(parameterIndex, x);
394: }
395:
396: /**
397: * {@inheritDoc}
398: */
399: public void setBigDecimal(final int parameterIndex,
400: final BigDecimal x) throws SQLException {
401: ps.setBigDecimal(parameterIndex, x);
402: }
403:
404: /**
405: * {@inheritDoc}
406: */
407: public void setURL(final int parameterIndex, final URL x)
408: throws SQLException {
409: ps.setURL(parameterIndex, x);
410: }
411:
412: /**
413: * {@inheritDoc}
414: */
415: public void setArray(final int i, final Array x)
416: throws SQLException {
417: ps.setArray(i, x);
418: }
419:
420: /**
421: * {@inheritDoc}
422: */
423: public void setBlob(final int i, final Blob x) throws SQLException {
424: ps.setBlob(i, x);
425: }
426:
427: /**
428: * {@inheritDoc}
429: */
430: public void setClob(final int i, final Clob x) throws SQLException {
431: ps.setClob(i, x);
432: }
433:
434: /**
435: * {@inheritDoc}
436: */
437: public void setDate(final int parameterIndex, final Date x)
438: throws SQLException {
439: ps.setDate(parameterIndex, x);
440: }
441:
442: /**
443: * {@inheritDoc}
444: */
445: public ParameterMetaData getParameterMetaData() throws SQLException {
446: return ps.getParameterMetaData();
447: }
448:
449: /**
450: * {@inheritDoc}
451: */
452: public void setRef(final int i, final Ref x) throws SQLException {
453: ps.setRef(i, x);
454: }
455:
456: /**
457: * {@inheritDoc}
458: */
459: public ResultSet executeQuery() throws SQLException {
460: return ps.executeQuery();
461: }
462:
463: /**
464: * {@inheritDoc}
465: */
466: public ResultSetMetaData getMetaData() throws SQLException {
467: return ps.getMetaData();
468: }
469:
470: /**
471: * {@inheritDoc}
472: */
473: public void setTime(final int parameterIndex, final Time x)
474: throws SQLException {
475: ps.setTime(parameterIndex, x);
476: }
477:
478: /**
479: * {@inheritDoc}
480: */
481: public void setTimestamp(final int parameterIndex, final Timestamp x)
482: throws SQLException {
483: ps.setTimestamp(parameterIndex, x);
484: }
485:
486: /**
487: * {@inheritDoc}
488: */
489: public void setDate(final int parameterIndex, final Date x,
490: final Calendar cal) throws SQLException {
491: ps.setDate(parameterIndex, x, cal);
492: }
493:
494: /**
495: * {@inheritDoc}
496: */
497: public void setTime(final int parameterIndex, final Time x,
498: final Calendar cal) throws SQLException {
499: ps.setTime(parameterIndex, x, cal);
500: }
501:
502: /**
503: * {@inheritDoc}
504: */
505: public void setTimestamp(final int parameterIndex,
506: final Timestamp x, final Calendar cal) throws SQLException {
507: ps.setTimestamp(parameterIndex, x, cal);
508: }
509:
510: /**
511: * {@inheritDoc}
512: */
513: public int getFetchDirection() throws SQLException {
514: return ps.getFetchDirection();
515: }
516:
517: /**
518: * {@inheritDoc}
519: */
520: public int getFetchSize() throws SQLException {
521: return ps.getFetchSize();
522: }
523:
524: /**
525: * {@inheritDoc}
526: */
527: public int getMaxFieldSize() throws SQLException {
528: return ps.getMaxFieldSize();
529: }
530:
531: /**
532: * {@inheritDoc}
533: */
534: public int getMaxRows() throws SQLException {
535: return ps.getMaxRows();
536: }
537:
538: /**
539: * {@inheritDoc}
540: */
541: public int getQueryTimeout() throws SQLException {
542: return ps.getQueryTimeout();
543: }
544:
545: /**
546: * {@inheritDoc}
547: */
548: public int getResultSetConcurrency() throws SQLException {
549: return ps.getResultSetConcurrency();
550: }
551:
552: /**
553: * {@inheritDoc}
554: */
555: public int getResultSetHoldability() throws SQLException {
556: return ps.getResultSetHoldability();
557: }
558:
559: /**
560: * {@inheritDoc}
561: */
562: public int getResultSetType() throws SQLException {
563: return ps.getResultSetType();
564: }
565:
566: /**
567: * {@inheritDoc}
568: */
569: public int getUpdateCount() throws SQLException {
570: return ps.getUpdateCount();
571: }
572:
573: /**
574: * {@inheritDoc}
575: */
576: public void cancel() throws SQLException {
577: ps.cancel();
578: }
579:
580: /**
581: * {@inheritDoc}
582: */
583: public void clearBatch() throws SQLException {
584: ps.clearBatch();
585: }
586:
587: /**
588: * {@inheritDoc}
589: */
590: public void clearWarnings() throws SQLException {
591: ps.clearWarnings();
592: }
593:
594: /**
595: * {@inheritDoc}
596: */
597: public void close() throws SQLException {
598: if (!opened) {
599: logger.debug("Statement already closed");
600: return;
601: }
602: opened = false;
603: closing = true;
604: mc.notifyPsClose(this );
605: closing = false;
606: }
607:
608: /**
609: * {@inheritDoc}
610: */
611: public boolean getMoreResults() throws SQLException {
612: return ps.getMoreResults();
613: }
614:
615: /**
616: * {@inheritDoc}
617: */
618: public int[] executeBatch() throws SQLException {
619: return ps.executeBatch();
620: }
621:
622: /**
623: * {@inheritDoc}
624: */
625: public void setFetchDirection(final int direction)
626: throws SQLException {
627: changed = true;
628: ps.setFetchDirection(direction);
629: }
630:
631: /**
632: * {@inheritDoc}
633: */
634: public void setFetchSize(final int rows) throws SQLException {
635: changed = true;
636: ps.setFetchSize(rows);
637: }
638:
639: /**
640: * {@inheritDoc}
641: */
642: public void setMaxFieldSize(final int max) throws SQLException {
643: changed = true;
644: ps.setMaxFieldSize(max);
645: }
646:
647: /**
648: * {@inheritDoc}
649: */
650: public void setMaxRows(final int max) throws SQLException {
651: changed = true;
652: ps.setMaxRows(max);
653: }
654:
655: /**
656: * {@inheritDoc}
657: */
658: public void setQueryTimeout(final int seconds) throws SQLException {
659: changed = true;
660: ps.setQueryTimeout(seconds);
661: }
662:
663: /**
664: * {@inheritDoc}
665: */
666: public boolean getMoreResults(final int current)
667: throws SQLException {
668: return ps.getMoreResults(current);
669: }
670:
671: /**
672: * {@inheritDoc}
673: */
674: public void setEscapeProcessing(final boolean enable)
675: throws SQLException {
676: ps.setEscapeProcessing(enable);
677: }
678:
679: /**
680: * {@inheritDoc}
681: */
682: public int executeUpdate(final String sql) throws SQLException {
683: return ps.executeUpdate(sql);
684: }
685:
686: /**
687: * {@inheritDoc}
688: */
689: public void addBatch(final String sql) throws SQLException {
690: changed = true;
691: ps.addBatch(sql);
692: }
693:
694: /**
695: * {@inheritDoc}
696: */
697: public void setCursorName(final String name) throws SQLException {
698: ps.setCursorName(name);
699: }
700:
701: /**
702: * {@inheritDoc}
703: */
704: public boolean execute(final String sql) throws SQLException {
705: changed = true;
706: return ps.execute(sql);
707: }
708:
709: /**
710: * {@inheritDoc}
711: */
712: public int executeUpdate(final String sql,
713: final int autoGeneratedKeys) throws SQLException {
714: changed = true;
715: return ps.executeUpdate(sql, autoGeneratedKeys);
716: }
717:
718: /**
719: * {@inheritDoc}
720: */
721: public boolean execute(final String sql, final int autoGeneratedKeys)
722: throws SQLException {
723: changed = true;
724: return ps.execute(sql, autoGeneratedKeys);
725: }
726:
727: /**
728: * {@inheritDoc}
729: */
730: public int executeUpdate(final String sql, final int[] columnIndexes)
731: throws SQLException {
732: changed = true;
733: return ps.executeUpdate(sql, columnIndexes);
734: }
735:
736: /**
737: * {@inheritDoc}
738: */
739: public boolean execute(final String sql, final int[] columnIndexes)
740: throws SQLException {
741: changed = true;
742: return ps.execute(sql, columnIndexes);
743: }
744:
745: /**
746: * {@inheritDoc}
747: */
748: public Connection getConnection() throws SQLException {
749: return ps.getConnection();
750: }
751:
752: /**
753: * {@inheritDoc}
754: */
755: public ResultSet getGeneratedKeys() throws SQLException {
756: return ps.getGeneratedKeys();
757: }
758:
759: /**
760: * {@inheritDoc}
761: */
762: public ResultSet getResultSet() throws SQLException {
763: return ps.getResultSet();
764: }
765:
766: /**
767: * {@inheritDoc}
768: */
769: public SQLWarning getWarnings() throws SQLException {
770: return ps.getWarnings();
771: }
772:
773: /**
774: * {@inheritDoc}
775: */
776: public int executeUpdate(final String sql,
777: final String[] columnNames) throws SQLException {
778: return ps.executeUpdate(sql, columnNames);
779: }
780:
781: /**
782: * {@inheritDoc}
783: */
784: public boolean execute(final String sql, final String[] columnNames)
785: throws SQLException {
786: return ps.execute(sql, columnNames);
787: }
788:
789: /**
790: * {@inheritDoc}
791: */
792: public ResultSet executeQuery(final String sql) throws SQLException {
793: return ps.executeQuery(sql);
794: }
795:
796: }
|