KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > jdbc > EmbedPooledConnection


1 /*
2
3    Derby - Class org.apache.derby.jdbc.EmbedPooledConnection
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.jdbc;
23
24 import org.apache.derby.iapi.services.sanity.SanityManager;
25 import org.apache.derby.iapi.reference.Property;
26 import org.apache.derby.iapi.error.ExceptionSeverity;
27 import org.apache.derby.iapi.reference.JDBC30Translation;
28
29 /* import impl class */
30 import org.apache.derby.impl.jdbc.Util;
31 import org.apache.derby.impl.jdbc.EmbedConnection;
32 import org.apache.derby.iapi.jdbc.BrokeredConnection;
33 import org.apache.derby.iapi.jdbc.BrokeredConnectionControl;
34 import org.apache.derby.iapi.jdbc.EngineConnection;
35 import org.apache.derby.impl.jdbc.EmbedPreparedStatement;
36 import org.apache.derby.impl.jdbc.EmbedCallableStatement;
37
38
39 import java.sql.Connection JavaDoc;
40 import java.sql.SQLException JavaDoc;
41 import java.sql.Statement JavaDoc;
42 import java.sql.PreparedStatement JavaDoc;
43 import java.sql.CallableStatement JavaDoc;
44
45 import java.util.Vector JavaDoc;
46 import java.util.Enumeration JavaDoc;
47
48 /* -- New jdbc 20 extension types --- */
49 import javax.sql.DataSource JavaDoc;
50 import javax.sql.PooledConnection JavaDoc;
51 import javax.sql.ConnectionEventListener JavaDoc;
52 import javax.sql.ConnectionEvent JavaDoc;
53
54 /**
55     A PooledConnection object is a connection object that provides hooks for
56     connection pool management.
57
58     <P>This is Derby's implementation of a PooledConnection for use in
59     the following environments:
60     <UL>
61     <LI> JDBC 3.0 - Java 2 - JDK 1.4, J2SE 5.0
62     <LI> JDBC 2.0 - Java 2 - JDK 1.2,1.3
63     </UL>
64
65  */

66 class EmbedPooledConnection implements javax.sql.PooledConnection JavaDoc, BrokeredConnectionControl
67 {
68
69     /** Static counter for connection ids */
70     private static int idCounter = 0;
71     
72     /** The id for this connection. */
73     private int connectionId;
74     
75     /** the connection string */
76     private String JavaDoc connString;
77     
78     private Vector JavaDoc eventListener; // who wants to know I am closed or error
79

80     EmbedConnection realConnection;
81     int defaultIsolationLevel;
82     private boolean defaultReadOnly;
83     BrokeredConnection currentConnectionHandle;
84
85     // set up once by the data source
86
final ReferenceableDataSource dataSource;
87     private final String JavaDoc username;
88     private final String JavaDoc password;
89     /**
90         True if the password was passed in on the connection request, false if it came from the data source property.
91     */

92     private final boolean requestPassword;
93
94     protected boolean isActive;
95     
96     private synchronized int nextId()
97     {
98         return idCounter++;
99     }
100
101     EmbedPooledConnection(ReferenceableDataSource ds, String JavaDoc u, String JavaDoc p, boolean requestPassword) throws SQLException JavaDoc
102     {
103         connectionId = nextId();
104
105         dataSource = ds;
106         username = u;
107         password = p;
108         this.requestPassword = requestPassword;
109         isActive = true;
110
111         // open the connection up front in order to do authentication
112
openRealConnection();
113
114     }
115
116     String JavaDoc getUsername()
117     {
118         if (username == null || username.equals(""))
119             return Property.DEFAULT_USER_NAME;
120         else
121             return username;
122     }
123
124     String JavaDoc getPassword()
125     {
126         if (password == null)
127             return "";
128         else
129             return password;
130     }
131
132
133     /**
134         Create an object handle for a database connection.
135
136         @return a Connection object
137
138         @exception SQLException - if a database-access error occurs.
139     */

140     public synchronized Connection getConnection() throws SQLException JavaDoc
141     {
142         checkActive();
143
144         // need to do this in case the connection is forcibly removed without
145
// first being closed.
146
closeCurrentConnectionHandle();
147
148
149         // RealConnection is not null if the app server yanks a local
150
// connection from one client and give it to another. In this case,
151
// the real connection is ready to be used. Otherwise, set it up
152
if (realConnection == null)
153         {
154             // first time we establish a connection
155
openRealConnection();
156         }
157         else
158         {
159             resetRealConnection();
160         }
161
162         // now make a brokered connection wrapper and give this to the user
163
// we reuse the EmbedConnection(ie realConnection).
164
Connection c = getNewCurrentConnectionHandle();
165         return c;
166     }
167
168     final void openRealConnection() throws SQLException JavaDoc {
169         // first time we establish a connection
170
Connection rc = dataSource.getConnection(username, password, requestPassword);
171
172         this.realConnection = (EmbedConnection) rc;
173         defaultIsolationLevel = rc.getTransactionIsolation();
174         defaultReadOnly = rc.isReadOnly();
175         if (currentConnectionHandle != null)
176             realConnection.setApplicationConnection(currentConnectionHandle);
177     }
178
179     final Connection getNewCurrentConnectionHandle() {
180         Connection applicationConnection = currentConnectionHandle =
181             ((org.apache.derby.jdbc.Driver20) (realConnection.getLocalDriver())).newBrokeredConnection(this);
182         realConnection.setApplicationConnection(applicationConnection);
183         return applicationConnection;
184
185     }
186
187     /**
188         In this case the Listeners are *not* notified. JDBC 3.0 spec section 11.4
189     */

190     private void closeCurrentConnectionHandle() throws SQLException JavaDoc {
191         if (currentConnectionHandle != null)
192         {
193             Vector JavaDoc tmpEventListener = eventListener;
194             eventListener = null;
195
196             try {
197                 currentConnectionHandle.close();
198             } finally {
199                 eventListener = tmpEventListener;
200             }
201
202             currentConnectionHandle = null;
203         }
204     }
205
206     void resetRealConnection() throws SQLException JavaDoc {
207
208         // ensure any outstanding changes from the previous
209
// user are rolledback.
210
realConnection.rollback();
211
212         // clear any warnings that are left over
213
realConnection.clearWarnings();
214
215         // need to reset transaction isolation, autocommit, readonly, holdability states
216
if (realConnection.getTransactionIsolation() != defaultIsolationLevel) {
217
218             realConnection.setTransactionIsolation(defaultIsolationLevel);
219         }
220
221         if (!realConnection.getAutoCommit())
222             realConnection.setAutoCommit(true);
223
224         if (realConnection.isReadOnly() != defaultReadOnly)
225             realConnection.setReadOnly(defaultReadOnly);
226
227         if (realConnection.getHoldability() != JDBC30Translation.HOLD_CURSORS_OVER_COMMIT)
228             realConnection.setHoldability(JDBC30Translation.HOLD_CURSORS_OVER_COMMIT);
229
230         // reset any remaining state of the connection
231
realConnection.resetFromPool();
232     }
233
234     /**
235         Close the Pooled connection.
236
237         @exception SQLException - if a database-access error occurs.
238      */

239     public synchronized void close() throws SQLException JavaDoc
240     {
241         if (!isActive)
242             return;
243
244         closeCurrentConnectionHandle();
245         try {
246             if (realConnection != null) {
247                 if (!realConnection.isClosed())
248                     realConnection.close();
249             }
250
251         } finally {
252
253             realConnection = null; // make sure I am not accessed again.
254
isActive = false;
255             eventListener = null;
256         }
257     }
258
259     /**
260         Add an event listener.
261      */

262     public final synchronized void addConnectionEventListener(ConnectionEventListener JavaDoc listener)
263     {
264         if (!isActive)
265             return;
266         if (listener == null)
267             return;
268         if (eventListener == null)
269             eventListener = new Vector JavaDoc();
270         eventListener.addElement(listener);
271     }
272
273     /**
274         Remove an event listener.
275      */

276     public final synchronized void removeConnectionEventListener(ConnectionEventListener JavaDoc listener)
277     {
278         if (listener == null)
279             return;
280         if (eventListener != null)
281             eventListener.removeElement(listener);
282     }
283
284     /*
285      * class specific method
286      */

287
288     // called by ConnectionHandle when it needs to forward things to the
289
// underlying connection
290
public synchronized EngineConnection getRealConnection()
291        throws SQLException JavaDoc
292     {
293         checkActive();
294
295         return realConnection;
296     }
297
298
299     // my conneciton handle has caught an error (actually, the real connection
300
// has already handled the error, we just need to nofity the listener an
301
// error is about to be thrown to the app).
302
public synchronized void notifyError(SQLException JavaDoc exception)
303     {
304         // only report fatal error to the connection pool manager
305
if (exception.getErrorCode() < ExceptionSeverity.SESSION_SEVERITY)
306             return;
307
308         // tell my listeners an exception is about to be thrown
309
if (eventListener != null && eventListener.size() > 0)
310         {
311             ConnectionEvent JavaDoc errorEvent = new ConnectionEvent JavaDoc(this, exception);
312
313             for (Enumeration JavaDoc e = eventListener.elements();
314                  e.hasMoreElements(); )
315             {
316                 ConnectionEventListener JavaDoc l =
317                     (ConnectionEventListener JavaDoc)e.nextElement();
318                 l.connectionErrorOccurred(errorEvent);
319             }
320         }
321     }
322
323     // my conneciton handle is being closed
324
public synchronized void notifyClose()
325     {
326         // tell my listeners I am closed
327
if (eventListener != null && eventListener.size() > 0)
328         {
329             ConnectionEvent JavaDoc closeEvent = new ConnectionEvent JavaDoc(this);
330
331             for (Enumeration JavaDoc e = eventListener.elements();
332                  e.hasMoreElements(); )
333             {
334                 ConnectionEventListener JavaDoc l =
335                     (ConnectionEventListener JavaDoc)e.nextElement();
336                 l.connectionClosed(closeEvent);
337             }
338         }
339     }
340
341     final void checkActive() throws SQLException JavaDoc {
342         if (!isActive)
343             throw Util.noCurrentConnection();
344     }
345
346
347     /*
348     ** BrokeredConnectionControl api
349     */

350
351     /**
352         Returns true if isolation level has been set using either JDBC api or SQL
353      */

354     public boolean isIsolationLevelSetUsingSQLorJDBC() throws SQLException JavaDoc {
355         if (realConnection != null)
356             return realConnection.getLanguageConnection().isIsolationLevelSetUsingSQLorJDBC();
357         else
358             return false;
359     }
360
361     /**
362         Reset the isolation level flag used to keep state in
363         BrokeredConnection. It will get set to true when isolation level
364         is set using JDBC/SQL. It will get reset to false at the start
365         and the end of a global transaction.
366     */

367     public void resetIsolationLevelFlag() throws SQLException JavaDoc {
368         realConnection.getLanguageConnection().resetIsolationLevelFlagUsedForSQLandJDBC();
369     }
370     
371     
372     /**
373         Notify the control class that a SQLException was thrown
374         during a call on one of the brokered connection's methods.
375     */

376     public void notifyException(SQLException JavaDoc sqle) {
377         this.notifyError(sqle);
378     }
379
380
381     /**
382         Allow control over setting auto commit mode.
383     */

384     public void checkAutoCommit(boolean autoCommit) throws SQLException JavaDoc {
385     }
386
387     /**
388         Are held cursors allowed.
389     */

390     public int checkHoldCursors(int holdability, boolean downgrade)
391         throws SQLException JavaDoc
392     {
393         return holdability;
394     }
395
396     /**
397         Allow control over creating a Savepoint (JDBC 3.0)
398     */

399     public void checkSavepoint() throws SQLException JavaDoc {
400     }
401
402     /**
403         Allow control over calling rollback.
404     */

405     public void checkRollback() throws SQLException JavaDoc {
406     }
407
408     /**
409         Allow control over calling commit.
410     */

411     public void checkCommit() throws SQLException JavaDoc {
412     }
413
414     /**
415         Close called on BrokeredConnection. If this call
416         returns true then getRealConnection().close() will be called.
417
418         Don't close the underlying real connection as
419         it is pooled.
420     */

421     public boolean closingConnection() throws SQLException JavaDoc {
422         notifyClose();
423         currentConnectionHandle = null;
424         return false;
425     }
426
427     /**
428         No need to wrap statements for PooledConnections.
429     */

430     public Statement wrapStatement(Statement s) throws SQLException JavaDoc {
431         return s;
432     }
433     /**
434          * Call the setBrokeredConnectionControl method inside the
435          * EmbedPreparedStatement class to set the BrokeredConnectionControl
436          * variable to this instance of EmbedPooledConnection
437          * This will then be used to call the onStatementErrorOccurred
438          * and onStatementClose events when the corresponding events
439          * occur on the PreparedStatement
440          *
441          * @param ps PreparedStatment to be wrapped
442          * @param sql String
443          * @param generatedKeys Object
444          * @return returns the wrapped PreparedStatement
445          * @throws java.sql.SQLException
446      */

447     public PreparedStatement wrapStatement(PreparedStatement ps, String JavaDoc sql, Object JavaDoc generatedKeys) throws SQLException JavaDoc {
448                /*
449                     
450                 */

451                 EmbedPreparedStatement ps_ = (EmbedPreparedStatement)ps;
452                 ps_.setBrokeredConnectionControl(this);
453         return (PreparedStatement)ps_;
454     }
455         
456         /**
457          * Call the setBrokeredConnectionControl method inside the
458          * EmbedCallableStatement class to set the BrokeredConnectionControl
459          * variable to this instance of EmbedPooledConnection
460          * This will then be used to call the onStatementErrorOccurred
461          * and onStatementClose events when the corresponding events
462          * occur on the CallableStatement
463          *
464          * @param cs CallableStatment to be wrapped
465          * @param sql String
466          * @return returns the wrapped CallableStatement
467          * @throws java.sql.SQLException
468      */

469     public CallableStatement wrapStatement(CallableStatement cs, String JavaDoc sql) throws SQLException JavaDoc {
470                 EmbedCallableStatement cs_ = (EmbedCallableStatement)cs;
471                 cs_.setBrokeredConnectionControl(this);
472         return (CallableStatement)cs_;
473     }
474     
475     /**
476      * Get the string representation of this pooled connection.
477      *
478      * A pooled connection is assigned a separate id from a physical
479      * connection. When a container calls PooledConnection.toString(),
480      * it gets the string representation of this id. This is useful for
481      * developers implementing connection pools when they are trying to
482      * debug pooled connections.
483      *
484      * @return a string representation of the uniquie id for this pooled
485      * connection.
486      *
487      */

488     public String JavaDoc toString()
489     {
490         if ( connString == null )
491         {
492             String JavaDoc physicalConnString = isActive ?
493                 realConnection.toString() : "<none>";
494             
495             connString =
496               this.getClass().getName() + "@" + this.hashCode() + " " +
497                 "(ID = " + connectionId + "), " +
498                 "Physical Connection = " + physicalConnString;
499         }
500         
501         return connString;
502     }
503     
504     /*-----------------------------------------------------------------*/
505     /*
506      * These methods are from the BrokeredConnectionControl interface.
507      * These methods are needed to provide StatementEvent support for
508      * derby.
509      * They are actually implemented in EmbedPooledConnection40 but have
510      * a dummy implementation here so that the compilation wont fail when they
511      * are compiled with jdk1.4
512      */

513     
514     /**
515      * Dummy implementation for the actual methods found in
516      * org.apache.derby.jdbc.EmbedPooledConnection40
517      * @param statement PreparedStatement
518      */

519     public void onStatementClose(PreparedStatement statement) {
520         
521     }
522     
523     /**
524      * Dummy implementation for the actual methods found in
525      * org.apache.derby.jdbc.EmbedPooledConnection40
526      * @param statement PreparedStatement
527      * @param sqle SQLException
528      */

529     public void onStatementErrorOccurred(PreparedStatement statement,
530             SQLException JavaDoc sqle) {
531         
532     }
533 }
534
Popular Tags