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