View Javadoc

1   /*
2    ~ Copyright 2006-2007 Nicolas De Loof.
3    ~
4    ~ Licensed under the Apache License, Version 2.0 (the "License");
5    ~ you may not use this file except in compliance with the License.
6    ~ You may obtain a copy of the License at
7    ~
8    ~      http://www.apache.org/licenses/LICENSE-2.0
9    ~
10   ~ Unless required by applicable law or agreed to in writing, software
11   ~ distributed under the License is distributed on an "AS IS" BASIS,
12   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   ~ See the License for the specific language governing permissions and
14   ~ limitations under the License.
15   */
16  package org.jmonit.support.jdbc;
17  
18  import java.lang.reflect.Proxy;
19  import java.sql.Array;
20  import java.sql.Blob;
21  import java.sql.CallableStatement;
22  import java.sql.Clob;
23  import java.sql.Connection;
24  import java.sql.DatabaseMetaData;
25  import java.sql.NClob;
26  import java.sql.PreparedStatement;
27  import java.sql.SQLClientInfoException;
28  import java.sql.SQLException;
29  import java.sql.SQLWarning;
30  import java.sql.SQLXML;
31  import java.sql.Savepoint;
32  import java.sql.Statement;
33  import java.sql.Struct;
34  import java.util.Map;
35  import java.util.Properties;
36  
37  import org.jmonit.Stopwatch;
38  
39  /**
40   * Wrapper around a JDBC connection. Only implements Java 1.3 JDBC-2.0 api to be
41   * fully compatible with Java 1.3 runtime.
42   * 
43   * @author <a href="mailto:ndeloof@sourceforge.net">Nicolas De Loof</a>
44   */
45  public class MonitoredConnection
46      implements Connection
47  {
48  
49      /** target connection */
50      private Connection connection;
51  
52      /** Probe for this connection */
53      private Stopwatch connectionOpen;
54  
55      /** Monitor for this connection */
56      private JdbcMonitor monitor;
57  
58      /**
59       * @param connection target connection
60       * @param monitor monitor for opened connections
61       */
62      public MonitoredConnection( Connection connection, JdbcMonitor monitor )
63      {
64          super();
65          this.connection = connection;
66          this.monitor = monitor;
67          connectionOpen = Stopwatch.start( monitor.getConnectionMonitor() );
68      }
69  
70      /**
71       * {@inheritDoc}
72       * 
73       * @see java.sql.Connection#clearWarnings()
74       */
75      public void clearWarnings()
76          throws SQLException
77      {
78          connection.clearWarnings();
79      }
80  
81      /**
82       * {@inheritDoc}
83       * 
84       * @see java.sql.Connection#close()
85       */
86      public void close()
87          throws SQLException
88      {
89          connection.close();
90          connectionOpen.stop();
91      }
92  
93      /**
94       * {@inheritDoc}
95       * 
96       * @see java.sql.Connection#commit()
97       */
98      public void commit()
99          throws SQLException
100     {
101         connection.commit();
102     }
103 
104     /**
105      * {@inheritDoc}
106      * 
107      * @see java.sql.Connection#createStatement()
108      */
109     public Statement createStatement()
110         throws SQLException
111     {
112         Statement statement = connection.createStatement();
113         return wrapp( statement );
114     }
115 
116     /**
117      * {@inheritDoc}
118      * 
119      * @see java.sql.Connection#createStatement(int, int)
120      */
121     public Statement createStatement( int resultSetType, int resultSetConcurrency )
122         throws SQLException
123     {
124         Statement statement = connection.createStatement( resultSetType, resultSetConcurrency );
125         return wrapp( statement );
126     }
127 
128     /**
129      * {@inheritDoc}
130      * 
131      * @see java.sql.Connection#getAutoCommit()
132      */
133     public boolean getAutoCommit()
134         throws SQLException
135     {
136         return connection.getAutoCommit();
137     }
138 
139     /**
140      * {@inheritDoc}
141      * 
142      * @see java.sql.Connection#getCatalog()
143      */
144     public String getCatalog()
145         throws SQLException
146     {
147         return connection.getCatalog();
148     }
149 
150     /**
151      * {@inheritDoc}
152      * 
153      * @see java.sql.Connection#getMetaData()
154      */
155     public DatabaseMetaData getMetaData()
156         throws SQLException
157     {
158         return connection.getMetaData();
159     }
160 
161     /**
162      * {@inheritDoc}
163      * 
164      * @see java.sql.Connection#getTransactionIsolation()
165      */
166     public int getTransactionIsolation()
167         throws SQLException
168     {
169         return connection.getTransactionIsolation();
170     }
171 
172     /**
173      * {@inheritDoc}
174      * 
175      * @see java.sql.Connection#getTypeMap()
176      */
177     public Map getTypeMap()
178         throws SQLException
179     {
180         return connection.getTypeMap();
181     }
182 
183     /**
184      * {@inheritDoc}
185      * 
186      * @see java.sql.Connection#getWarnings()
187      */
188     public SQLWarning getWarnings()
189         throws SQLException
190     {
191         return connection.getWarnings();
192     }
193 
194     /**
195      * {@inheritDoc}
196      * 
197      * @see java.sql.Connection#isClosed()
198      */
199     public boolean isClosed()
200         throws SQLException
201     {
202         return connection.isClosed();
203     }
204 
205     /**
206      * {@inheritDoc}
207      * 
208      * @see java.sql.Connection#isReadOnly()
209      */
210     public boolean isReadOnly()
211         throws SQLException
212     {
213         return connection.isReadOnly();
214     }
215 
216     /**
217      * {@inheritDoc}
218      * 
219      * @see java.sql.Connection#nativeSQL(java.lang.String)
220      */
221     public String nativeSQL( String sql )
222         throws SQLException
223     {
224         return connection.nativeSQL( sql );
225     }
226 
227     /**
228      * {@inheritDoc}
229      * 
230      * @see java.sql.Connection#prepareCall(java.lang.String, int, int)
231      */
232     public CallableStatement prepareCall( String sql, int resultSetType, int resultSetConcurrency )
233         throws SQLException
234     {
235         CallableStatement statement =
236             connection.prepareCall( sql, resultSetType, resultSetConcurrency );
237         return wrapp( statement, sql );
238     }
239 
240     /**
241      * {@inheritDoc}
242      * 
243      * @see java.sql.Connection#prepareCall(java.lang.String)
244      */
245     public CallableStatement prepareCall( String sql )
246         throws SQLException
247     {
248         CallableStatement statement = connection.prepareCall( sql );
249         return wrapp( statement, sql );
250     }
251 
252     /**
253      * {@inheritDoc}
254      * 
255      * @see java.sql.Connection#prepareStatement(java.lang.String, int, int)
256      */
257     public PreparedStatement prepareStatement( String sql, int resultSetType,
258                                                int resultSetConcurrency )
259         throws SQLException
260     {
261         PreparedStatement statement =
262             connection.prepareStatement( sql, resultSetType, resultSetConcurrency );
263         return wrapp( statement, sql );
264     }
265 
266     /**
267      * {@inheritDoc}
268      * 
269      * @see java.sql.Connection#prepareStatement(java.lang.String)
270      */
271     public PreparedStatement prepareStatement( String sql )
272         throws SQLException
273     {
274         PreparedStatement statement = connection.prepareStatement( sql );
275         return wrapp( statement, sql );
276     }
277 
278     /**
279      * {@inheritDoc}
280      * 
281      * @see java.sql.Connection#rollback()
282      */
283     public void rollback()
284         throws SQLException
285     {
286         connection.rollback();
287     }
288 
289     /**
290      * {@inheritDoc}
291      * 
292      * @see java.sql.Connection#setAutoCommit(boolean)
293      */
294     public void setAutoCommit( boolean autoCommit )
295         throws SQLException
296     {
297         connection.setAutoCommit( autoCommit );
298     }
299 
300     /**
301      * {@inheritDoc}
302      * 
303      * @see java.sql.Connection#setCatalog(java.lang.String)
304      */
305     public void setCatalog( String catalog )
306         throws SQLException
307     {
308         connection.setCatalog( catalog );
309     }
310 
311     /**
312      * {@inheritDoc}
313      * 
314      * @see java.sql.Connection#setReadOnly(boolean)
315      */
316     public void setReadOnly( boolean readOnly )
317         throws SQLException
318     {
319         connection.setReadOnly( readOnly );
320     }
321 
322     /**
323      * {@inheritDoc}
324      * 
325      * @see java.sql.Connection#setTransactionIsolation(int)
326      */
327     public void setTransactionIsolation( int level )
328         throws SQLException
329     {
330         connection.setTransactionIsolation( level );
331     }
332 
333     /**
334      * {@inheritDoc}
335      * 
336      * @see java.sql.Connection#setTypeMap(java.util.Map)
337      */
338     public void setTypeMap( Map arg0 )
339         throws SQLException
340     {
341         connection.setTypeMap( arg0 );
342     }
343 
344     /**
345      * @return the connection
346      */
347     protected Connection getTargetConnection()
348     {
349         return connection;
350     }
351 
352     /**
353      * @param statement traget Statement
354      * @return monitored Statement
355      */
356     protected Statement wrapp( Statement statement )
357     {
358         return new MonitoredStatement( statement, this, monitor );
359     }
360 
361     /**
362      * @param statement traget PreparedStatement
363      * @param sql SQL Query
364      * @return monitored PreparedStatement
365      */
366     protected PreparedStatement wrapp( PreparedStatement statement, String sql )
367     {
368         return new MonitoredPreparedStatement( statement, sql, this, monitor );
369     }
370 
371     /**
372      * @param statement target PreparedStatement
373      * @param sql SQL Query
374      * @return Monitored CallableStatement
375      */
376     protected CallableStatement wrapp( CallableStatement statement, String sql )
377     {
378         return new MonitoredCallableStatement( statement, sql, this, monitor );
379     }
380 
381     /**
382      * {@inheritDoc}
383      * 
384      * @see java.sql.Connection#createStatement(int, int, int)
385      */
386     public Statement createStatement( int resultSetType, int resultSetConcurrency,
387                                       int resultSetHoldability )
388         throws SQLException
389     {
390         Statement statement =
391             getTargetConnection().createStatement( resultSetType, resultSetConcurrency,
392                 resultSetHoldability );
393         return new MonitoredStatement( statement, this, monitor );
394     }
395 
396     /**
397      * {@inheritDoc}
398      * 
399      * @see java.sql.Connection#getHoldability()
400      */
401     public int getHoldability()
402         throws SQLException
403     {
404         return getTargetConnection().getHoldability();
405     }
406 
407     /**
408      * {@inheritDoc}
409      * 
410      * @see java.sql.Connection#prepareCall(java.lang.String, int, int, int)
411      */
412     public CallableStatement prepareCall( String sql, int resultSetType, int resultSetConcurrency,
413                                           int resultSetHoldability )
414         throws SQLException
415     {
416         CallableStatement statement =
417             getTargetConnection().prepareCall( sql, resultSetType, resultSetConcurrency,
418                 resultSetHoldability );
419         return new MonitoredCallableStatement( statement, sql, this, monitor );
420     }
421 
422     /**
423      * {@inheritDoc}
424      * 
425      * @see java.sql.Connection#prepareStatement(java.lang.String, int, int,
426      * int)
427      */
428     public PreparedStatement prepareStatement( String sql, int resultSetType,
429                                                int resultSetConcurrency, int resultSetHoldability )
430         throws SQLException
431     {
432         PreparedStatement statement =
433             getTargetConnection().prepareStatement( sql, resultSetType, resultSetConcurrency,
434                 resultSetHoldability );
435         return new MonitoredPreparedStatement( statement, sql, this, monitor );
436     }
437 
438     /**
439      * {@inheritDoc}
440      * 
441      * @see java.sql.Connection#prepareStatement(java.lang.String, int)
442      */
443     public PreparedStatement prepareStatement( String sql, int autoGeneratedKeys )
444         throws SQLException
445     {
446         PreparedStatement statement =
447             getTargetConnection().prepareStatement( sql, autoGeneratedKeys );
448         return new MonitoredPreparedStatement( statement, sql, this, monitor );
449     }
450 
451     /**
452      * Optionnaly use a java.lang.relect Proxy for statement in place of
453      * hard-coded ones to bypass JDBC API version conflicts
454      */
455     boolean useProxy;
456 
457     private PreparedStatement monitor( PreparedStatement statement, String sql )
458     {
459         if ( useProxy )
460         {
461             ClassLoader cl = Thread.currentThread().getContextClassLoader();
462             if ( cl == null )
463             {
464                 cl = getClass().getClassLoader();
465             }
466             return (PreparedStatement) Proxy.newProxyInstance( cl,
467                 new Class[] { PreparedStatement.class }, null );
468         }
469         else
470         {
471             return new MonitoredPreparedStatement( statement, sql, this, monitor );
472         }
473     }
474 
475     /**
476      * {@inheritDoc}
477      * 
478      * @see java.sql.Connection#prepareStatement(java.lang.String, int[])
479      */
480     public PreparedStatement prepareStatement( String sql, int[] columnIndexes )
481         throws SQLException
482     {
483         PreparedStatement statement = getTargetConnection().prepareStatement( sql, columnIndexes );
484         return new MonitoredPreparedStatement( statement, sql, this, monitor );
485     }
486 
487     /**
488      * {@inheritDoc}
489      * 
490      * @see java.sql.Connection#prepareStatement(java.lang.String,
491      * java.lang.String[])
492      */
493     public PreparedStatement prepareStatement( String sql, String[] columnNames )
494         throws SQLException
495     {
496         PreparedStatement statement = getTargetConnection().prepareStatement( sql, columnNames );
497         return new MonitoredPreparedStatement( statement, sql, this, monitor );
498     }
499 
500     /**
501      * {@inheritDoc}
502      * 
503      * @see java.sql.Connection#releaseSavepoint(java.sql.Savepoint)
504      */
505     public void releaseSavepoint( Savepoint savepoint )
506         throws SQLException
507     {
508         getTargetConnection().releaseSavepoint( savepoint );
509     }
510 
511     /**
512      * {@inheritDoc}
513      * 
514      * @see java.sql.Connection#rollback(java.sql.Savepoint)
515      */
516     public void rollback( Savepoint savepoint )
517         throws SQLException
518     {
519         getTargetConnection().rollback( savepoint );
520     }
521 
522     /**
523      * {@inheritDoc}
524      * 
525      * @see java.sql.Connection#setHoldability(int)
526      */
527     public void setHoldability( int holdability )
528         throws SQLException
529     {
530         getTargetConnection().setHoldability( holdability );
531     }
532 
533     /**
534      * {@inheritDoc}
535      * 
536      * @see java.sql.Connection#setSavepoint()
537      */
538     public Savepoint setSavepoint()
539         throws SQLException
540     {
541         return getTargetConnection().setSavepoint();
542     }
543 
544     /**
545      * {@inheritDoc}
546      * 
547      * @see java.sql.Connection#setSavepoint(java.lang.String)
548      */
549     public Savepoint setSavepoint( String name )
550         throws SQLException
551     {
552         return getTargetConnection().setSavepoint( name );
553     }
554 
555     public final Array createArrayOf( String typeName, Object[] elements )
556         throws SQLException
557     {
558         return connection.createArrayOf( typeName, elements );
559     }
560 
561     public final Blob createBlob()
562         throws SQLException
563     {
564         return connection.createBlob();
565     }
566 
567     public final Clob createClob()
568         throws SQLException
569     {
570         return connection.createClob();
571     }
572 
573     public final NClob createNClob()
574         throws SQLException
575     {
576         return connection.createNClob();
577     }
578 
579     public final SQLXML createSQLXML()
580         throws SQLException
581     {
582         return connection.createSQLXML();
583     }
584 
585     public final Struct createStruct( String typeName, Object[] attributes )
586         throws SQLException
587     {
588         return connection.createStruct( typeName, attributes );
589     }
590 
591     public final Properties getClientInfo()
592         throws SQLException
593     {
594         return connection.getClientInfo();
595     }
596 
597     public final String getClientInfo( String name )
598         throws SQLException
599     {
600         return connection.getClientInfo( name );
601     }
602 
603     public final boolean isValid( int timeout )
604         throws SQLException
605     {
606         return connection.isValid( timeout );
607     }
608 
609     public final boolean isWrapperFor( Class<?> iface )
610         throws SQLException
611     {
612         return connection.isWrapperFor( iface );
613     }
614 
615     public final void setClientInfo( Properties properties )
616         throws SQLClientInfoException
617     {
618         connection.setClientInfo( properties );
619     }
620 
621     public final void setClientInfo( String name, String value )
622         throws SQLClientInfoException
623     {
624         connection.setClientInfo( name, value );
625     }
626 
627     public final <T> T unwrap( Class<T> iface )
628         throws SQLException
629     {
630         return connection.unwrap( iface );
631     }
632 
633 }