KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opensubsystems > core > persist > db > transaction > TransactionalConnection


1 /*
2  * Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
3  *
4  * Project: OpenSubsystems
5  *
6  * $Id: TransactionalConnection.java,v 1.4 2007/01/23 06:00:01 bastafidli Exp $
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21
22 package org.opensubsystems.core.persist.db.transaction;
23
24 import java.sql.CallableStatement JavaDoc;
25 import java.sql.Connection JavaDoc;
26 import java.sql.DatabaseMetaData JavaDoc;
27 import java.sql.PreparedStatement JavaDoc;
28 import java.sql.SQLException JavaDoc;
29 import java.sql.SQLWarning JavaDoc;
30 import java.sql.Savepoint JavaDoc;
31 import java.sql.Statement JavaDoc;
32 import java.util.Map JavaDoc;
33
34 import org.opensubsystems.core.persist.db.DatabaseConnectionFactoryImpl;
35 import org.opensubsystems.core.util.GlobalConstants;
36
37 /**
38  * Transactional connection is wrapper around real database connection to ensure
39  * that the connection can be made part of global transaction spanning several
40  * code components which do not know about each other.
41  *
42  * @version $Id: TransactionalConnection.java,v 1.4 2007/01/23 06:00:01 bastafidli Exp $
43  * @author Miro Halas
44  * @code.reviewer Miro Halas
45  * @code.reviewed 1.1 2005/08/20 21:17:01 bastafidli
46  */

47 public class TransactionalConnection implements Connection JavaDoc
48 {
49    // Attributes ///////////////////////////////////////////////////////////////
50

51    /**
52     * Underlying database connection to which all method calls are delegated.
53     */

54    private Connection JavaDoc m_privateConnection;
55
56    /**
57     * Name of the data source this connection belongs to.
58     */

59    private String JavaDoc m_strDataSourceName;
60    
61    /**
62     * User name under which this connection was created.
63     */

64    private String JavaDoc m_strUser;
65
66    /**
67     * Password under which this connection was created.
68     */

69    private String JavaDoc m_strPassword;
70    
71    /**
72     * This flag is used by transaction to see if this connection was used
73     * while it was associated with the transaction to see if it should be
74     * commited or not.
75     */

76    private boolean m_bUsed;
77    
78    /**
79     * This flas is increamented when the connection is requested from the pool
80     * and decremented when it is returned. This is used in case the connection
81     * is returned in the transaction to mark it as returned since it cannot be
82     * really returned while it is associated with transaction.
83     */

84    private int m_iActiveCount;
85    
86    /**
87     * This flag will be set to true if the connection is associated with
88     * transaction so that the database connection factory knows it cannot
89     * be returned to the pool.
90     */

91    private boolean m_bInTransaction;
92    
93    /**
94     * Connection factory from which the private connection was acquired.
95     */

96    private DatabaseConnectionFactoryImpl m_connectionFactory;
97    
98    // Constructors /////////////////////////////////////////////////////////////
99

100    /**
101     * Protected constructor so that only classes from this package can create it.
102     *
103     * @param privateConnection - real connection to the database
104     * @param strDataSourceName - name of the data source this connection belongs to
105     * @param strUser - user name under which this connection was created
106     * @param strPassword - password under which this connection was created
107     * @param inTransaction - is the connection already in the transaction
108     * @param connectionFactory - connection factory from which the private connection
109     * was acquired
110     */

111    protected TransactionalConnection(
112       Connection JavaDoc privateConnection,
113       String JavaDoc strDataSourceName,
114       String JavaDoc strUser,
115       String JavaDoc strPassword,
116       boolean inTransaction,
117       DatabaseConnectionFactoryImpl connectionFactory
118    )
119    {
120       super();
121       
122       m_privateConnection = privateConnection;
123       m_strDataSourceName = strDataSourceName;
124       m_strUser = strUser;
125       m_strPassword = strPassword;
126       m_bInTransaction = inTransaction;
127       m_connectionFactory = connectionFactory;
128       m_bUsed = false; // the connection wasn't used yet
129
m_iActiveCount = 1; // the connection was just constructed so it has to be active
130
}
131    
132    // Accessors ////////////////////////////////////////////////////////////////
133

134    /**
135     * This method is not public so that it can be used only in this package.
136     *
137     * @return boolean - if true then the connection is active, it wasn't returned
138     * to the pool yet.
139     */

140    boolean isActive()
141    {
142       return (m_iActiveCount > 0);
143    }
144    
145    /**
146     * This method is not public so that it can be used only in this package.
147     *
148     * @param active - if true then the connection was requested from the pool
149     * if false it was already returned to the pool
150     */

151    void setActive(
152       boolean active
153    )
154    {
155       if (active)
156       {
157          m_iActiveCount++;
158       }
159       else
160       {
161          m_iActiveCount--;
162          if (GlobalConstants.ERROR_CHECKING)
163          {
164             assert m_iActiveCount >= 0 : "Connection was returned too many times.";
165          }
166       }
167    }
168    
169    /**
170     * This method is not public so that it can be used only in this package.
171     *
172     * @return boolean - if true then the connection any use of connection at
173     * this time will be inside of transaction.
174     */

175    boolean isInTransaction()
176    {
177       return m_bInTransaction;
178    }
179    
180    /**
181     * This method is not public so that it can be used only in this package.
182     *
183     * @param inTransaction - if in true then this connection is now associated
184     * with the transaction
185     * @throws SQLException - an error has occured while associating connection
186     * with transaction
187     */

188    void setInTransaction(
189       boolean inTransaction
190    ) throws SQLException JavaDoc
191    {
192       if ((inTransaction) && (m_privateConnection.getAutoCommit()))
193       {
194          // Since the connection is now in transaction we need to disable
195
// the autocommit
196
m_privateConnection.setAutoCommit(false);
197       }
198       m_bInTransaction = inTransaction;
199    }
200    
201    /**
202     * This method is not public so that it can be used only in this package.
203     *
204     * @return boolean - if true then some method was called on connection since
205     * the last time this flag was reset
206     */

207    public boolean isUsed()
208    {
209       return m_bUsed;
210    }
211    
212    /**
213     * @param used - if true then some method was called on connection since
214     * the last time this flag was reset
215     * @throws SQLException - an error probably because the connection should
216     * no longer be used
217     */

218    void setUsed(
219       boolean used
220    ) throws SQLException JavaDoc
221    {
222       if ((m_iActiveCount == 0) && (used))
223       {
224          throw new SQLException JavaDoc("This connection was already returned to the pool " +
225                                 " and shouldn't be used anymore.");
226       }
227       m_bUsed = used;
228    }
229    
230    /**
231     * @return String
232     */

233    public String JavaDoc getDataSourceName()
234    {
235       return m_strDataSourceName;
236    }
237
238    /**
239     * @return String
240     */

241    public String JavaDoc getPassword()
242    {
243       return m_strPassword;
244    }
245    
246    /**
247     * @return String
248     */

249    public String JavaDoc getUser()
250    {
251       return m_strUser;
252    }
253    
254    /**
255     * Verify if the specified connection is the one which is used by this wrapper.
256     *
257     * @param verifiableConnection - connection to verify
258     * @return boolean - true if the connections are the same
259     */

260    public boolean verifyConnection(
261       Connection JavaDoc verifiableConnection
262    )
263    {
264       // Verify if they are the same instance using ==
265
return verifiableConnection == m_privateConnection;
266    }
267
268    /**
269     * @return DatabaseConnectionFactoryImpl
270     */

271    public DatabaseConnectionFactoryImpl getConnectionFactory()
272    {
273       return m_connectionFactory;
274    }
275    
276    // java.sql.Connection delegating methods ///////////////////////////////////
277

278    /**
279     * {@inheritDoc}
280     */

281    public void clearWarnings(
282    ) throws SQLException JavaDoc
283    {
284       setUsed(true);
285       m_privateConnection.clearWarnings();
286    }
287
288    /**
289     * {@inheritDoc}
290     */

291    public void close(
292    ) throws SQLException JavaDoc
293    {
294       throw new SQLException JavaDoc("Connection is not supposed to be closed." +
295                              " It should be returned to database connection factory.");
296       // setUsed(true);
297
// m_privateConnection.close();
298
}
299
300    /**
301     * {@inheritDoc}
302     */

303    public void commit(
304    ) throws SQLException JavaDoc
305    {
306       if (m_bInTransaction)
307       {
308          throw new SQLException JavaDoc("Connection in transaction cannot be commited.");
309       }
310       // We are commiting so that means that this connection is clean and not
311
// used anymore
312
setUsed(false);
313       m_privateConnection.commit();
314    }
315
316    /**
317     * {@inheritDoc}
318     */

319    public Statement JavaDoc createStatement(
320    ) throws SQLException JavaDoc
321    {
322       setUsed(true);
323       return m_privateConnection.createStatement();
324    }
325
326    /**
327     * {@inheritDoc}
328     */

329    public Statement JavaDoc createStatement(
330       int resultSetType,
331       int resultSetConcurrency
332    ) throws SQLException JavaDoc
333    {
334       setUsed(true);
335       return m_privateConnection.createStatement(resultSetType, resultSetConcurrency);
336    }
337
338    /**
339     * {@inheritDoc}
340     */

341    public Statement JavaDoc createStatement(
342       int resultSetType,
343       int resultSetConcurrency,
344       int resultSetHoldability
345    ) throws SQLException JavaDoc
346    {
347       setUsed(true);
348       return m_privateConnection.createStatement(resultSetType, resultSetConcurrency,
349                resultSetHoldability);
350    }
351
352    /**
353     * {@inheritDoc}
354     */

355    public boolean equals(
356       Object JavaDoc obj
357    )
358    {
359       // This is not really a use of connection
360
// setUsed(true);
361
return m_privateConnection.equals(obj);
362    }
363
364    /**
365     * {@inheritDoc}
366     */

367    public boolean getAutoCommit(
368    ) throws SQLException JavaDoc
369    {
370       setUsed(true);
371       return m_privateConnection.getAutoCommit();
372    }
373
374    /**
375     * {@inheritDoc}
376     */

377    public String JavaDoc getCatalog(
378    ) throws SQLException JavaDoc
379    {
380       setUsed(true);
381       return m_privateConnection.getCatalog();
382    }
383
384    /**
385     * {@inheritDoc}
386     */

387    public int getHoldability(
388    ) throws SQLException JavaDoc
389    {
390       setUsed(true);
391       return m_privateConnection.getHoldability();
392    }
393
394    /**
395     * {@inheritDoc}
396     */

397    public DatabaseMetaData JavaDoc getMetaData(
398    ) throws SQLException JavaDoc
399    {
400       setUsed(true);
401       return m_privateConnection.getMetaData();
402    }
403
404    /**
405     * {@inheritDoc}
406     */

407    public int getTransactionIsolation(
408    ) throws SQLException JavaDoc
409    {
410       setUsed(true);
411       return m_privateConnection.getTransactionIsolation();
412    }
413
414    /**
415     * {@inheritDoc}
416     */

417    public Map JavaDoc getTypeMap(
418    ) throws SQLException JavaDoc
419    {
420       setUsed(true);
421       return m_privateConnection.getTypeMap();
422    }
423
424    /**
425     * {@inheritDoc}
426     */

427    public SQLWarning JavaDoc getWarnings(
428    ) throws SQLException JavaDoc
429    {
430       setUsed(true);
431       return m_privateConnection.getWarnings();
432    }
433
434    /**
435     * {@inheritDoc}
436     */

437    public int hashCode()
438    {
439       // This is not really a use of connection
440
// setUsed(true);
441
return m_privateConnection.hashCode();
442    }
443
444    /**
445     * {@inheritDoc}
446     */

447    public boolean isClosed(
448    ) throws SQLException JavaDoc
449    {
450       setUsed(true);
451       return m_privateConnection.isClosed();
452    }
453
454    /**
455     * {@inheritDoc}
456     */

457    public boolean isReadOnly(
458    ) throws SQLException JavaDoc
459    {
460       setUsed(true);
461       return m_privateConnection.isReadOnly();
462    }
463
464    /**
465     * {@inheritDoc}
466     */

467    public String JavaDoc nativeSQL(
468       String JavaDoc sql
469    ) throws SQLException JavaDoc
470    {
471       setUsed(true);
472       return m_privateConnection.nativeSQL(sql);
473    }
474
475    /**
476     * {@inheritDoc}
477     */

478    public CallableStatement JavaDoc prepareCall(
479       String JavaDoc sql
480    ) throws SQLException JavaDoc
481    {
482       setUsed(true);
483       return m_privateConnection.prepareCall(sql);
484    }
485
486    /**
487     * {@inheritDoc}
488     */

489    public CallableStatement JavaDoc prepareCall(
490       String JavaDoc sql,
491       int resultSetType,
492       int resultSetConcurrency
493    ) throws SQLException JavaDoc
494    {
495       setUsed(true);
496       return m_privateConnection.prepareCall(sql, resultSetType, resultSetConcurrency);
497    }
498
499    /**
500     * {@inheritDoc}
501     */

502    public CallableStatement JavaDoc prepareCall(
503       String JavaDoc sql,
504       int resultSetType,
505       int resultSetConcurrency,
506       int resultSetHoldability
507    ) throws SQLException JavaDoc
508    {
509       setUsed(true);
510       return m_privateConnection.prepareCall(sql, resultSetType, resultSetConcurrency,
511                resultSetHoldability);
512    }
513
514    /**
515     * {@inheritDoc}
516     */

517    public PreparedStatement JavaDoc prepareStatement(
518       String JavaDoc sql
519    ) throws SQLException JavaDoc
520    {
521       setUsed(true);
522       return m_privateConnection.prepareStatement(sql);
523    }
524
525    /**
526     * {@inheritDoc}
527     */

528    public PreparedStatement JavaDoc prepareStatement(
529       String JavaDoc sql,
530       int autoGeneratedKeys
531    ) throws SQLException JavaDoc
532    {
533       setUsed(true);
534       return m_privateConnection.prepareStatement(sql, autoGeneratedKeys);
535    }
536
537    /**
538     * {@inheritDoc}
539     */

540    public PreparedStatement JavaDoc prepareStatement(
541       String JavaDoc sql,
542       int resultSetType,
543       int resultSetConcurrency
544    ) throws SQLException JavaDoc
545    {
546       setUsed(true);
547       return m_privateConnection.prepareStatement(sql, resultSetType, resultSetConcurrency);
548    }
549
550    /**
551     * {@inheritDoc}
552     */

553    public PreparedStatement JavaDoc prepareStatement(
554       String JavaDoc sql,
555       int resultSetType,
556       int resultSetConcurrency,
557       int resultSetHoldability
558    ) throws SQLException JavaDoc
559    {
560       setUsed(true);
561       return m_privateConnection.prepareStatement(sql, resultSetType, resultSetConcurrency,
562                resultSetHoldability);
563    }
564
565    /**
566     * {@inheritDoc}
567     */

568    public PreparedStatement JavaDoc prepareStatement(
569       String JavaDoc sql,
570       int[] columnIndexes
571    ) throws SQLException JavaDoc
572    {
573       setUsed(true);
574       return m_privateConnection.prepareStatement(sql, columnIndexes);
575    }
576
577    /**
578     * {@inheritDoc}
579     */

580    public PreparedStatement JavaDoc prepareStatement(
581       String JavaDoc sql, String JavaDoc[] columnNames
582    ) throws SQLException JavaDoc
583    {
584       setUsed(true);
585       return m_privateConnection.prepareStatement(sql, columnNames);
586    }
587
588    /**
589     * {@inheritDoc}
590     */

591    public void releaseSavepoint(
592       Savepoint JavaDoc savepoint
593    ) throws SQLException JavaDoc
594    {
595       setUsed(true);
596       m_privateConnection.releaseSavepoint(savepoint);
597    }
598
599    /**
600     * {@inheritDoc}
601     */

602    public void rollback(
603    ) throws SQLException JavaDoc
604    {
605       if (m_bInTransaction)
606       {
607          throw new SQLException JavaDoc("Connection in transaction cannot be rollbacked.");
608       }
609       // We are rolling back so that means that this connection is clean and not
610
// used anymore
611
setUsed(false);
612       m_privateConnection.rollback();
613    }
614
615    /**
616     * {@inheritDoc}
617     */

618    public void rollback(
619       Savepoint JavaDoc savepoint
620    ) throws SQLException JavaDoc
621    {
622       setUsed(true);
623       m_privateConnection.rollback(savepoint);
624    }
625
626    /**
627     * {@inheritDoc}
628     */

629    public void setAutoCommit(
630       boolean autoCommit
631    ) throws SQLException JavaDoc
632    {
633       if ((m_bInTransaction) && (autoCommit))
634       {
635          throw new SQLException JavaDoc("Connection in transaction cannot be set to autocommit.");
636       }
637       setUsed(true);
638       m_privateConnection.setAutoCommit(autoCommit);
639    }
640
641    /**
642     * {@inheritDoc}
643     */

644    public void setCatalog(
645       String JavaDoc catalog
646    ) throws SQLException JavaDoc
647    {
648       setUsed(true);
649       m_privateConnection.setCatalog(catalog);
650    }
651
652    /**
653     * {@inheritDoc}
654     */

655    public void setHoldability(
656       int holdability
657    ) throws SQLException JavaDoc
658    {
659       setUsed(true);
660       m_privateConnection.setHoldability(holdability);
661    }
662
663    /**
664     * {@inheritDoc}
665     */

666    public void setReadOnly(
667       boolean readOnly
668    ) throws SQLException JavaDoc
669    {
670       setUsed(true);
671       m_privateConnection.setReadOnly(readOnly);
672    }
673
674    /**
675     * {@inheritDoc}
676     */

677    public Savepoint JavaDoc setSavepoint(
678    ) throws SQLException JavaDoc
679    {
680       setUsed(true);
681       return m_privateConnection.setSavepoint();
682    }
683
684    /**
685     * {@inheritDoc}
686     */

687    public Savepoint JavaDoc setSavepoint(
688       String JavaDoc name
689    ) throws SQLException JavaDoc
690    {
691       setUsed(true);
692       return m_privateConnection.setSavepoint(name);
693    }
694
695    /**
696     * {@inheritDoc}
697     */

698    public void setTransactionIsolation(
699       int level
700    ) throws SQLException JavaDoc
701    {
702       setUsed(true);
703       m_privateConnection.setTransactionIsolation(level);
704    }
705
706    /**
707     * {@inheritDoc}
708     */

709    public void setTypeMap(
710       Map JavaDoc map
711    ) throws SQLException JavaDoc
712    {
713       setUsed(true);
714       m_privateConnection.setTypeMap(map);
715    }
716
717    /**
718     * {@inheritDoc}
719     */

720    public String JavaDoc toString()
721    {
722       // This is not really a use of connection
723
// setUsed(true);
724
return m_privateConnection.toString();
725    }
726
727    // These methods were added in Java 1.6 /////////////////////////////////////
728

729 // TODO: JDK 1.6
730
// /**
731
// * {@inheritDoc}
732
// */
733
// public Array createArrayOf(
734
// String typeName,
735
// Object[] elements
736
// ) throws SQLException
737
// {
738
// setUsed(true);
739
// return m_privateConnection.createArrayOf(typeName, elements);
740
// }
741
//
742
// /**
743
// * {@inheritDoc}
744
// */
745
// public Blob createBlob(
746
// ) throws SQLException
747
// {
748
// setUsed(true);
749
// return m_privateConnection.createBlob();
750
// }
751
//
752
// /**
753
// * {@inheritDoc}
754
// */
755
// public Clob createClob(
756
// ) throws SQLException
757
// {
758
// setUsed(true);
759
// return m_privateConnection.createClob();
760
// }
761
//
762
// /**
763
// * {@inheritDoc}
764
// */
765
// public NClob createNClob(
766
// ) throws SQLException
767
// {
768
// setUsed(true);
769
// return m_privateConnection.createNClob();
770
// }
771
//
772
// /**
773
// * {@inheritDoc}
774
// */
775
// public SQLXML createSQLXML(
776
// ) throws SQLException
777
// {
778
// setUsed(true);
779
// return m_privateConnection.createSQLXML();
780
// }
781
//
782
// /**
783
// * {@inheritDoc}
784
// */
785
// public Struct createStruct(
786
// String typeName,
787
// Object[] attributes
788
// ) throws SQLException
789
// {
790
// setUsed(true);
791
// return m_privateConnection.createStruct(typeName, attributes);
792
// }
793
//
794
// /**
795
// * {@inheritDoc}
796
// */
797
// public Properties getClientInfo(
798
// ) throws SQLException
799
// {
800
// setUsed(true);
801
// return m_privateConnection.getClientInfo();
802
// }
803
//
804
// /**
805
// * {@inheritDoc}
806
// */
807
// public String getClientInfo(
808
// String name
809
// ) throws SQLException
810
// {
811
// setUsed(true);
812
// return m_privateConnection.getClientInfo(name);
813
// }
814
//
815
// /**
816
// * {@inheritDoc}
817
// */
818
// public boolean isValid(
819
// int timeout
820
// ) throws SQLException
821
// {
822
// setUsed(true);
823
// return m_privateConnection.isValid(timeout);
824
// }
825
//
826
// /**
827
// * {@inheritDoc}
828
// */
829
// public void setClientInfo(
830
// Properties properties
831
// ) throws SQLClientInfoException
832
// {
833
// try
834
// {
835
// setUsed(true);
836
// }
837
// catch (SQLException exc)
838
// {
839
// SQLClientInfoException exc2 = new SQLClientInfoException();
840
// exc2.setNextException(exc);
841
// throw exc2;
842
// }
843
// m_privateConnection.setClientInfo(properties);
844
// }
845
//
846
// /**
847
// * {@inheritDoc}
848
// */
849
// public void setClientInfo(
850
// String name,
851
// String value
852
// ) throws SQLClientInfoException
853
// {
854
// try
855
// {
856
// setUsed(true);
857
// }
858
// catch (SQLException exc)
859
// {
860
// SQLClientInfoException exc2 = new SQLClientInfoException();
861
// exc2.setNextException(exc);
862
// throw exc2;
863
// }
864
// m_privateConnection.setClientInfo(name, value);
865
// }
866
//
867
// /**
868
// * {@inheritDoc}
869
// */
870
// public boolean isWrapperFor(
871
// Class iface
872
// ) throws SQLException
873
// {
874
// setUsed(true);
875
// return m_privateConnection.isWrapperFor(iface);
876
// }
877
//
878
// /**
879
// * {@inheritDoc}
880
// */
881
// public Object unwrap(
882
// Class iface
883
// ) throws SQLException
884
// {
885
// setUsed(true);
886
// return m_privateConnection.unwrap(iface);
887
// }
888
}
889
Popular Tags