EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [EmbedPooledConnection.java]

nameclass, %method, %block, %line, %
EmbedPooledConnection.java100% (1/1)87%  (26/30)82%  (311/381)85%  (102.8/121)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class EmbedPooledConnection100% (1/1)87%  (26/30)82%  (311/381)85%  (102.8/121)
<static initializer> 100% (1/1)100% (3/3)100% (1/1)
EmbedPooledConnection (ReferenceableDataSource, String, String, boolean): void 100% (1/1)100% (24/24)100% (9/9)
addConnectionEventListener (ConnectionEventListener): void 100% (1/1)95%  (19/20)88%  (7/8)
checkActive (): void 100% (1/1)100% (6/6)100% (3/3)
checkAutoCommit (boolean): void 100% (1/1)100% (1/1)100% (1/1)
checkCommit (): void 100% (1/1)100% (1/1)100% (1/1)
checkHoldCursors (int, boolean): int 100% (1/1)100% (2/2)100% (1/1)
checkRollback (): void 100% (1/1)100% (1/1)100% (1/1)
checkSavepoint (): void 100% (1/1)100% (1/1)100% (1/1)
close (): void 100% (1/1)88%  (30/34)98%  (11.7/12)
closeCurrentConnectionHandle (): void 100% (1/1)77%  (20/26)96%  (7.7/8)
closingConnection (): boolean 100% (1/1)100% (7/7)100% (3/3)
getConnection (): Connection 100% (1/1)100% (17/17)100% (7/7)
getNewCurrentConnectionHandle (): Connection 100% (1/1)100% (16/16)100% (3/3)
getPassword (): String 0%   (0/1)0%   (0/8)0%   (0/3)
getRealConnection (): EngineConnection 100% (1/1)100% (5/5)100% (2/2)
getUsername (): String 0%   (0/1)0%   (0/13)0%   (0/3)
isIsolationLevelSetUsingSQLorJDBC (): boolean 100% (1/1)100% (10/10)100% (3/3)
nextId (): int 100% (1/1)100% (6/6)100% (1/1)
notifyClose (): void 100% (1/1)100% (28/28)100% (7/7)
notifyError (SQLException): void 100% (1/1)26%  (9/34)38%  (3.4/9)
notifyException (SQLException): void 100% (1/1)100% (4/4)100% (2/2)
openRealConnection (): void 100% (1/1)100% (31/31)100% (7/7)
removeConnectionEventListener (ConnectionEventListener): void 100% (1/1)25%  (3/12)40%  (2/5)
resetIsolationLevelFlag (): void 100% (1/1)100% (5/5)100% (2/2)
resetRealConnection (): void 100% (1/1)100% (49/49)100% (12/12)
toString (): String 100% (1/1)100% (11/11)100% (3/3)
wrapStatement (CallableStatement, String): CallableStatement 0%   (0/1)0%   (0/2)0%   (0/1)
wrapStatement (PreparedStatement, String, Object): PreparedStatement 0%   (0/1)0%   (0/2)0%   (0/1)
wrapStatement (Statement): Statement 100% (1/1)100% (2/2)100% (1/1)

1/*
2 
3   Derby - Class org.apache.derby.jdbc.EmbedPooledConnection
4 
5   Copyright 2001, 2005 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11      http://www.apache.org/licenses/LICENSE-2.0
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 */
20 
21package org.apache.derby.jdbc;
22 
23import org.apache.derby.iapi.services.sanity.SanityManager;
24import org.apache.derby.iapi.reference.Property;
25import org.apache.derby.iapi.error.ExceptionSeverity;
26import org.apache.derby.iapi.reference.JDBC30Translation;
27 
28/* import impl class */
29import org.apache.derby.impl.jdbc.Util;
30import org.apache.derby.impl.jdbc.EmbedConnection;
31import org.apache.derby.iapi.jdbc.BrokeredConnection;
32import org.apache.derby.iapi.jdbc.BrokeredConnectionControl;
33import org.apache.derby.iapi.jdbc.EngineConnection;
34import org.apache.derby.impl.jdbc.EmbedPreparedStatement;
35import org.apache.derby.impl.jdbc.EmbedCallableStatement;
36 
37 
38import java.sql.Connection;
39import java.sql.SQLException;
40import java.sql.Statement;
41import java.sql.PreparedStatement;
42import java.sql.CallableStatement;
43 
44import java.util.Vector;
45import java.util.Enumeration;
46 
47/* -- New jdbc 20 extension types --- */
48import javax.sql.DataSource;
49import javax.sql.PooledConnection;
50import javax.sql.ConnectionEventListener;
51import javax.sql.ConnectionEvent;
52 
53/** 
54        A PooledConnection object is a connection object that provides hooks for
55        connection pool management.
56 
57        <P>This is Derby's implementation of a PooledConnection for use in
58        the following environments:
59        <UL>
60        <LI> JDBC 3.0 - Java 2 - JDK 1.4, J2SE 5.0
61        <LI> JDBC 2.0 - Java 2 - JDK 1.2,1.3
62        </UL>
63 
64 */
65class EmbedPooledConnection implements javax.sql.PooledConnection, BrokeredConnectionControl
66{
67 
68    /** Static counter for connection ids */
69    private static int idCounter = 0;
70    
71    /** The id for this connection.  */
72    private int connectionId;
73    
74    /** the connection string */
75    private String connString;
76    
77        private Vector eventListener; // who wants to know I am closed or error
78 
79        EmbedConnection realConnection;
80        int defaultIsolationLevel;
81        private boolean defaultReadOnly;
82        BrokeredConnection currentConnectionHandle;
83 
84        // set up once by the data source
85        final ReferenceableDataSource dataSource;
86        private final String username;
87        private final String password;
88        /**
89                True if the password was passed in on the connection request, false if it came from the data source property.
90        */
91        private final boolean requestPassword;
92 
93        protected boolean isActive;
94    
95    private synchronized int nextId()
96    {
97        return idCounter++;
98    }
99 
100        EmbedPooledConnection(ReferenceableDataSource ds, String u, String p, boolean requestPassword) throws SQLException
101        {
102        connectionId = nextId();
103 
104                dataSource = ds;
105                username = u;
106                password = p;
107                this.requestPassword = requestPassword;
108                isActive = true;
109 
110                // open the connection up front in order to do authentication
111                openRealConnection();
112 
113        }
114 
115        String getUsername()
116        {
117                if (username == null || username.equals(""))
118                        return Property.DEFAULT_USER_NAME;
119                else
120                        return username;
121        }
122 
123        String getPassword()
124        {
125                if (password == null)
126                        return "";
127                else
128                        return password;
129        }
130 
131 
132        /** 
133                Create an object handle for a database connection.
134 
135                @return a Connection object
136 
137                @exception SQLException - if a database-access error occurs.
138        */
139        public synchronized Connection getConnection() throws SQLException
140        {
141                checkActive();
142 
143                // need to do this in case the connection is forcibly removed without
144                // first being closed.
145                closeCurrentConnectionHandle();
146 
147 
148                // RealConnection is not null if the app server yanks a local
149                // connection from one client and give it to another.  In this case,
150                // the real connection is ready to be used.  Otherwise, set it up
151                if (realConnection == null)
152                {
153                        // first time we establish a connection
154                        openRealConnection();
155                }
156                else
157                {
158                        resetRealConnection();
159                }
160 
161                // now make a brokered connection wrapper and give this to the user
162                // we reuse the EmbedConnection(ie realConnection).
163                Connection c = getNewCurrentConnectionHandle();                
164                return c;
165        }
166 
167        final void openRealConnection() throws SQLException {
168                // first time we establish a connection
169                Connection rc = dataSource.getConnection(username, password, requestPassword);
170 
171                this.realConnection = (EmbedConnection) rc;
172                defaultIsolationLevel = rc.getTransactionIsolation();
173                defaultReadOnly = rc.isReadOnly();
174                if (currentConnectionHandle != null)
175                        realConnection.setApplicationConnection(currentConnectionHandle);
176        }
177 
178        final Connection getNewCurrentConnectionHandle() {
179                Connection applicationConnection = currentConnectionHandle =
180                        ((org.apache.derby.jdbc.Driver20) (realConnection.getLocalDriver())).newBrokeredConnection(this);
181                realConnection.setApplicationConnection(applicationConnection);
182                return applicationConnection;
183 
184        }
185 
186        /**
187                In this case the Listeners are *not* notified. JDBC 3.0 spec section 11.4
188        */
189        private void closeCurrentConnectionHandle() throws SQLException {
190                if (currentConnectionHandle != null)
191                {
192                        Vector tmpEventListener = eventListener;
193                        eventListener = null;
194 
195                        try {
196                                currentConnectionHandle.close();
197                        } finally {
198                                eventListener = tmpEventListener;
199                        }
200 
201                        currentConnectionHandle = null;
202                }
203        }
204 
205        void resetRealConnection() throws SQLException {
206 
207                // ensure any outstanding changes from the previous
208                // user are rolledback.
209                realConnection.rollback();
210 
211                // clear any warnings that are left over
212                realConnection.clearWarnings();
213 
214                // need to reset transaction isolation, autocommit, readonly, holdability states
215                if (realConnection.getTransactionIsolation() != defaultIsolationLevel) {
216 
217                        realConnection.setTransactionIsolation(defaultIsolationLevel);
218                }
219 
220                if (!realConnection.getAutoCommit())
221                        realConnection.setAutoCommit(true);
222 
223                if (realConnection.isReadOnly() != defaultReadOnly)
224                        realConnection.setReadOnly(defaultReadOnly);
225 
226                if (realConnection.getHoldability() != JDBC30Translation.HOLD_CURSORS_OVER_COMMIT)
227                        realConnection.setHoldability(JDBC30Translation.HOLD_CURSORS_OVER_COMMIT);
228 
229                // reset any remaining state of the connection
230                realConnection.resetFromPool();
231        }
232 
233        /**
234                Close the Pooled connection.
235 
236                @exception SQLException - if a database-access error occurs.
237         */
238        public synchronized void close() throws SQLException
239        {
240                if (!isActive)
241                        return;
242 
243                closeCurrentConnectionHandle();
244                try {
245                        if (realConnection != null) {
246                                if (!realConnection.isClosed())
247                                        realConnection.close();
248                        }
249 
250                } finally {
251 
252                        realConnection = null;        // make sure I am not accessed again.
253                        isActive = false;
254                        eventListener = null;
255                }
256        }
257 
258        /**
259                Add an event listener.
260         */
261        public final synchronized void addConnectionEventListener(ConnectionEventListener listener) 
262        {
263                if (!isActive)
264                        return;
265                if (listener == null)
266                        return;
267                if (eventListener == null)
268                        eventListener = new Vector();
269                eventListener.addElement(listener);
270        }
271 
272        /**
273                Remove an event listener.
274         */
275        public final synchronized void removeConnectionEventListener(ConnectionEventListener listener)
276        {
277                if (listener == null)
278                        return;
279                if (eventListener != null)
280                        eventListener.removeElement(listener);
281        }
282 
283        /*
284         * class specific method
285         */
286 
287        // called by ConnectionHandle when it needs to forward things to the
288        // underlying connection
289        public synchronized EngineConnection getRealConnection()
290       throws SQLException
291        {
292                checkActive();
293 
294                return realConnection;
295        }
296 
297 
298        // my conneciton handle has caught an error (actually, the real connection
299        // has already handled the error, we just need to nofity the listener an
300        // error is about to be thrown to the app).
301        public synchronized void notifyError(SQLException exception)
302        {
303                // only report fatal error to the connection pool manager 
304                if (exception.getErrorCode() < ExceptionSeverity.SESSION_SEVERITY)
305                        return;
306 
307                // tell my listeners an exception is about to be thrown
308                if (eventListener != null && eventListener.size() > 0)
309                {
310                        ConnectionEvent errorEvent = new ConnectionEvent(this, exception);
311 
312                        for (Enumeration e = eventListener.elements();
313                                 e.hasMoreElements(); )
314                        {
315                                ConnectionEventListener l =
316                                        (ConnectionEventListener)e.nextElement();
317                                l.connectionErrorOccurred(errorEvent);
318                        }
319                }
320        }
321 
322        // my conneciton handle is being closed
323        public synchronized void notifyClose()
324        {
325                // tell my listeners I am closed 
326                if (eventListener != null && eventListener.size() > 0)
327                {
328                        ConnectionEvent closeEvent = new ConnectionEvent(this);
329 
330                        for (Enumeration e = eventListener.elements();
331                                 e.hasMoreElements(); )
332                        {
333                                ConnectionEventListener l =
334                                        (ConnectionEventListener)e.nextElement();
335                                l.connectionClosed(closeEvent);
336                        }
337                }
338        }
339 
340        final void checkActive() throws SQLException {
341                if (!isActive)
342                        throw Util.noCurrentConnection();
343        }
344 
345 
346        /*
347        ** BrokeredConnectionControl api
348        */
349 
350        /**
351                Returns true if isolation level has been set using either JDBC api or SQL
352         */
353        public boolean isIsolationLevelSetUsingSQLorJDBC() throws SQLException {
354                if (realConnection != null)
355                        return realConnection.getLanguageConnection().isIsolationLevelSetUsingSQLorJDBC();
356                else
357                        return false;
358        }
359 
360        /**
361                Reset the isolation level flag used to keep state in 
362                BrokeredConnection. It will get set to true when isolation level 
363                is set using JDBC/SQL. It will get reset to false at the start
364                and the end of a global transaction.
365        */
366        public void resetIsolationLevelFlag() throws SQLException {
367                realConnection.getLanguageConnection().resetIsolationLevelFlagUsedForSQLandJDBC();
368        }
369        
370        
371        /**
372                Notify the control class that a SQLException was thrown
373                during a call on one of the brokered connection's methods.
374        */
375        public void notifyException(SQLException sqle) {
376                this.notifyError(sqle);
377        }
378 
379 
380        /**
381                Allow control over setting auto commit mode.
382        */
383        public void checkAutoCommit(boolean autoCommit) throws SQLException {
384        }
385 
386        /**
387                Are held cursors allowed.
388        */
389        public int checkHoldCursors(int holdability, boolean downgrade)
390        throws SQLException
391    {
392        return holdability;
393        }
394 
395        /**
396                Allow control over creating a Savepoint (JDBC 3.0)
397        */
398        public void checkSavepoint() throws SQLException {
399        }
400 
401        /**
402                Allow control over calling rollback.
403        */
404        public void checkRollback() throws SQLException {
405        }
406 
407        /**
408                Allow control over calling commit.
409        */
410        public void checkCommit() throws SQLException {
411        }
412 
413        /**
414                Close called on BrokeredConnection. If this call
415                returns true then getRealConnection().close() will be called.
416 
417                Don't close the underlying real connection as
418                it is pooled.
419        */
420        public boolean closingConnection() throws SQLException {
421                notifyClose();
422                currentConnectionHandle = null;
423                return false;
424        }
425 
426        /**
427                No need to wrap statements for PooledConnections.
428        */
429        public Statement wrapStatement(Statement s) throws SQLException {
430                return s;
431        }
432        /**
433         * Call the setBrokeredConnectionControl method inside the 
434         * EmbedPreparedStatement class to set the BrokeredConnectionControl 
435         * variable to this instance of EmbedPooledConnection
436         * This will then be used to call the onStatementErrorOccurred
437         * and onStatementClose events when the corresponding events
438         * occur on the PreparedStatement
439         *
440         * @param  ps            PreparedStatment to be wrapped
441         * @param  sql           String
442         * @param  generatedKeys Object
443         * @return returns the wrapped PreparedStatement
444         * @throws java.sql.SQLException
445         */
446        public PreparedStatement wrapStatement(PreparedStatement ps, String sql, Object generatedKeys) throws SQLException {
447               /*
448                    
449                */
450                EmbedPreparedStatement ps_ = (EmbedPreparedStatement)ps;
451                ps_.setBrokeredConnectionControl(this);
452                return (PreparedStatement)ps_;
453        }
454        
455        /**
456         * Call the setBrokeredConnectionControl method inside the 
457         * EmbedCallableStatement class to set the BrokeredConnectionControl 
458         * variable to this instance of EmbedPooledConnection
459         * This will then be used to call the onStatementErrorOccurred
460         * and onStatementClose events when the corresponding events
461         * occur on the CallableStatement
462         *
463         * @param  cs            CallableStatment to be wrapped
464         * @param  sql           String
465         * @return returns the wrapped CallableStatement
466         * @throws java.sql.SQLException
467         */
468        public CallableStatement wrapStatement(CallableStatement cs, String sql) throws SQLException {
469                EmbedCallableStatement cs_ = (EmbedCallableStatement)cs;
470                cs_.setBrokeredConnectionControl(this);
471                return (CallableStatement)cs_;
472        }
473    
474    /** 
475     * Get the string representation of this pooled connection.
476     *
477     * A pooled connection is assigned a separate id from a physical 
478     * connection. When a container calls PooledConnection.toString(), 
479     * it gets the string representation of this id. This is useful for 
480     * developers implementing connection pools when they are trying to
481     * debug pooled connections. 
482     *
483     * @return a string representation of the uniquie id for this pooled
484     *    connection.
485     *
486     */
487    public String toString()
488    {
489        if ( connString == null )
490        {
491            String physicalConnString = isActive ?
492                realConnection.toString() : "<none>";
493            
494            connString = 
495              this.getClass().getName() + "@" + this.hashCode() + " " +
496                "(ID = " + connectionId + "), " +
497                "Physical Connection = " + physicalConnString;
498        }    
499        
500        return connString;
501    }
502    
503    /*-----------------------------------------------------------------*/
504    /*
505     * These methods are from the BrokeredConnectionControl interface. 
506     * These methods are needed to provide StatementEvent support for 
507     * derby. 
508     * They are actually implemented in EmbedPooledConnection40 but have
509     * a dummy implementation here so that the compilation wont fail when they
510     * are compiled with jdk1.4
511     */
512    
513    /**
514     * Dummy implementation for the actual methods found in 
515     * org.apache.derby.jdbc.EmbedPooledConnection40
516     * @param statement PreparedStatement
517     */
518    public void onStatementClose(PreparedStatement statement) {
519        
520    }
521    
522    /**
523     * Dummy implementation for the actual methods found in 
524     * org.apache.derby.jdbc.EmbedPooledConnection40
525     * @param statement PreparedStatement
526     * @param sqle      SQLException 
527     */
528    public void onStatementErrorOccurred(PreparedStatement statement,
529            SQLException sqle) {
530        
531    }
532}

[all classes][org.apache.derby.jdbc]
EMMA 2.0.5312 (C) Vladimir Roubtsov