KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > proxool > AbstractProxyStatement


1 /*
2  * This software is released under a licence similar to the Apache Software Licence.
3  * See org.logicalcobwebs.proxool.package.html for details.
4  * The latest version is available at http://proxool.sourceforge.net
5  */

6 package org.logicalcobwebs.proxool;
7
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10
11 import java.sql.SQLException JavaDoc;
12 import java.sql.Statement JavaDoc;
13 import java.sql.Connection JavaDoc;
14 import java.util.*;
15 import java.text.DateFormat JavaDoc;
16 import java.text.SimpleDateFormat JavaDoc;
17
18 /**
19  * Contains most of the functionality that we require to manipilate the
20  * statement. The subclass of this defines how we delegate to the
21  * real statement.
22  * @version $Revision: 1.22 $, $Date: 2006/03/03 09:58:26 $
23  * @author bill
24  * @author $Author: billhorsman $ (current maintainer)
25  * @since Proxool 0.7
26  */

27 abstract class AbstractProxyStatement {
28
29     private static final Log LOG = LogFactory.getLog(ProxyStatement.class);
30
31     private static final DateFormat JavaDoc DATE_FORMAT = new SimpleDateFormat JavaDoc("dd-MMM-yyyy.HH:mm:ss");
32
33     private Statement JavaDoc statement;
34
35     private ConnectionPool connectionPool;
36
37     private ProxyConnectionIF proxyConnection;
38
39     private Map parameters;
40
41     private String JavaDoc sqlStatement;
42
43     private StringBuffer JavaDoc sqlLog = new StringBuffer JavaDoc();
44
45     /**
46      * @param statement the real statement that we will delegate to
47      * @param connectionPool the connection pool that we are using
48      * @param proxyConnection the connection that was used to create the statement
49      * @param sqlStatement the SQL statement that was used to create this statement
50      * (optional, can be null) so that we can use if for tracing.
51      */

52     public AbstractProxyStatement(Statement JavaDoc statement, ConnectionPool connectionPool, ProxyConnectionIF proxyConnection, String JavaDoc sqlStatement) {
53         this.statement = statement;
54         this.connectionPool = connectionPool;
55         this.proxyConnection = proxyConnection;
56         this.sqlStatement = sqlStatement;
57     }
58
59     /**
60      * Check to see whether an exception is a fatal one. If it is, then throw the connection
61      * away (and it won't be made available again)
62      * @param t the exception to test
63      */

64     protected boolean testException(Throwable JavaDoc t) {
65         if (FatalSqlExceptionHelper.testException(connectionPool.getDefinition(), t)) {
66             // This SQL exception indicates a fatal problem with this connection. We should probably
67
// just junk it.
68
try {
69                 statement.close();
70                 connectionPool.throwConnection(proxyConnection, "Fatal SQL Exception has been detected");
71
72                 // We should check all the existing connections as soon as possible
73
HouseKeeperController.sweepNow(connectionPool.getDefinition().getAlias());
74
75                 LOG.warn("Connection has been thrown away because fatal exception was detected", t);
76             } catch (SQLException JavaDoc e2) {
77                 LOG.error("Problem trying to throw away suspect connection", e2);
78             }
79             return true;
80         } else {
81             return false;
82         }
83     }
84
85     /**
86      * Gets the real Statement that we got from the delegate driver
87      * @return delegate statement
88      */

89     public Statement JavaDoc getDelegateStatement() {
90         return statement;
91     }
92
93     /**
94      * The connection pool we are using
95      * @return connectionPool
96      */

97     protected ConnectionPool getConnectionPool() {
98         return connectionPool;
99     }
100
101     /**
102      * The real, delegate statement
103      * @return statement
104      */

105     protected Statement JavaDoc getStatement() {
106         return statement;
107     }
108
109     /**
110      * Close the statement and tell the ProxyConnection that it did so.
111      * @throws SQLException if it couldn't be closed
112      * @see ProxyConnectionIF#registerClosedStatement
113      */

114     public void close() throws SQLException JavaDoc {
115         statement.close();
116         proxyConnection.registerClosedStatement(statement);
117     }
118
119     protected Connection JavaDoc getConnection() {
120         return ProxyFactory.getWrappedConnection((ProxyConnection) proxyConnection);
121     }
122
123     /**
124      * Whether the delegate statements are the same
125      * @see Object#equals
126      */

127     public boolean equals(Object JavaDoc obj) {
128         return (statement.hashCode() == obj.hashCode());
129     }
130
131     /**
132      * Add a parameter so that we can show its value when tracing
133      * @param index within the procedure
134      * @param value an object describing its value
135      */

136     protected void putParameter(int index, Object JavaDoc value) {
137
138         // Lazily instantiate parameters if necessary
139
if (parameters == null) {
140             parameters = new TreeMap(new Comparator() {
141                 public int compare(Object JavaDoc o1, Object JavaDoc o2) {
142                     int c = 0;
143
144                     if (o1 instanceof Integer JavaDoc && o2 instanceof Integer JavaDoc) {
145                         c = ((Integer JavaDoc) o1).compareTo(((Integer JavaDoc) o2));
146                     }
147
148                     return c;
149                 }
150             });
151         }
152
153         Object JavaDoc key = new Integer JavaDoc(index);
154         if (value == null) {
155             parameters.put(key, "NULL");
156         } else if (value instanceof String JavaDoc) {
157             parameters.put(key, "'" + value + "'");
158         } else if (value instanceof Number JavaDoc) {
159             parameters.put(key, value);
160         } else if (value instanceof Boolean JavaDoc) {
161             parameters.put(key, ((Boolean JavaDoc) value).toString());
162         } else if (value instanceof Date) {
163             parameters.put(key, "'" + getDateAsString((Date) value) + "'");
164         } else {
165             String JavaDoc className = value.getClass().getName();
166             StringTokenizer st = new StringTokenizer(className, ".");
167             while (st.hasMoreTokens()) {
168                 className = st.nextToken();
169             }
170             parameters.put(key, className);
171         }
172     }
173
174     /**
175      * Trace the call that was just made
176      * @param startTime so we can log how long it took
177      * @param exception if anything went wrong during execution
178      * @throws SQLException if the {@link ConnectionPool#onExecute onExecute} method threw one.
179      */

180     protected void trace(long startTime, Exception JavaDoc exception) throws SQLException JavaDoc {
181
182         if (isTrace()) {
183             // Log if configured to
184
if (connectionPool.getLog().isDebugEnabled() && connectionPool.getDefinition().isTrace()) {
185                 connectionPool.getLog().debug(sqlLog.toString() + " (" + (System.currentTimeMillis() - startTime) + " milliseconds"
186                         + (exception != null ? ", threw a " + exception.getClass().getName() + ": " + exception.getMessage() + ")" : ")"));
187             }
188             // Send to any listener
189
connectionPool.onExecute(sqlLog.toString(), (System.currentTimeMillis() - startTime), exception);
190         }
191
192         // Clear parameters for next time
193
if (parameters != null) {
194             parameters.clear();
195         }
196         sqlStatement = null;
197         sqlLog.setLength(0);
198
199     }
200
201     protected void startExecute() {
202         if (isTrace()) {
203             ((ProxyConnection) proxyConnection).addSqlCall(sqlLog.toString());
204         }
205     }
206
207     /**
208      * Get the parameters that have been built up and use them to fill in any parameters
209      * withing the sqlStatement and produce a log. If the log already exists (for instance,
210      * if a batch is being peformed) then it is appended to the end.
211      */

212     protected void appendToSqlLog() {
213         if (sqlStatement != null && sqlStatement.length() > 0 && isTrace()) {
214             int parameterIndex = 0;
215             StringTokenizer st = new StringTokenizer(sqlStatement, "?");
216             while (st.hasMoreTokens()) {
217                 if (parameterIndex > 0) {
218                     if (parameters != null) {
219                         final Object JavaDoc value = parameters.get(new Integer JavaDoc(parameterIndex));
220                         if (value != null) {
221                             sqlLog.append(value);
222                         } else {
223                             sqlLog.append("?");
224                         }
225                     } else {
226                             sqlLog.append("?");
227                     }
228                 }
229                 parameterIndex++;
230                 sqlLog.append(st.nextToken());
231             }
232             if (sqlStatement.endsWith("?")) {
233                 if (parameterIndex > 0) {
234                     if (parameters != null) {
235                         final Object JavaDoc value = parameters.get(new Integer JavaDoc(parameterIndex));
236                         if (value != null) {
237                             sqlLog.append(value);
238                         } else {
239                             sqlLog.append("?");
240                         }
241                     } else {
242                             sqlLog.append("?");
243                     }
244                 }
245             }
246             if (sqlStatement != null && !sqlStatement.trim().endsWith(";")) {
247                 sqlLog.append("; ");
248             }
249         }
250         if (parameters != null) {
251             parameters.clear();
252         }
253     }
254
255     protected boolean isTrace() {
256         return getConnectionPool().isConnectionListenedTo() || (getConnectionPool().getDefinition().isTrace());
257     }
258
259     /**
260      * Sets sqlStatement if it isn't already set
261      * @param sqlStatement the statement we are sending the database
262      */

263     protected void setSqlStatementIfNull(String JavaDoc sqlStatement) {
264         if (this.sqlStatement == null) {
265             this.sqlStatement = sqlStatement;
266         }
267     }
268
269     protected static String JavaDoc getDateAsString(Date date) {
270         return DATE_FORMAT.format(date);
271     }
272
273 }
274
275
276 /*
277  Revision history:
278  $Log: AbstractProxyStatement.java,v $
279  Revision 1.22 2006/03/03 09:58:26 billhorsman
280  Fix for statement.getConnection(). See bug 1149834.
281
282  Revision 1.21 2006/01/18 14:40:00 billhorsman
283  Unbundled Jakarta's Commons Logging.
284
285  Revision 1.20 2005/10/07 08:25:15 billhorsman
286  Support new sqlCalls list and isTrace() is now true if the connection pool is being listened to or if trace is on. It no longer depends on the log level. This is because the sqlCalls are available in AdminServlet and not just the logs.
287
288  Revision 1.19 2005/09/26 10:01:31 billhorsman
289  Added lastSqlCall when trace is on.
290
291  Revision 1.18 2004/06/02 20:04:54 billhorsman
292  Fixed sql log: boolean and date now supported, and last parameter is included
293
294  Revision 1.17 2003/11/04 13:54:02 billhorsman
295  checkstyle
296
297  Revision 1.16 2003/10/27 12:21:59 billhorsman
298  Optimisation to avoid preparing sql log if tracing is off.
299
300  Revision 1.15 2003/10/27 11:18:42 billhorsman
301  Fix for sqlStatement being null.
302
303  Revision 1.14 2003/10/19 09:50:08 billhorsman
304  Debug exception displays class name.
305
306  Revision 1.13 2003/10/18 20:44:48 billhorsman
307  Better SQL logging (embed parameter values within SQL call) and works properly with batched statements now.
308
309  Revision 1.12 2003/09/30 18:39:07 billhorsman
310  New test-before-use, test-after-use and fatal-sql-exception-wrapper-class properties.
311
312  Revision 1.11 2003/09/05 16:26:50 billhorsman
313  testException() now returns true if a fatal exception was detected.
314
315  Revision 1.10 2003/03/10 23:43:09 billhorsman
316  reapplied checkstyle that i'd inadvertently let
317  IntelliJ change...
318
319  Revision 1.9 2003/03/10 15:26:42 billhorsman
320  refactoringn of concurrency stuff (and some import
321  optimisation)
322
323  Revision 1.8 2003/03/05 18:42:32 billhorsman
324  big refactor of prototyping and house keeping to
325  drastically reduce the number of threads when using
326  many pools
327
328  Revision 1.7 2003/03/03 11:11:56 billhorsman
329  fixed licence
330
331  Revision 1.6 2003/02/26 16:05:52 billhorsman
332  widespread changes caused by refactoring the way we
333  update and redefine pool definitions.
334
335  Revision 1.5 2003/02/19 22:38:32 billhorsman
336  fatal sql exception causes house keeper to run
337  immediately
338
339  Revision 1.4 2003/02/13 17:06:42 billhorsman
340  allow for sqlStatement in execute() method
341
342  Revision 1.3 2003/02/06 17:41:04 billhorsman
343  now uses imported logging
344
345  Revision 1.2 2003/01/28 11:47:08 billhorsman
346  new isTrace() and made close() public
347
348  Revision 1.1 2003/01/27 18:26:35 billhorsman
349  refactoring of ProxyConnection and ProxyStatement to
350  make it easier to write JDK 1.2 patch
351
352  */
Popular Tags