001package org.javasimon.jdbc4;
002
003import java.sql.Array;
004import java.sql.Blob;
005import java.sql.CallableStatement;
006import java.sql.Clob;
007import java.sql.Connection;
008import java.sql.DatabaseMetaData;
009import java.sql.NClob;
010import java.sql.PreparedStatement;
011import java.sql.SQLClientInfoException;
012import java.sql.SQLException;
013import java.sql.SQLWarning;
014import java.sql.SQLXML;
015import java.sql.Savepoint;
016import java.sql.Statement;
017import java.sql.Struct;
018import java.util.Map;
019import java.util.Properties;
020import java.util.concurrent.Executor;
021
022import org.javasimon.Counter;
023import org.javasimon.SimonManager;
024import org.javasimon.Split;
025
026/**
027 * Class implements Simon JDBC proxy connection.
028 * <p>
029 * Every method of this connection is implemented as call of real connection method.
030 * Several methods have added work with Simons (starting, stopping, etc.) for monitoring
031 * purposes.
032 * </p>
033 * <p>
034 * From all statement-return-methods (<code>createStatement(*)</code>,
035 * <code>prepareStatement(*)</code>, <code>prepareCall(*)</code>) connection returns own
036 * implementation of statement classes. Those classes are also proxies and provides
037 * additional Simons for monitoring features of JDBC driver.
038 * </p>
039 * Monitoring connection ensure following Simons:
040 * <ul>
041 * <li>lifespan (<code>org.javasimon.jdbc4.conn</code>, stopwatch) - measure connection life and count</li>
042 * <li>commits (<code>org.javasimon.jdbc4.conn.commits</code>, counter) - measure executed commits of all connections</li>
043 * <li>rollbacks (<code>org.javasimon.jdbc4.conn.rollbacks</code>, counter) - measure executed rollbacks of all connections</li>
044 * </ul>
045 *
046 * @author Radovan Sninsky
047 * @see java.sql.Connection
048 * @since 2.4
049 */
050public final class SimonConnection implements Connection {
051        private final Connection conn;
052        private final WrapperSupport<Connection> wrapperSupport;
053        private String prefix;
054
055        private Split life;
056        private Counter commits;
057        private Counter rollbacks;
058
059        /**
060         * Class constructor, initializes Simons (lifespan, active, commits
061         * and rollbacks) related to the DB connection.
062         *
063         * @param conn real DB connection
064         * @param prefix hierarchy prefix for connection Simons
065         */
066        public SimonConnection(Connection conn, String prefix) {
067                this.conn = conn;
068                this.wrapperSupport = new WrapperSupport<>(this.conn, Connection.class);
069                this.prefix = prefix;
070
071                commits = SimonManager.getCounter(prefix + ".conn.commits");
072                rollbacks = SimonManager.getCounter(prefix + ".conn.rollbacks");
073                life = SimonManager.getStopwatch(prefix + ".conn").start();
074        }
075
076        /**
077         * Closes the real connection, stops lifespan Simon and decreases the active Simon.
078         *
079         * @throws java.sql.SQLException if real operation fails
080         */
081        @Override
082        public void close() throws SQLException {
083                conn.close();
084
085                life.stop();
086        }
087
088        /**
089         * Commits the real connection and increases the commits Simon.
090         *
091         * @throws java.sql.SQLException if real commit fails
092         */
093        @Override
094        public void commit() throws SQLException {
095                conn.commit();
096
097                commits.increase();
098        }
099
100        /**
101         * Rollback the real connection and increase the rollbacks Simon.
102         *
103         * @throws java.sql.SQLException if real operation fails
104         */
105        @Override
106        public void rollback() throws SQLException {
107                conn.rollback();
108
109                rollbacks.increase();
110        }
111
112        /**
113         * Rollbacks the real connection and increases the rollbacks Simon.
114         *
115         * @param savepoint the <code>Savepoint</code> object to roll back to
116         * @throws java.sql.SQLException if real operation fails
117         */
118        @Override
119        public void rollback(Savepoint savepoint) throws SQLException {
120                conn.rollback(savepoint);
121
122                rollbacks.increase();
123        }
124
125        /**
126         * Calls the real createStatement and wraps the returned statement by Simon's statement.
127         *
128         * @return Simon's statement with wrapped real statement
129         * @throws java.sql.SQLException if real operation fails
130         */
131        @Override
132        public Statement createStatement() throws SQLException {
133                return new SimonStatement(this, conn.createStatement(), prefix);
134        }
135
136        /**
137         * Calls real createStatement and wraps returned statement by Simon's statement.
138         *
139         * @param rsType result set type
140         * @param rsConcurrency result set concurrency
141         * @return Simon's statement with wrapped real statement
142         * @throws java.sql.SQLException if real operation fails
143         */
144        @Override
145        public Statement createStatement(int rsType, int rsConcurrency) throws SQLException {
146                return new SimonStatement(this, conn.createStatement(rsType, rsConcurrency), prefix);
147        }
148
149        /**
150         * Calls real createStatement and wraps returned statement by Simon's statement.
151         *
152         * @param rsType result set type
153         * @param rsConcurrency result set concurrency
154         * @param rsHoldability result set holdability
155         * @return Simon's statement with wrapped real statement
156         * @throws java.sql.SQLException if real operation fails
157         */
158        @Override
159        public Statement createStatement(int rsType, int rsConcurrency, int rsHoldability) throws SQLException {
160                return new SimonStatement(this, conn.createStatement(rsType, rsConcurrency, rsHoldability), prefix);
161        }
162
163        /**
164         * Calls real prepareStatement and wraps returned statement by Simon's statement.
165         *
166         * @param sql SQL statement
167         * @return Simon's statement with wrapped real statement
168         * @throws java.sql.SQLException if real operation fails
169         */
170        @Override
171        public PreparedStatement prepareStatement(String sql) throws SQLException {
172                return new SimonPreparedStatement(this, conn.prepareStatement(sql), sql, prefix);
173        }
174
175        /**
176         * Calls real prepareStatement and wraps returned statement by Simon's statement.
177         *
178         * @param sql SQL statement
179         * @param autoGeneratedKeys auto generated keys
180         * @return Simon's statement with wrapped real statement
181         * @throws java.sql.SQLException if real operation fails
182         */
183        @Override
184        public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
185                return new SimonPreparedStatement(this, conn.prepareStatement(sql, autoGeneratedKeys), sql, prefix);
186        }
187
188        /**
189         * Calls real prepareStatement and wraps returned statement by Simon's statement.
190         *
191         * @param sql SQL statement
192         * @param rsType result set type
193         * @param rsConcurrency result set concurrency
194         * @return Simon's statement with wrapped real statement
195         * @throws java.sql.SQLException if real operation fails
196         */
197        @Override
198        public PreparedStatement prepareStatement(String sql, int rsType, int rsConcurrency) throws SQLException {
199                return new SimonPreparedStatement(this, conn.prepareStatement(sql, rsType, rsConcurrency), sql, prefix);
200        }
201
202        /**
203         * Calls real prepareStatement and wraps returned statement by Simon's statement.
204         *
205         * @param sql SQL statement
206         * @param rsType result set type
207         * @param rsConcurrency result set concurrency
208         * @param rsHoldability result set holdability
209         * @return Simon's statement with wrapped real statement
210         * @throws java.sql.SQLException if real operation fails
211         */
212        @Override
213        public PreparedStatement prepareStatement(String sql, int rsType, int rsConcurrency, int rsHoldability) throws SQLException {
214                return new SimonPreparedStatement(this, conn.prepareStatement(sql, rsType, rsConcurrency, rsHoldability), sql, prefix);
215        }
216
217        /**
218         * Calls real prepareStatement and wraps returned statement by Simon's statement.
219         *
220         * @param sql SQL statement
221         * @param columnIndexes an array of column indexes indicating the columns
222         * that should be returned from the inserted row or rows
223         * @return Simon's statement with wrapped real statement
224         * @throws java.sql.SQLException if real operation fails
225         */
226        @Override
227        public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
228                return new SimonPreparedStatement(this, conn.prepareStatement(sql, columnIndexes), sql, prefix);
229        }
230
231        /**
232         * Calls real prepareStatement and wraps returned statement by Simon's statement.
233         *
234         * @param sql SQL statement
235         * @param columnNames an array of column names indicating the columns
236         * that should be returned from the inserted row or rows
237         * @return Simon's statement with wrapped real statement
238         * @throws java.sql.SQLException if real operation fails
239         */
240        @Override
241        public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
242                return new SimonPreparedStatement(this, conn.prepareStatement(sql, columnNames), sql, prefix);
243        }
244
245        /**
246         * Calls real prepareCall and wraps returned statement by Simon's statement.
247         *
248         * @param sql an SQL statement, typically a JDBC function call escape string
249         * @return Simon's statement with wrapped real statement
250         * @throws java.sql.SQLException if real operation fails
251         */
252        @Override
253        public CallableStatement prepareCall(String sql) throws SQLException {
254                return new SimonCallableStatement(conn, conn.prepareCall(sql), sql, prefix);
255        }
256
257        /**
258         * Calls real prepareCall and wraps returned statement by Simon's statement.
259         *
260         * @param sql an SQL statement, typically a JDBC function call escape string
261         * @param rsType result set type
262         * @param rsConcurrency result set concurrency
263         * @return Simon's statement with wrapped real statement
264         * @throws java.sql.SQLException if real operation fails
265         */
266        @Override
267        public CallableStatement prepareCall(String sql, int rsType, int rsConcurrency) throws SQLException {
268                return new SimonCallableStatement(conn, conn.prepareCall(sql, rsType, rsConcurrency), sql, prefix);
269        }
270
271        /**
272         * Calls real prepareCall and wraps returned statement by Simon's statement.
273         *
274         * @param sql an SQL statement, typically a JDBC function call escape string
275         * @param rsType result set type
276         * @param rsConcurrency result set concurrency
277         * @param rsHoldability result set holdability
278         * @return Simon's statement with wrapped real statement
279         * @throws java.sql.SQLException if real operation fails
280         */
281        @Override
282        public CallableStatement prepareCall(String sql, int rsType, int rsConcurrency, int rsHoldability) throws SQLException {
283                return new SimonCallableStatement(conn, conn.prepareCall(sql, rsType, rsConcurrency, rsHoldability), sql, prefix);
284        }
285
286        //// NOT MONITORED
287
288        @Override
289        public String nativeSQL(String s) throws SQLException {
290                return conn.nativeSQL(s);
291        }
292
293        @Override
294        public void setAutoCommit(boolean b) throws SQLException {
295                conn.setAutoCommit(b);
296        }
297
298        @Override
299        public boolean getAutoCommit() throws SQLException {
300                return conn.getAutoCommit();
301        }
302
303        @Override
304        public boolean isClosed() throws SQLException {
305                return conn.isClosed();
306        }
307
308        @Override
309        public DatabaseMetaData getMetaData() throws SQLException {
310                return conn.getMetaData();
311        }
312
313        @Override
314        public void setReadOnly(boolean b) throws SQLException {
315                conn.setReadOnly(b);
316        }
317
318        @Override
319        public boolean isReadOnly() throws SQLException {
320                return conn.isReadOnly();
321        }
322
323        @Override
324        public void setCatalog(String s) throws SQLException {
325                conn.setCatalog(s);
326        }
327
328        @Override
329        public String getCatalog() throws SQLException {
330                return conn.getCatalog();
331        }
332
333        @Override
334        public void setTransactionIsolation(int i) throws SQLException {
335                conn.setTransactionIsolation(i);
336        }
337
338        @Override
339        public int getTransactionIsolation() throws SQLException {
340                return conn.getTransactionIsolation();
341        }
342
343        @Override
344        public SQLWarning getWarnings() throws SQLException {
345                return conn.getWarnings();
346        }
347
348        @Override
349        public void clearWarnings() throws SQLException {
350                conn.clearWarnings();
351        }
352
353        @Override
354        public Map<String, Class<?>> getTypeMap() throws SQLException {
355                return conn.getTypeMap();
356        }
357
358        @Override
359        public void setTypeMap(Map<String, Class<?>> stringClassMap) throws SQLException {
360                conn.setTypeMap(stringClassMap);
361        }
362
363        @Override
364        public void setHoldability(int i) throws SQLException {
365                conn.setHoldability(i);
366        }
367
368        @Override
369        public int getHoldability() throws SQLException {
370                return conn.getHoldability();
371        }
372
373        @Override
374        public Savepoint setSavepoint() throws SQLException {
375                return conn.setSavepoint();
376        }
377
378        @Override
379        public Savepoint setSavepoint(String s) throws SQLException {
380                return conn.setSavepoint(s);
381        }
382
383        @Override
384        public void releaseSavepoint(Savepoint savepoint) throws SQLException {
385                conn.releaseSavepoint(savepoint);
386        }
387
388        @Override
389        public Clob createClob() throws SQLException {
390                return conn.createClob();
391        }
392
393        @Override
394        public Blob createBlob() throws SQLException {
395                return conn.createBlob();
396        }
397
398        @Override
399        public NClob createNClob() throws SQLException {
400                return conn.createNClob();
401        }
402
403        @Override
404        public SQLXML createSQLXML() throws SQLException {
405                return conn.createSQLXML();
406        }
407
408        @Override
409        public boolean isValid(int i) throws SQLException {
410                return conn.isValid(i);
411        }
412
413        @Override
414        public void setClientInfo(String s, String s1) throws SQLClientInfoException {
415                conn.setClientInfo(s, s1);
416        }
417
418        @Override
419        public void setClientInfo(Properties properties) throws SQLClientInfoException {
420                conn.setClientInfo(properties);
421        }
422
423        @Override
424        public String getClientInfo(String s) throws SQLException {
425                return conn.getClientInfo(s);
426        }
427
428        @Override
429        public Properties getClientInfo() throws SQLException {
430                return conn.getClientInfo();
431        }
432
433        @Override
434        public Array createArrayOf(String s, Object[] objects) throws SQLException {
435                return conn.createArrayOf(s, objects);
436        }
437
438        @Override
439        public Struct createStruct(String s, Object[] objects) throws SQLException {
440                return conn.createStruct(s, objects);
441        }
442
443    @Override
444    public void setSchema(String schema) throws SQLException {
445        conn.setSchema(schema);
446    }
447
448    @Override
449    public String getSchema() throws SQLException {
450        return conn.getSchema();
451    }
452
453    @Override
454    public void abort(Executor executor) throws SQLException {
455        conn.abort(executor);
456    }
457
458    @Override
459    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
460        conn.setNetworkTimeout(executor, milliseconds);
461    }
462
463    @Override
464    public int getNetworkTimeout() throws SQLException {
465        return conn.getNetworkTimeout();
466    }
467
468    @Override
469        public <T> T unwrap(Class<T> iface) throws SQLException {
470                return wrapperSupport.unwrap(iface);
471        }
472
473        @Override
474        public boolean isWrapperFor(Class<?> iface) throws SQLException {
475                return wrapperSupport.isWrapperFor(iface);
476        }
477}