KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > spi > persistence > support > sqlstore > connection > ConnectionImpl


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * ConnectionImpl.java
26  *
27  * Create on March 3, 2000
28  */

29
30 package com.sun.jdo.spi.persistence.support.sqlstore.connection;
31
32 import com.sun.jdo.api.persistence.support.JDODataStoreException;
33 import com.sun.jdo.api.persistence.support.Transaction;
34 import com.sun.jdo.spi.persistence.support.sqlstore.ejb.EJBHelper;
35 import com.sun.jdo.spi.persistence.utility.Linkable;
36 import com.sun.jdo.spi.persistence.utility.logging.Logger;
37 import com.sun.jdo.spi.persistence.support.sqlstore.LogHelperSQLStore;
38
39
40 import java.sql.*;
41
42 /**
43  * This class implements the <code>java.sql.Connection</code>
44  * interface, which is part of the JDBC API. You should use
45  * the <code>java.sql.Connection</code> interface as an object
46  * type instead of this class.
47  */

48 public class ConnectionImpl implements Connection, Linkable {
49     /*
50      * The associated JDBC Connection.
51      */

52     private Connection connection;
53
54     /*
55      * The datasource url; e.g. "jdbc:oracle:oci7:@ABYSS_ORACLE".
56      */

57     private String JavaDoc url;
58
59     /*
60      * User name.
61      */

62     private String JavaDoc userName;
63
64     /*
65      * Previous ConnectionImpl in a chain.
66      */

67     Linkable previous;
68
69     /*
70      * Next ConnectionImpl in a chain.
71      */

72     Linkable next;
73
74     /*
75      * Indicates whether this ConnectionImpl is pooled.
76      */

77     private boolean pooled;
78
79     /*
80      * The Transaction object for the associated transaction.
81      */

82     private Transaction transaction;
83
84     /*
85      * Indicates whether this ConnectionImpl is to be freed on
86      * transaction termination.
87      */

88     boolean freePending;
89
90     /*
91      * The resource interface that is registered with a transaction
92      * object.
93      */

94     // private ForteJDBCResource resource;
95

96     /*
97      * The parent ConnectionManager object.
98      */

99     ConnectionManager connectionManager;
100     
101     /**
102      * The logger
103      */

104     private static Logger logger = LogHelperSQLStore.getLogger();
105
106
107     /**
108      * Create a new ConnectionImpl object and keep a reference to
109      * the corresponding JDBC Connection.
110      *
111      * @param conn Connection
112      */

113     public ConnectionImpl(Connection conn, String JavaDoc url, String JavaDoc userName,
114                           ConnectionManager connMgr) {
115         super();
116         this.connection = conn;
117         this.url = url;
118         this.userName = userName;
119         this.previous = null;
120         this.next = null;
121         this.pooled = false;
122         this.transaction = null;
123         this.freePending = false;
124         // this.resource = null;
125
this.connectionManager = connMgr;
126     }
127
128     //----------------------------------------------------------------------
129
// Wrapper methods for JDBC Connection:
130

131     //
132
// Create a JDBC Statement to execute SQL statements without parameters.
133
// <p>
134
// @return A StatementImpl wrapper object.
135
// @exception SQLException if a database error occurs.
136
//
137
public synchronized Statement createStatement()
138             throws SQLException {
139         StatementImpl fstmt;
140
141         try {
142             this.checkXact();
143             fstmt = new StatementImpl(this, this.connection.createStatement());
144         } catch (SQLException se) {
145             throw se;
146         }
147
148         return ((Statement) fstmt);
149     }
150
151     public Statement createStatement(int resultSetType,
152                                      int resultSetConcurrency)
153             throws SQLException {
154         return (null);
155     }
156
157     public PreparedStatement prepareStatement(String JavaDoc sql, int resultSetType,
158                                               int resultSetConcurrency)
159             throws SQLException {
160         return (null);
161     }
162
163     public CallableStatement prepareCall(String JavaDoc sql,
164                                          int resultSetType,
165                                          int resultSetConcurrency)
166             throws SQLException {
167         return (null);
168     }
169
170     //
171
// Prepare a SQL statement, with or without parameters, that can be
172
// efficiently executed multiple times.
173
// <p>
174
// @param sql SQL statement.
175
// @return A StatementImpl wrapper object.
176
// @exception SQLException if a database error occurs.
177
//
178
public synchronized PreparedStatement prepareStatement(String JavaDoc sql)
179             throws SQLException {
180         PreparedStatementImpl fpstmt;
181
182         try {
183             this.checkXact();
184             fpstmt = new PreparedStatementImpl(this,
185                     this.connection.prepareStatement(sql));
186         } catch (SQLException se) {
187             throw se;
188         }
189
190         return ((PreparedStatement) fpstmt);
191     }
192
193     //
194
// Prepare a SQL stored procedure call.
195
// <p>
196
// @parameter sql SQL stored procedure call.
197
// @return a ForteCallableStatement wrapper object.
198
// @exception SQLException if a database error occurs.
199
//
200
public synchronized CallableStatement prepareCall(String JavaDoc sql)
201             throws SQLException {
202         CallableStatementImpl fcstmt;
203
204         try {
205             this.checkXact();
206             fcstmt = new CallableStatementImpl(this,
207                     this.connection.prepareCall(sql));
208             return ((CallableStatement) fcstmt);
209         } catch (SQLException se) {
210             throw se;
211         }
212     }
213
214     public synchronized String JavaDoc nativeSQL(String JavaDoc sql) throws SQLException {
215         try {
216             return (this.connection.nativeSQL(sql));
217         } catch (SQLException se) {
218             throw se;
219         }
220     }
221
222     public synchronized void setAutoCommit(boolean autoCommit)
223             throws SQLException {
224         try {
225             this.connection.setAutoCommit(autoCommit);
226         } catch (SQLException se) {
227             throw se;
228         }
229     }
230
231     public synchronized boolean getAutoCommit() throws SQLException {
232         try {
233             return (this.connection.getAutoCommit());
234         } catch (SQLException se) {
235             throw se;
236         }
237     }
238
239     public synchronized void commit() throws SQLException {
240
241         try {
242             this.connection.commit();
243             if (this.freePending) {
244                 if (this.connectionManager.shutDownPending) {
245                     try {
246                         this.connection.close();
247                         logger.finest("sqlstore.connectionimpl.commit"); // NOI18N
248
} catch (SQLException se) {
249                         ;
250                     }
251                 } else {
252                     this.freePending = false;
253                     this.connectionManager.freeList.insertAtTail(this);
254                 }
255             }
256             if (EJBHelper.isManaged()) {
257                 // this is for use with test 'ejb' only.
258
closeInternal();
259             }
260         } catch (SQLException se) {
261             throw se;
262         }
263     }
264
265     public synchronized void rollback() throws SQLException {
266         logger.finest("sqlstore.connectionimpl.rollback"); // NOI18N
267

268         try {
269             this.connection.rollback();
270             if (this.freePending) {
271                 if (this.connectionManager.shutDownPending) {
272                     this.connection.close();
273                     logger.finest("sqlstore.connectionimpl.rollback.close"); // NOI18N
274
} else {
275                     this.freePending = false;
276                     this.connectionManager.freeList.insertAtTail(this);
277                 }
278             }
279             if (EJBHelper.isManaged()) {
280                 // this is for use with test 'ejb' only.
281
closeInternal();
282             }
283         } catch (SQLException se) {
284             throw se;
285         }
286     }
287
288     public synchronized void close() throws SQLException {
289         if (EJBHelper.isManaged()) {
290             logger.finest("sqlstore.connectionimpl.close"); // NOI18N
291

292             // ignore - this can happen in test 'ejb' only
293
return;
294         }
295
296         closeInternal();
297     }
298
299     private synchronized void closeInternal() throws SQLException {
300
301         boolean debug = logger.isLoggable(Logger.FINEST);
302
303         ConnectionImpl conn = (ConnectionImpl) this;
304
305         if (debug) {
306             logger.finest("sqlstore.connectionimpl.close_arg",conn); // NOI18N
307
}
308
309         try {
310             conn.connectionManager.busyList.removeFromList((Linkable) conn);
311             if (conn.xactPending() == true) {
312                 conn.setFreePending(true);
313                 if (debug) {
314                     logger.finest("sqlstore.connectionimpl.close.freepending"); // NOI18N
315
}
316             } else if ((conn.getPooled() == true) && (conn.connectionManager.shutDownPending == false)) {
317                 conn.connectionManager.freeList.insertAtTail((Linkable) conn);
318                 if (debug) {
319                     logger.finest("sqlstore.connectionimpl.close.putfreelist"); // NOI18N
320
}
321             } else {
322                 if (EJBHelper.isManaged()) {
323                     // RESOLVE: do we need it here?
324
this.connection.close();
325                     if (debug) {
326                         logger.finest("sqlstore.connectionimpl.close.exit"); // NOI18N
327
}
328                 } else {
329                     // Save reference to this connection and close it only when
330
// another free becomes available. This reduces time to
331
// get a new connection.
332
this.connectionManager.replaceFreeConnection(this);
333                     if (debug) {
334                         logger.finest("sqlstore.connectionimpl.close.replaced"); // NOI18N
335
}
336                 }
337             }
338
339         } catch (SQLException se) {
340             throw se;
341         }
342     }
343
344     /**
345      * Called by ConnectionManager to close old connection when a new free connection
346      * becomes available
347      */

348     protected void release() {
349         try {
350             this.connection.close();
351         } catch (SQLException se) {
352             // ignore
353
}
354         logger.finest("sqlstore.connectionimpl.close.connrelease"); // NOI18N
355
}
356
357     public synchronized boolean isClosed() throws SQLException {
358         try {
359             return (this.connection.isClosed());
360         } catch (SQLException se) {
361             throw se;
362         }
363     }
364
365     public synchronized DatabaseMetaData getMetaData() throws SQLException {
366         try {
367             return (this.connection.getMetaData());
368         } catch (SQLException se) {
369             throw se;
370         }
371     }
372
373     public synchronized void setReadOnly(boolean readOnly) throws SQLException {
374         try {
375             this.connection.setReadOnly(readOnly);
376         } catch (SQLException se) {
377             throw se;
378         }
379     }
380
381     public synchronized boolean isReadOnly() throws SQLException {
382         try {
383             return (this.connection.isReadOnly());
384         } catch (SQLException se) {
385             throw se;
386         }
387     }
388
389     public synchronized void setCatalog(String JavaDoc catalog) throws SQLException {
390         try {
391             this.connection.setCatalog(catalog);
392         } catch (SQLException se) {
393             throw se;
394         }
395     }
396
397     public synchronized String JavaDoc getCatalog() throws SQLException {
398         try {
399             return (this.connection.getCatalog());
400         } catch (SQLException se) {
401             throw se;
402         }
403     }
404
405     public synchronized void setTransactionIsolation(int level)
406             throws SQLException {
407         try {
408             this.connection.setTransactionIsolation(level);
409         } catch (SQLException se) {
410             throw se;
411         }
412     }
413
414     public synchronized int getTransactionIsolation() throws SQLException {
415         try {
416             return (this.connection.getTransactionIsolation());
417         } catch (SQLException se) {
418             throw se;
419         }
420     }
421
422     public synchronized SQLWarning getWarnings() throws SQLException {
423         try {
424             return (this.connection.getWarnings());
425         } catch (SQLException se) {
426             throw se;
427         }
428     }
429
430     public synchronized void clearWarnings() throws SQLException {
431         try {
432             this.connection.clearWarnings();
433         } catch (SQLException se) {
434             throw se;
435         }
436     }
437
438     public synchronized java.util.Map JavaDoc getTypeMap()
439             throws SQLException {
440         try {
441             return (this.connection.getTypeMap());
442         } catch (SQLException se) {
443             throw se;
444         }
445     }
446
447     public synchronized void setTypeMap(java.util.Map JavaDoc map)
448             throws SQLException {
449         try {
450             this.connection.setTypeMap(map);
451         } catch (SQLException se) {
452             throw se;
453         }
454     }
455
456     //-------------Begin New methods added in JDBC 3.0 --------------
457

458     public synchronized void setHoldability(int holdability)
459                     throws SQLException {
460
461         throw new UnsupportedOperationException JavaDoc();
462     }
463
464     public synchronized int getHoldability()
465                     throws SQLException {
466
467         throw new UnsupportedOperationException JavaDoc();
468     }
469
470     public synchronized Savepoint setSavepoint()
471                        throws SQLException {
472
473         throw new UnsupportedOperationException JavaDoc();
474     }
475
476     public synchronized Savepoint setSavepoint(String JavaDoc name)
477                        throws SQLException {
478
479         throw new UnsupportedOperationException JavaDoc();
480     }
481
482     public synchronized void rollback(Savepoint savepoint)
483               throws SQLException {
484
485        throw new UnsupportedOperationException JavaDoc();
486
487     }
488
489     public synchronized void releaseSavepoint(Savepoint savepoint)
490                       throws SQLException {
491
492        throw new UnsupportedOperationException JavaDoc();
493     }
494
495     public synchronized Statement createStatement(int resultSetType,
496                                  int resultSetConcurrency,
497                                  int resultSetHoldability)
498                           throws SQLException {
499
500         throw new UnsupportedOperationException JavaDoc();
501     }
502
503     public synchronized PreparedStatement prepareStatement(String JavaDoc sql,
504                                           int resultSetType,
505                                           int resultSetConcurrency,
506                                           int resultSetHoldability)
507                                    throws SQLException {
508
509         throw new UnsupportedOperationException JavaDoc();
510     }
511
512     public synchronized CallableStatement prepareCall(String JavaDoc sql,
513                                      int resultSetType,
514                                      int resultSetConcurrency,
515                                      int resultSetHoldability)
516                               throws SQLException {
517
518         throw new UnsupportedOperationException JavaDoc();
519     }
520
521     public synchronized PreparedStatement prepareStatement(String JavaDoc sql,
522                                           int autoGeneratedKeys)
523                                    throws SQLException {
524
525         throw new UnsupportedOperationException JavaDoc();
526     }
527
528     public synchronized PreparedStatement prepareStatement(String JavaDoc sql,
529                                           int[] columnIndexes)
530                                    throws SQLException {
531
532         throw new UnsupportedOperationException JavaDoc();
533     }
534
535     public synchronized PreparedStatement prepareStatement(String JavaDoc sql,
536                                           String JavaDoc[] columnNames)
537                                    throws SQLException {
538         throw new UnsupportedOperationException JavaDoc();
539     }
540
541     //-------------End New methods added in JDBC 3.0 --------------
542

543     //---------------- ConnectionImpl methods ----------------
544

545     /**
546      * Check the TransactionContext. If the current thread is in a
547      * transaction, and the Connection is not participating in a
548      * transaction; the Connection should register a resource with
549      * the current thread's transaction. If the current thread is
550      * in a transaction, and the Connection is participating in a
551      * transaction; the thread's transaction and the Connection's
552      * transaction must be the same transaction. Anything else is
553      * an error.
554      * <p>
555      * @exception SQLException if the current thread's transaction
556      * and the Connection's transaction do
557      * not match.
558      * @ForteInternal
559      */

560     synchronized void checkXact() throws SQLException {
561         /* RESOLVE: Need to reimplement this
562              * for CMP environment if any
563
564         Transaction tran;
565
566         try
567         {
568             tran = ThreadContext.transactionContext().getTransaction();
569         }
570         catch (SystemException ex)
571         {
572             tran = null;
573         }
574
575         if (tran == null)
576         {
577             if (this.transaction != null)
578             {
579                 throw new SQLException("Thread is no longer in transaction."); // NOI18N
580             }
581             else
582             {
583                 // No transaction.
584                 return;
585             }
586         }
587         else if (this.transaction == null)
588         {
589             // This is a new transaction.
590             this.transaction = tran;
591             this.resource = new ForteJDBCResource(this);
592             try
593             {
594                 TranManager tm = ThreadContext.partition().getTranManager();
595                 tm.enlistResource(this.resource);
596                 this.setAutoCommit(false);
597             }
598             catch (SQLException ex)
599             {
600             }
601             catch (Throwable ex)
602             {
603                 // XXX This shouldn't happen. XXX
604             }
605             this.connectionManager.associateXact(tran, this);
606         }
607         else if (!tran.equals(this.transaction))
608         {
609             throw new SQLException("Wrong Transaction."); // NOI18N
610         }
611         else
612         {
613             // Connection and thread are in the same transaction.
614             return;
615         }
616         */

617     }
618
619     /**
620      * Mark the Connection free-pending. A Connection gets into this
621      * state only if it is freed while still participating in a transaction.
622      * <p>
623      */

624     synchronized void setFreePending(boolean freePending) {
625         this.freePending = freePending;
626     }
627
628     /**
629      * Get the value of the free-pending attribute.
630      * <p>
631      */

632     synchronized boolean getFreePending() {
633         return (this.freePending);
634     }
635
636     /**
637      * Indicates whether this Connection is participating in a transaction.
638      * <p>
639      * @return True if this Connection is participating in a transaction;
640      * false, otherwise.
641      */

642     synchronized boolean xactPending() {
643         return ((this.transaction != null) ? true : false);
644     }
645
646     /**
647      * Get the previous ConnectionImpl in a chain.
648      * <p>
649      * @return The previous ConnectionImpl in a chain.
650      */

651     public Linkable getPrevious() {
652         return (this.previous);
653     }
654
655     /**
656      * Hook a ConnectionImpl to a chain.
657      * <p>
658      * @param conn The ConnectionImpl to hook on the chain.
659      */

660     public void setPrevious(Linkable conn) {
661         this.previous = conn;
662     }
663
664     /**
665      * Get the next ConnectionImpl in a chain.
666      * <p>
667      * @return The next ConnectionImpl in a chain.
668      */

669     public Linkable getNext() {
670         return (this.next);
671     }
672
673     /**
674      * Hook a ConnectionImpl to a chain.
675      * <p>
676      * @param conn The ConnectionImpl to hook on the chain.
677      */

678     public void setNext(Linkable conn) {
679         this.next = conn;
680     }
681
682     /**
683      * Indicates whether this ConnectionImpl is pooled.
684      * <p>
685      * @return TRUE if this ConnectionImpl is pooled.
686      */

687     synchronized boolean getPooled() {
688         return (this.pooled);
689     }
690
691     /**
692      * Mark this ConnectionImpl as pooled.
693      * <p>
694      */

695     synchronized void setPooled(boolean flag) {
696         this.pooled = flag;
697     }
698
699     /**
700      * Get the url for this ConnectionImpl object.
701      * <p>
702      * @return String containing the url for this ConnectionImpl object.
703      */

704     synchronized String JavaDoc getURL() {
705         return this.url;
706     }
707
708     /**
709      * Get the user name for this ConnectionImpl object.
710      * <p>
711      * @return String containing the user name for this
712      * ConnectionImpl object.
713      */

714     synchronized String JavaDoc getUserName() {
715         return this.userName;
716     }
717
718     /**
719      * Used by TransactionImpl to commit the transaction on this
720      * Connection. Also disassociates this Connection from the
721      * transaction. Throws ... (javax.transaction.xa.XAException(XA_RBROLLBACK))
722      * on commit error.
723      * <p>
724      */

725     public synchronized void internalCommit() {
726         logger.finest("sqlstore.connectionimpl.internalcommit"); // NOI18N
727

728         try {
729             this.connection.commit();
730         } catch (Exception JavaDoc e1) {
731             try {
732                 this.connection.rollback();
733             } catch (Exception JavaDoc e2) {
734                 // XXX Try to recover from bad connection. XXX
735
} finally {
736                 this.clearXact();
737             }
738             throw new JDODataStoreException(null, e1); //XAException(XAException.XA_RBROLLBACK);
739
} finally {
740             this.clearXact();
741         }
742     }
743
744
745     /**
746      * Used by TransactionImpl to rollback the transaction on this
747      * Connection. Also disassociates this Connection from the
748      * transaction.
749      * <p>
750      */

751     public synchronized void internalRollback() {
752         logger.finest("sqlstore.connectionimpl.internalrollback"); // NOI18N
753
try {
754             this.connection.rollback();
755         } catch (Exception JavaDoc e1) {
756             // XXX Try to recover from bad connection. XXX
757
} finally {
758             this.clearXact();
759         }
760     }
761
762     /**
763      * Clear this ConnectionImpl of any knowledge of a transaction.
764      * Also informs the parent ConnectionManager to clear its knowledge
765      * of the transaction as well.
766      * <p>
767      */

768     private void clearXact() {
769         logger.finest("sqlstore.connectionimpl.clearxact"); // NOI18N
770

771         try {
772             if (this.freePending) {
773                 this.freePending = false;
774                 if (this.pooled) {
775                     this.connectionManager.disassociateXact(this.transaction, this, true);
776                     logger.finest("sqlstore.connectionimpl.pendingdisassocxact"); // NOI18N
777
} else {
778                     this.connectionManager.disassociateXact(this.transaction, this, false);
779                     // Make sure the last things done are the only things
780
// that can throw exceptions.
781
this.connection.close();
782
783                     logger.finest("sqlstore.connectionimpl.clearxact.close"); // NOI18N
784
}
785             } else {
786                 this.connectionManager.disassociateXact(this.transaction, this, false);
787                 logger.finest("sqlstore.connectionimpl.clearxact.disassocxact"); // NOI18N
788
}
789             this.connection.setAutoCommit(true);
790         } catch (SQLException ex) {
791             // XXX Need to recover from a bad connection. XXX
792
} finally {
793             // this.resource = null;
794
this.transaction = null;
795         }
796     }
797
798     /**
799      * Return a string representation of this ConnectionImpl object.
800      * <p>
801      * @return String describing contents of this ConnectionImpl
802      * object.
803      */

804     public synchronized String JavaDoc toString() {
805         int xactIsolation = 0;
806         String JavaDoc buffer = "Connect@"; // NOI18N
807

808         String JavaDoc strTran = (this.transaction == null) ?
809                 " NULL" : this.transaction.toString(); // NOI18N
810
int hash = this.hashCode();
811
812         try {
813             xactIsolation = this.getTransactionIsolation();
814         } catch (SQLException ex) {
815             xactIsolation = -1;
816         }
817
818         buffer = buffer + hash + "\n" + // NOI18N
819
" pooled = " + this.pooled + "\n" + // NOI18N
820
" freePending = " + this.freePending + "\n" + // NOI18N
821
" xactIsolation = " + xactIsolation + "\n" + // NOI18N
822
" Tran = " + strTran + "\n"; // NOI18N
823

824         return buffer;
825     }
826
827     protected void finalize() {
828         try {
829             this.connection.close();
830             logger.finest("sqlstore.connectionimpl.finalize"); // NOI18N
831
} catch (SQLException se) {
832             ;
833         }
834     }
835 }
836
Popular Tags