KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > sql > UserConnection


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.sql;
31
32 import com.caucho.log.Log;
33 import com.caucho.util.L10N;
34
35 import java.sql.*;
36 import java.util.ArrayList JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.logging.Level JavaDoc;
39 import java.util.logging.Logger JavaDoc;
40
41 /**
42  * Adapts the JDBC 2.0 connection pooling and XA support for database drivers
43  * which don't understand it.
44  *
45  * <p>Closing the connection will return the real connection to the pool
46  * and close any statements.
47  */

48 public class UserConnection implements java.sql.Connection JavaDoc {
49   protected static final Logger JavaDoc log = Log.open(UserConnection.class);
50   protected static final L10N L = new L10N(UserConnection.class);
51
52   // The parent XAConnectionAdapter
53
private ManagedConnectionImpl _mConn;
54
55   // Maximum statements saved for automatic closing
56

57   private Statement _statement;
58   // ArrayList of all the statements created by this connection
59
private ArrayList JavaDoc<Statement> _statements;
60
61   /**
62    * Creates a new PooledConnection.
63    *
64    * @param pool the pool the connection belongs to.
65    * @param conn the underlying connection.
66    */

67   UserConnection(ManagedConnectionImpl mConn)
68   {
69     if (mConn == null || mConn.getDriverConnection() == null)
70       throw new NullPointerException JavaDoc();
71
72     _mConn = mConn;
73   }
74
75   /**
76    * Returns the underlying connection.
77    */

78   public Connection getConnection()
79     throws SQLException
80   {
81     Connection conn = getDriverConnection();
82
83     if (conn instanceof com.caucho.sql.spy.SpyConnection)
84       conn = ((com.caucho.sql.spy.SpyConnection)conn).getConnection();
85
86     return conn;
87   }
88
89   public String JavaDoc getURL()
90   {
91     return getMConn().getDBPool().getURL();
92   }
93
94   /**
95    * Associates with a different mConn.
96    */

97   void associate(ManagedConnectionImpl mConn)
98   {
99     _mConn = mConn;
100   }
101
102   /**
103    * JDBC api to create a new statement. Any SQL exception thrown here
104    * will make the connection invalid, i.e. it can't be put back into
105    * the pool.
106    *
107    * @return a new JDBC statement.
108    */

109   public Statement createStatement()
110     throws SQLException
111   {
112     Statement stmt;
113
114     Connection conn = getDriverConnection();
115
116     try {
117       stmt = conn.createStatement();
118     } catch (SQLException e) {
119       fatalEvent();
120       throw e;
121     }
122
123     addStatement(stmt);
124
125     if (_mConn.isWrapStatements())
126       return new UserStatement(this, stmt);
127     else
128       return stmt;
129   }
130
131   /**
132    * JDBC api to create a new statement. Any SQL exception thrown here
133    * will make the connection invalid, i.e. it can't be put back into
134    * the pool.
135    *
136    * @return a new JDBC statement.
137    */

138   public Statement createStatement(int resultSetType, int resultSetConcurrency)
139     throws SQLException
140   {
141     Statement stmt;
142
143     Connection conn = getDriverConnection();
144
145     try {
146       stmt = conn.createStatement(resultSetType, resultSetConcurrency);
147     } catch (SQLException e) {
148       fatalEvent();
149       throw e;
150     }
151
152     addStatement(stmt);
153
154     if (_mConn.isWrapStatements())
155       return new UserStatement(this, stmt);
156     else
157       return stmt;
158   }
159
160   /**
161    * Creates a statement.
162    */

163   public Statement createStatement(int resultSetType,
164                                    int resultSetConcurrency,
165                                    int resultSetHoldability)
166     throws SQLException
167   {
168     Statement stmt;
169
170     Connection conn = getDriverConnection();
171
172     try {
173       stmt = conn.createStatement(resultSetType,
174                                   resultSetConcurrency,
175                                   resultSetHoldability);
176     } catch (SQLException e) {
177       fatalEvent();
178       throw e;
179     }
180
181     addStatement(stmt);
182
183     if (_mConn.isWrapStatements())
184       return new UserStatement(this, stmt);
185     else
186       return stmt;
187   }
188
189   /**
190    * Returns a prepared statement with the given sql.
191    *
192    * @param sql the prepared sql.
193    */

194   public PreparedStatement prepareStatement(String JavaDoc sql)
195     throws SQLException
196   {
197     PreparedStatement stmt;
198
199     if (getDriverConnection() == null) {
200       fatalEvent();
201       throw new SQLException(L.l("can't create statement from closed connection."));
202     }
203
204     try {
205       stmt = getMConn().prepareStatement(this, sql);
206     } catch (SQLException e) {
207       getMConn().fatalEvent(e);
208       throw e;
209     }
210
211     addStatement(stmt);
212
213     if (_mConn.isWrapStatements())
214       return new UserPreparedStatement(this, stmt);
215     else
216       return stmt;
217   }
218
219   /**
220    * Returns a prepared statement with the given sql.
221    *
222    * @param sql the prepared sql.
223    */

224   public PreparedStatement prepareStatement(String JavaDoc sql,
225                                             int resultSetType,
226                                             int resultSetConcurrency)
227     throws SQLException
228   {
229     PreparedStatement stmt;
230
231     if (getDriverConnection() == null) {
232       fatalEvent();
233       throw new SQLException(L.l("can't create statement from closed connection."));
234     }
235
236     try {
237       stmt = getDriverConnection().prepareStatement(sql, resultSetType, resultSetConcurrency);
238     } catch (SQLException e) {
239       fatalEvent();
240       throw e;
241     }
242
243     addStatement(stmt);
244
245     if (_mConn.isWrapStatements())
246       return new UserPreparedStatement(this, stmt);
247     else
248       return stmt;
249   }
250
251   /**
252    * Returns a prepared statement with the given sql.
253    *
254    * @param sql the prepared sql.
255    */

256   public PreparedStatement prepareStatement(String JavaDoc sql,
257                                             int resultSetType,
258                                             int resultSetConcurrency,
259                                             int resultSetHoldability)
260     throws SQLException
261   {
262     PreparedStatement stmt;
263
264     if (getDriverConnection() == null) {
265       fatalEvent();
266       throw new SQLException(L.l("can't create statement from closed connection."));
267     }
268
269     try {
270       stmt = getDriverConnection().prepareStatement(sql,
271                                               resultSetType,
272                                               resultSetConcurrency,
273                                               resultSetHoldability);
274     } catch (SQLException e) {
275       fatalEvent();
276       throw e;
277     }
278
279     addStatement(stmt);
280
281     if (_mConn.isWrapStatements())
282       return new UserPreparedStatement(this, stmt);
283     else
284       return stmt;
285   }
286
287   /**
288    * Returns a prepared statement with the given sql.
289    *
290    * @param sql the prepared sql.
291    */

292   public PreparedStatement prepareStatement(String JavaDoc sql,
293                                             int resultSetType)
294     throws SQLException
295   {
296     PreparedStatement stmt;
297
298     if (getDriverConnection() == null) {
299       fatalEvent();
300       throw new SQLException(L.l("can't create statement from closed connection."));
301     }
302
303     try {
304       stmt = getMConn().prepareStatement(this, sql, resultSetType);
305     } catch (SQLException e) {
306       fatalEvent();
307       throw e;
308     }
309
310     addStatement(stmt);
311
312     if (_mConn.isWrapStatements())
313       return new UserPreparedStatement(this, stmt);
314     else
315       return stmt;
316   }
317
318   /**
319    * Returns a prepared statement with the given sql.
320    *
321    * @param sql the prepared sql.
322    */

323   public PreparedStatement prepareStatement(String JavaDoc sql,
324                                             int []columnIndexes)
325     throws SQLException
326   {
327     PreparedStatement stmt;
328
329     if (getDriverConnection() == null) {
330       fatalEvent();
331       throw new SQLException(L.l("can't create statement from closed connection."));
332     }
333
334     try {
335       stmt = getDriverConnection().prepareStatement(sql, columnIndexes);
336     } catch (SQLException e) {
337       fatalEvent();
338       throw e;
339     }
340
341     addStatement(stmt);
342
343     if (_mConn.isWrapStatements())
344       return new UserPreparedStatement(this, stmt);
345     else
346       return stmt;
347   }
348
349   /**
350    * Returns a prepared statement with the given sql.
351    *
352    * @param sql the prepared sql.
353    */

354   public PreparedStatement prepareStatement(String JavaDoc sql,
355                                             String JavaDoc []columnNames)
356     throws SQLException
357   {
358     PreparedStatement stmt;
359
360     if (getDriverConnection() == null) {
361       fatalEvent();
362       throw new SQLException(L.l("can't create statement from closed connection."));
363     }
364
365     try {
366       stmt = getDriverConnection().prepareStatement(sql, columnNames);
367     } catch (SQLException e) {
368       fatalEvent();
369       throw e;
370     }
371
372     addStatement(stmt);
373
374     if (_mConn.isWrapStatements())
375       return new UserPreparedStatement(this, stmt);
376     else
377       return stmt;
378   }
379
380   public CallableStatement prepareCall(String JavaDoc sql, int resultSetType,
381                int resultSetConcurrency)
382     throws SQLException
383   {
384     CallableStatement stmt;
385
386     if (getDriverConnection() == null) {
387       fatalEvent();
388       throw new SQLException(L.l("can't create statement from closed connection."));
389     }
390
391     try {
392       stmt = getDriverConnection().prepareCall(sql, resultSetType, resultSetConcurrency);
393     } catch (SQLException e) {
394       fatalEvent();
395       throw e;
396     }
397
398     addStatement(stmt);
399
400     if (_mConn.isWrapStatements())
401       return new UserCallableStatement(this, stmt);
402     else
403       return stmt;
404   }
405
406   public CallableStatement prepareCall(String JavaDoc sql)
407     throws SQLException
408   {
409     CallableStatement stmt;
410
411     if (getDriverConnection() == null) {
412       fatalEvent();
413       throw new SQLException(L.l("can't create statement from closed connection."));
414     }
415
416     try {
417       stmt = getDriverConnection().prepareCall(sql);
418     } catch (SQLException e) {
419       fatalEvent();
420       throw e;
421     }
422
423     addStatement(stmt);
424
425     if (_mConn.isWrapStatements())
426       return new UserCallableStatement(this, stmt);
427     else
428       return stmt;
429   }
430
431   public CallableStatement prepareCall(String JavaDoc sql,
432                                        int resultSetType,
433                                        int resultSetConcurrency,
434                                        int resultSetHoldability)
435     throws SQLException
436   {
437     CallableStatement stmt;
438
439     if (getDriverConnection() == null) {
440       fatalEvent();
441       throw new SQLException(L.l("can't create statement from closed connection."));
442     }
443
444     try {
445       stmt = getDriverConnection().prepareCall(sql,
446                                          resultSetType,
447                                          resultSetConcurrency,
448                                          resultSetHoldability);
449     } catch (SQLException e) {
450       fatalEvent();
451       throw e;
452     }
453
454     addStatement(stmt);
455
456     if (_mConn.isWrapStatements())
457       return new UserCallableStatement(this, stmt);
458     else
459       return stmt;
460   }
461
462   /**
463    * JDBC api to return the connection's catalog.
464    *
465    * @return the JDBC catalog.
466    */

467   public String JavaDoc getCatalog()
468     throws SQLException
469   {
470     try {
471       return getDriverConnection().getCatalog();
472     } catch (SQLException e) {
473       fatalEvent();
474       throw e;
475     }
476   }
477
478   /**
479    * Sets the JDBC catalog.
480    */

481   public void setCatalog(String JavaDoc catalog)
482     throws SQLException
483   {
484     getMConn().setCatalog(catalog);
485   }
486
487   /**
488    * Gets the connection's metadata.
489    */

490   public DatabaseMetaData getMetaData()
491     throws SQLException
492   {
493     try {
494       return getDriverConnection().getMetaData();
495     } catch (SQLException e) {
496       fatalEvent();
497       throw e;
498     }
499   }
500
501   /**
502    * Returns the connection's type map.
503    */

504   public Map JavaDoc getTypeMap()
505     throws SQLException
506   {
507     try {
508       return getDriverConnection().getTypeMap();
509     } catch (SQLException e) {
510       fatalEvent();
511       throw e;
512     }
513   }
514
515   /**
516    * Sets the connection's type map.
517    */

518   public void setTypeMap(Map JavaDoc<String JavaDoc,Class JavaDoc<?>> map)
519     throws SQLException
520   {
521     getMConn().setTypeMap(map);
522   }
523
524   /**
525    * Calls the nativeSQL method for the connection.
526    */

527   public String JavaDoc nativeSQL(String JavaDoc sql)
528     throws SQLException
529   {
530     try {
531       return getDriverConnection().nativeSQL(sql);
532     } catch (SQLException e) {
533       fatalEvent();
534       throw e;
535     }
536   }
537
538   public int getTransactionIsolation()
539     throws SQLException
540   {
541     try {
542       return getDriverConnection().getTransactionIsolation();
543     } catch (SQLException e) {
544       fatalEvent();
545       throw e;
546     }
547   }
548
549   public void setTransactionIsolation(int isolation)
550     throws SQLException
551   {
552     getMConn().setTransactionIsolation(isolation);
553   }
554
555   public SQLWarning getWarnings()
556     throws SQLException
557   {
558     try {
559       Connection conn = getDriverConnection();
560
561       if (conn != null)
562         return conn.getWarnings();
563       else
564         return null;
565     } catch (SQLException e) {
566       fatalEvent();
567       throw e;
568     }
569   }
570
571   public void clearWarnings()
572     throws SQLException
573   {
574     try {
575       Connection conn = getDriverConnection();
576
577       if (conn != null)
578         conn.clearWarnings();
579     } catch (SQLException e) {
580       fatalEvent();
581       throw e;
582     }
583   }
584
585   public void setReadOnly(boolean readOnly)
586     throws SQLException
587   {
588     getMConn().setReadOnly(readOnly);
589   }
590
591   public boolean isReadOnly()
592     throws SQLException
593   {
594     try {
595       return getDriverConnection().isReadOnly();
596     } catch (SQLException e) {
597       fatalEvent();
598       throw e;
599     }
600   }
601
602   public boolean getAutoCommit()
603     throws SQLException
604   {
605     try {
606       return getDriverConnection().getAutoCommit();
607     } catch (SQLException e) {
608       fatalEvent();
609       throw e;
610     }
611   }
612
613   public void setAutoCommit(boolean autoCommit)
614     throws SQLException
615   {
616     getMConn().setAutoCommit(autoCommit);
617   }
618
619   public void commit()
620     throws SQLException
621   {
622     try {
623       Connection conn = getDriverConnection();
624
625       if (conn != null)
626         conn.commit();
627     } catch (SQLException e) {
628       fatalEvent();
629       throw e;
630     }
631   }
632
633   public void rollback()
634     throws SQLException
635   {
636     try {
637       Connection conn = getDriverConnection();
638
639       if (conn != null)
640         conn.rollback();
641     } catch (SQLException e) {
642       fatalEvent();
643       throw e;
644     }
645   }
646
647   /**
648    * Returns true if the connection is closed.
649    */

650   public boolean isClosed()
651     throws SQLException
652   {
653     try {
654       return _mConn == null || getDriverConnection() == null || getDriverConnection().isClosed();
655     } catch (SQLException e) {
656       log.log(Level.FINER, e.toString(), e);
657
658       return true;
659     }
660   }
661
662   /**
663    * Reset the connection and return the underlying JDBC connection to
664    * the pool.
665    */

666   public void close() throws SQLException
667   {
668     ManagedConnectionImpl mConn;
669
670     synchronized (this) {
671       mConn = _mConn;
672       _mConn = null;
673
674       if (mConn == null)
675         return;
676     }
677
678     try {
679       // Clean up the connection and put it back in the pool
680
resetConnection(mConn);
681     } catch (Throwable JavaDoc e) {
682       mConn.fatalEvent();
683
684       log.log(Level.WARNING, e.toString(), e);
685       /*
686       if (e instanceof SQLException)
687         throw (SQLException) e;
688       else if (e instanceof RuntimeException)
689         throw (RuntimeException) e;
690       else
691         throw new SQLExceptionWrapper(e);
692       */

693     } finally {
694       mConn.closeEvent(this);
695     }
696   }
697
698   /**
699    * Adds the statement to a list, so they can be automatically closed
700    * when the connection returns to the pool.
701    */

702   private void addStatement(Statement stmt)
703   {
704     if (_statement == null)
705       _statement = stmt;
706     else if (_statements != null)
707       _statements.add(stmt);
708     else {
709       _statements = new ArrayList JavaDoc<Statement>();
710       _statements.add(stmt);
711     }
712   }
713
714   public void setHoldability(int hold)
715     throws SQLException
716   {
717     getDriverConnection().setHoldability(hold);
718   }
719
720   public int getHoldability()
721     throws SQLException
722   {
723     return getDriverConnection().getHoldability();
724   }
725
726   public Savepoint setSavepoint()
727     throws SQLException
728   {
729     return getDriverConnection().setSavepoint();
730   }
731
732   public Savepoint setSavepoint(String JavaDoc name)
733     throws SQLException
734   {
735     return getDriverConnection().setSavepoint(name);
736   }
737
738   public void releaseSavepoint(Savepoint savepoint)
739     throws SQLException
740   {
741     getDriverConnection().releaseSavepoint(savepoint);
742   }
743
744   public void rollback(Savepoint savepoint)
745     throws SQLException
746   {
747     getDriverConnection().rollback(savepoint);
748   }
749
750   /**
751    * Resets the underlying connection to its initial state and closes
752    * any open statements.
753    */

754   private void resetConnection(ManagedConnectionImpl mConn)
755   {
756     closeStatements(mConn);
757   }
758
759   /**
760    * Closes a single statement.
761    */

762   void closeStatement(Statement stmt)
763   {
764     if (_statement == stmt)
765       _statement = null;
766     else if (_statements != null)
767       _statements.remove(stmt);
768   }
769
770   /**
771    * Closes the connection's statements.
772    */

773   private void closeStatements(ManagedConnectionImpl mConn)
774   {
775     ArrayList JavaDoc<Statement> statements = _statements;
776     _statements = null;
777
778     Statement stmt = _statement;
779     _statement = null;
780
781     try {
782       if (stmt != null)
783         stmt.close();
784     } catch (Throwable JavaDoc e) {
785       log.log(Level.FINE, e.toString(), e);
786
787       // Can't set fatalEvent because Sybase throws an exception
788
// if statements are closed twice
789
// fatalEvent();
790
}
791
792     for (int i = 0; statements != null && i < statements.size(); i++) {
793       try {
794         stmt = statements.get(i);
795
796         if (stmt != null)
797           stmt.close();
798       } catch (Throwable JavaDoc e) {
799         log.log(Level.FINE, e.toString(), e);
800
801         // Can't set fatalEvent because Sybase throws an exception
802
// if statements are closed twice
803
// fatalEvent();
804
}
805     }
806   }
807
808   /**
809    * Returns the underlying connection.
810    */

811   public Connection getDriverConnection()
812     throws SQLException
813   {
814     ManagedConnectionImpl mConn = getMConn();
815
816     if (mConn == null)
817       throw new IllegalStateException JavaDoc(L.l("Cannot use closed connection. Check max-active-time and review application code. "));
818
819     Connection conn = mConn.getDriverConnection();
820
821     return conn;
822   }
823
824   /**
825    * Returns the underlying connection.
826    */

827   private ManagedConnectionImpl getMConn()
828   {
829     ManagedConnectionImpl mConn = _mConn;
830
831     if (mConn == null)
832       throw new IllegalStateException JavaDoc("connection is closed");
833
834     return mConn;
835   }
836
837   /**
838    * Marks the connection as error.
839    */

840   public void discardConnection()
841   {
842     fatalEvent();
843   }
844
845   /**
846    * Returns the underlying connection.
847    */

848   private void fatalEvent()
849   {
850     ManagedConnectionImpl mConn = _mConn;
851
852     if (mConn != null)
853       mConn.fatalEvent();
854   }
855
856   /**
857    * Returns the underlying connection.
858    */

859   private void fatalEvent(SQLException exn)
860   {
861     ManagedConnectionImpl mConn = _mConn;
862
863     if (mConn != null)
864       mConn.fatalEvent(exn);
865   }
866
867   protected void finalize()
868   {
869     try {
870       close();
871     } catch (Throwable JavaDoc e) {
872     }
873   }
874
875   public String JavaDoc toString()
876   {
877     return "UserConnection[" + _mConn + "]";
878   }
879 }
880
Popular Tags