1 /************************************************************************
2 * Copyright (c) 2000-2006 The Apache Software Foundation. *
3 * All rights reserved. *
4 * ------------------------------------------------------------------- *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you *
6 * may not use this file except in compliance with the License. You *
7 * may obtain a copy of the License at: *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14 * implied. See the License for the specific language governing *
15 * permissions and limitations under the License. *
16 ***********************************************************************/
17
18 package org.apache.james.util.mordred;
19
20 import java.io.PrintWriter;
21 import java.io.StringWriter;
22 import java.sql.CallableStatement;
23 import java.sql.Connection;
24 import java.sql.DatabaseMetaData;
25 import java.sql.PreparedStatement;
26 import java.sql.SQLException;
27 import java.sql.SQLWarning;
28 import java.sql.Statement;
29 import java.util.Map;
30
31 /***
32 * An entry in a connection pool.
33 *
34 */
35 public class PoolConnEntry implements java.sql.Connection{
36 private static final boolean DEEP_DEBUG = false;
37
38
39 public final static int AVAILABLE = 0;
40 public final static int ACTIVE = 1;
41
42 private JdbcDataSource container;
43
44 private Connection connection;
45 private int status;
46 private long lockTime;
47 private long createDate;
48 private long lastActivity;
49 private int id;
50 private java.lang.Throwable trace;
51
52 /***
53 * Insert the method's description here.
54 * Creation date: (8/24/99 11:43:45 AM)
55 * @param conn java.sql.Connection
56 */
57 public PoolConnEntry(JdbcDataSource container, Connection conn, int id) {
58 this.container = container;
59 this.connection = conn;
60 status = AVAILABLE;
61 createDate = System.currentTimeMillis();
62 lastActivity = System.currentTimeMillis();
63 this.id = id;
64 }
65
66 /***
67 * Locks an entry for anybody else using it
68 */
69 public synchronized boolean lock() throws SQLException {
70 if (DEEP_DEBUG) {
71 System.out.println("Trying to lock");
72 }
73
74 if (status != PoolConnEntry.AVAILABLE) {
75 return false;
76 }
77
78 if (DEEP_DEBUG) {
79 System.out.println("Available");
80 }
81
82 if (false) {
83
84
85
86 if (connection.isClosed()) {
87 throw new SQLException("Connection has been closed.");
88 }
89
90 if (DEEP_DEBUG) {
91 System.out.println("not closed");
92 }
93 }
94
95
96 status = PoolConnEntry.ACTIVE;
97 lockTime = System.currentTimeMillis();
98 lastActivity = lockTime;
99 trace = new Throwable();
100 clearWarnings();
101 if (DEEP_DEBUG) {
102 System.out.println("Returning");
103 }
104 return true;
105 }
106
107 /***
108 * Resets flags on an entry for reuse in the pool
109 */
110 public synchronized void unlock() {
111 lastActivity = System.currentTimeMillis();
112 trace = null;
113 status = AVAILABLE;
114 }
115
116 /***
117 * Simple method to log any warnings on an entry (connection), and
118 * then clear them.
119 * @throws java.sql.SQLException
120 */
121 public void clearWarnings() {
122 try {
123 SQLWarning currSQLWarning = connection.getWarnings();
124 while (currSQLWarning != null) {
125 StringBuffer logBuffer =
126 new StringBuffer(256)
127 .append("Warnings on connection ")
128 .append(id)
129 .append(currSQLWarning);
130 container.debug(logBuffer.toString());
131 currSQLWarning = currSQLWarning.getNextWarning();
132 }
133 connection.clearWarnings();
134 } catch (SQLException sqle) {
135 container.debug("Error while clearing exceptions on " + id);
136
137 }
138 }
139
140
141 /***
142 * Insert the method's description here.
143 * Creation date: (8/24/99 11:43:19 AM)
144 * @return a long representing the time this entry was created
145 */
146 public long getCreateDate() {
147 return createDate;
148 }
149
150 /***
151 * Insert the method's description here.
152 * Creation date: (8/24/99 12:09:01 PM)
153 * @return int
154 */
155 public int getId() {
156 return id;
157 }
158
159 /***
160 * Insert the method's description here.
161 * Creation date: (8/24/99 11:43:19 AM)
162 * @return long
163 */
164 public long getLastActivity() {
165 return lastActivity;
166 }
167
168 /***
169 * Insert the method's description here.
170 * Creation date: (8/24/99 11:43:19 AM)
171 * @return long
172 */
173 public long getLockTime() {
174 return lockTime;
175 }
176
177 /***
178 * Insert the method's description here.
179 * Creation date: (8/24/99 11:43:19 AM)
180 * @return int
181 */
182 public int getStatus() {
183 return status;
184 }
185
186 /***
187 * Insert the method's description here.
188 * Creation date: (8/24/99 2:33:38 PM)
189 * @return java.lang.Throwable
190 */
191 public java.lang.Throwable getTrace() {
192 return trace;
193 }
194
195 /***
196 * Need to clean up the connection
197 */
198 protected void finalize() {
199 container.debug("Closing connection " + id);
200 try {
201 connection.close();
202 } catch (SQLException ex) {
203 StringBuffer warnBuffer =
204 new StringBuffer(64)
205 .append("Cannot close connection ")
206 .append(id)
207 .append(" on finalize");
208 container.warn(warnBuffer.toString());
209 }
210
211 if (getTrace() != null) {
212 StringWriter sout = new StringWriter();
213 trace.printStackTrace(new PrintWriter(sout, true));
214 container.info(sout.toString());
215 }
216 }
217
218 public String getString() {
219 StringBuffer poolConnStringBuffer =
220 new StringBuffer(64)
221 .append(getId())
222 .append(": ")
223 .append(connection.toString());
224 return poolConnStringBuffer.toString();
225 }
226
227
228
229
230
231
232
233
234
235
236
237 public void close() throws SQLException {
238 clearWarnings();
239 container.releaseConnection(this);
240 }
241
242 /***
243 * Returns whether this entry is closed.
244 *
245 * @return whether the underlying conntection is closed
246 */
247 public boolean isClosed() throws SQLException {
248 return connection.isClosed();
249 }
250
251
252 public final Statement createStatement() throws SQLException {
253 return connection.createStatement();
254 }
255
256 public final PreparedStatement prepareStatement(final String sql) throws SQLException {
257 return connection.prepareStatement(sql);
258 }
259
260 public final CallableStatement prepareCall(final String sql) throws SQLException {
261 return connection.prepareCall(sql);
262 }
263
264 public final String nativeSQL(final String sql) throws SQLException {
265 return connection.nativeSQL( sql );
266 }
267
268 public final void setAutoCommit(final boolean autoCommit) throws SQLException {
269 connection.setAutoCommit( autoCommit );
270 }
271
272 public final boolean getAutoCommit() throws SQLException {
273 return connection.getAutoCommit();
274 }
275
276 public final void commit() throws SQLException {
277 connection.commit();
278 }
279
280 public final void rollback() throws SQLException {
281 connection.rollback();
282 }
283
284 public final DatabaseMetaData getMetaData() throws SQLException {
285 return connection.getMetaData();
286 }
287
288 public final void setReadOnly( final boolean readOnly ) throws SQLException {
289 connection.setReadOnly( readOnly );
290 }
291
292 public final boolean isReadOnly() throws SQLException {
293 return connection.isReadOnly();
294 }
295
296 public final void setCatalog( final String catalog ) throws SQLException {
297 connection.setCatalog( catalog );
298 }
299
300 public final String getCatalog() throws SQLException {
301 return connection.getCatalog();
302 }
303
304 public final void setTransactionIsolation( final int level ) throws SQLException {
305 connection.setTransactionIsolation(level);
306 }
307
308 public final int getTransactionIsolation() throws SQLException {
309 return connection.getTransactionIsolation();
310 }
311
312 public final SQLWarning getWarnings() throws SQLException {
313 return connection.getWarnings();
314 }
315
316 public final Statement createStatement( final int resultSetType,
317 final int resultSetConcurrency )
318 throws SQLException {
319 return connection.createStatement(resultSetType, resultSetConcurrency);
320 }
321
322 public final PreparedStatement prepareStatement( final String sql,
323 final int resultSetType,
324 final int resultSetConcurrency )
325 throws SQLException {
326 return connection.prepareStatement( sql, resultSetType, resultSetConcurrency);
327 }
328
329 public final CallableStatement prepareCall( final String sql,
330 final int resultSetType,
331 final int resultSetConcurrency )
332 throws SQLException {
333 return connection.prepareCall( sql, resultSetType, resultSetConcurrency );
334 }
335
336 public final Map getTypeMap() throws SQLException {
337 return connection.getTypeMap();
338 }
339
340 public final void setTypeMap( final Map map ) throws SQLException {
341 connection.setTypeMap( map );
342 }
343
344
345 public final void setHoldability(int holdability)
346 throws SQLException
347 {
348 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
349 }
350
351 public final int getHoldability()
352 throws SQLException
353 {
354 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
355 }
356
357 public final java.sql.Savepoint setSavepoint()
358 throws SQLException
359 {
360 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
361 }
362
363 public final java.sql.Savepoint setSavepoint(String savepoint)
364 throws SQLException
365 {
366 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
367 }
368
369 public final void rollback(java.sql.Savepoint savepoint)
370 throws SQLException
371 {
372 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
373 }
374
375 public final void releaseSavepoint(java.sql.Savepoint savepoint)
376 throws SQLException
377 {
378 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
379 }
380
381 public final Statement createStatement(int resulSetType,
382 int resultSetConcurrency,
383 int resultSetHoldability)
384 throws SQLException
385 {
386 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
387 }
388
389 public final PreparedStatement prepareStatement(String sql,
390 int resulSetType,
391 int resultSetConcurrency,
392 int resultSetHoldability)
393 throws SQLException
394 {
395 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
396 }
397
398 public final CallableStatement prepareCall(String sql,
399 int resulSetType,
400 int resultSetConcurrency,
401 int resultSetHoldability)
402 throws SQLException
403 {
404 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
405 }
406
407 public final PreparedStatement prepareStatement(String sql,
408 int autoGeneratedKeys)
409 throws SQLException
410 {
411 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
412 }
413
414 public final PreparedStatement prepareStatement(String sql,
415 int[] columnIndexes)
416 throws SQLException
417 {
418 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
419 }
420
421 public final PreparedStatement prepareStatement(String sql,
422 String[] columnNames)
423 throws SQLException
424 {
425 throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
426 }
427
428
429 }