public void addStatementEventListener(StatementEventListener sel) { if (logger.isLoggable(MLevel.INFO)) logger.info( "Per the JDBC4 spec, " + this.getClass().getName() + " accepts StatementListeners, but for now there is no circumstance under which they are notified!"); ses.addStatementEventListener(sel); }
boolean closeAndRemoveResourcesInSet(Set s, Method closeMethod) { boolean okay = true; Set temp; synchronized (s) { temp = new HashSet(s); } for (Iterator ii = temp.iterator(); ii.hasNext(); ) { Object rsrc = ii.next(); try { closeMethod.invoke(rsrc, CLOSE_ARGS); } catch (Exception e) { Throwable t = e; if (t instanceof InvocationTargetException) t = ((InvocationTargetException) e).getTargetException(); logger.log(MLevel.WARNING, "An exception occurred while cleaning up a resource.", t); // t.printStackTrace(); okay = false; } finally { s.remove(rsrc); } } // We had to abandon the idea of simply iterating over s directly, because // our resource close methods sometimes try to remove the resource from // its parent Set. This is important (when the user closes the resources // directly), but leads to ConcurrenModificationExceptions while we are // iterating over the Set to close. So, now we iterate over a copy, but remove // from the original Set. Since removal is idempotent, it don't matter if // the close method already provoked a remove. Sucks that we have to copy // the set though. // // Original (direct iteration) version: // // synchronized (s) // { // for (Iterator ii = s.iterator(); ii.hasNext(); ) // { // Object rsrc = ii.next(); // try // { closeMethod.invoke(rsrc, CLOSE_ARGS); } // catch (Exception e) // { // Throwable t = e; // if (t instanceof InvocationTargetException) // t = ((InvocationTargetException) e).getTargetException(); // t.printStackTrace(); // okay = false; // } // finally // { ii.remove(); } // } // } return okay; }
synchronized void closeMaybeCheckedOut(boolean checked_out) throws SQLException { if (checked_out) { // reset transaction state try { C3P0ImplUtils.resetTxnState( physicalConnection, forceIgnoreUnresolvedTransactions, autoCommitOnClose, false); } catch (Exception e) { if (logger.isLoggable(MLevel.FINER)) logger.log( MLevel.FINER, "Failed to reset the transaction state of " + physicalConnection + "just prior to close(). " + "Only relevant at all if this was a Connection being forced close()ed midtransaction.", e); } } close(false); }
private void reset(boolean known_resolved_txn) throws SQLException { ensureOkay(); C3P0ImplUtils.resetTxnState( physicalConnection, forceIgnoreUnresolvedTransactions, autoCommitOnClose, known_resolved_txn); if (isolation_lvl_nondefault) { physicalConnection.setTransactionIsolation(dflt_txn_isolation); isolation_lvl_nondefault = false; } if (catalog_nondefault) { physicalConnection.setCatalog(dflt_catalog); catalog_nondefault = false; } if (holdability_nondefault) // we don't test if holdability is supported, 'cuz it can never go // nondefault if it's not. { physicalConnection.setHoldability(dflt_holdability); holdability_nondefault = false; } try { physicalConnection.setReadOnly(false); } catch (Throwable t) { if (logger.isLoggable(MLevel.FINE)) logger.log( MLevel.FINE, "A Throwable occurred while trying to reset the readOnly property of our Connection to false!", t); } try { if (supports_setTypeMap) physicalConnection.setTypeMap(Collections.EMPTY_MAP); } catch (Throwable t) { if (logger.isLoggable(MLevel.FINE)) logger.log( MLevel.FINE, "A Throwable occurred while trying to reset the typeMap property of our Connection to Collections.EMPTY_MAP!", t); } }
// must be called from sync'ed method private void doBadUpdate(int new_status) { this.connection_status = new_status; try { this.close(true); } catch (SQLException e) { // System.err.print("Broken Connection Close Error: "); // e.printStackTrace(); logger.log(MLevel.WARNING, "Broken Connection Close Error. ", e); } }
boolean closeAndRemoveResultSets(Set rsSet) { boolean okay = true; synchronized (rsSet) { for (Iterator ii = rsSet.iterator(); ii.hasNext(); ) { ResultSet rs = (ResultSet) ii.next(); try { rs.close(); } catch (SQLException e) { if (Debug.DEBUG) logger.log(MLevel.WARNING, "An exception occurred while cleaning up a ResultSet.", e); // e.printStackTrace(); okay = false; } finally { ii.remove(); } } } return okay; }
// must be called from sync'ed method to protecte // exposedProxy private Connection getCreateNewConnection() throws SQLException { try { // DEBUG // origGet = new Exception("[DOUBLE_GET_TESTER] -- Orig Get"); ensureOkay(); /* * we reset the physical connection when we close an exposed proxy * no need to do it again when we create one */ // reset(); return (exposedProxy = createProxyConnection()); } catch (SQLException e) { throw e; } catch (Exception e) { // e.printStackTrace(); logger.log(MLevel.WARNING, "Failed to acquire connection!", e); throw new SQLException("Failed to acquire connection!"); } }
// synchronized to protect exposedProxy public synchronized Connection getConnection() throws SQLException { if (exposedProxy != null) { // DEBUG // System.err.println("[DOUBLE_GET_TESTER] -- double getting a Connection from " + this ); // new Exception("[DOUBLE_GET_TESTER] -- Double-Get Stack Trace").printStackTrace(); // origGet.printStackTrace(); // System.err.println("c3p0 -- Uh oh... getConnection() was called on a PooledConnection // when " + // "it had already provided a client with a Connection that has not yet been " + // "closed. This probably indicates a bug in the connection pool!!!"); logger.warning( "c3p0 -- Uh oh... getConnection() was called on a PooledConnection when " + "it had already provided a client with a Connection that has not yet been " + "closed. This probably indicates a bug in the connection pool!!!"); return exposedProxy; } else { return getCreateNewConnection(); } }
static { try { CON_PROXY_CTOR = createProxyConstructor(ProxyConnection.class); Class[] argClasses = new Class[0]; RS_CLOSE_METHOD = ResultSet.class.getMethod("close", argClasses); STMT_CLOSE_METHOD = Statement.class.getMethod("close", argClasses); CLOSE_ARGS = new Object[0]; OBJECT_METHODS = Collections.unmodifiableSet(new HashSet(Arrays.asList(Object.class.getMethods()))); } catch (Exception e) { // e.printStackTrace(); logger.log( MLevel.SEVERE, "An Exception occurred in static initializer of" + C3P0PooledConnection.class.getName(), e); throw new InternalError( "Something is very wrong, or this is a pre 1.3 JVM." + "We cannot set up dynamic proxies and/or methods!"); } }
/* * TODO: factor all this convolution out into * C3P0Statement */ Statement createProxyStatement( // final Method cachedStmtProducingMethod, // final Object[] cachedStmtProducingMethodArgs, final boolean inner_is_cached, final Statement innerStmt) throws Exception { final Set activeResultSets = Collections.synchronizedSet(new HashSet()); final Connection parentConnection = exposedProxy; if (Debug.DEBUG && parentConnection == null) { // System.err.print("PROBABLE C3P0 BUG -- "); // System.err.println(this + ": created a proxy Statement when there is no active, exposed // proxy Connection???"); logger.warning( "PROBABLE C3P0 BUG -- " + this + ": created a proxy Statement when there is no active, exposed proxy Connection???"); } // we can use this one wrapper under all circumstances // except jdbc3 CallableStatement multiple open ResultSets... // avoid object allocation in statement methods where possible. final StatementProxyingSetManagedResultSet mainResultSet = new StatementProxyingSetManagedResultSet(activeResultSets); class WrapperStatementHelper { Statement wrapperStmt; Statement nakedInner; public WrapperStatementHelper(Statement wrapperStmt, Statement nakedInner) { this.wrapperStmt = wrapperStmt; this.nakedInner = nakedInner; if (!inner_is_cached) uncachedActiveStatements.add(wrapperStmt); } private boolean closeAndRemoveActiveResultSets() { return closeAndRemoveResultSets(activeResultSets); } public ResultSet wrap(ResultSet rs) { if (mainResultSet.getInner() == null) { mainResultSet.setInner(rs); mainResultSet.setProxyStatement(wrapperStmt); return mainResultSet; } else { // for the case of multiple open ResultSets StatementProxyingSetManagedResultSet out = new StatementProxyingSetManagedResultSet(activeResultSets); out.setInner(rs); out.setProxyStatement(wrapperStmt); return out; } } public void doClose() throws SQLException { boolean okay = closeAndRemoveActiveResultSets(); if (inner_is_cached) // this statement was cached scache.checkinStatement(innerStmt); else { innerStmt.close(); uncachedActiveStatements.remove(wrapperStmt); } if (!okay) throw new SQLException("Failed to close an orphaned ResultSet properly."); } public Object doRawStatementOperation(Method m, Object target, Object[] args) throws IllegalAccessException, InvocationTargetException, SQLException { if (target == C3P0ProxyStatement.RAW_STATEMENT) target = nakedInner; for (int i = 0, len = args.length; i < len; ++i) if (args[i] == C3P0ProxyStatement.RAW_STATEMENT) args[i] = nakedInner; Object out = m.invoke(target, args); if (out instanceof ResultSet) out = wrap((ResultSet) out); return out; } } if (innerStmt instanceof CallableStatement) { class ProxyCallableStatement extends FilterCallableStatement implements C3P0ProxyStatement { WrapperStatementHelper wsh; ProxyCallableStatement(CallableStatement is) { super(is); this.wsh = new WrapperStatementHelper(this, is); } public Connection getConnection() { return parentConnection; } public ResultSet getResultSet() throws SQLException { return wsh.wrap(super.getResultSet()); } public ResultSet getGeneratedKeys() throws SQLException { return wsh.wrap(super.getGeneratedKeys()); } public ResultSet executeQuery(String sql) throws SQLException { return wsh.wrap(super.executeQuery(sql)); } public ResultSet executeQuery() throws SQLException { return wsh.wrap(super.executeQuery()); } public Object rawStatementOperation(Method m, Object target, Object[] args) throws IllegalAccessException, InvocationTargetException, SQLException { return wsh.doRawStatementOperation(m, target, args); } public void close() throws SQLException { wsh.doClose(); } } return new ProxyCallableStatement((CallableStatement) innerStmt); } else if (innerStmt instanceof PreparedStatement) { class ProxyPreparedStatement extends FilterPreparedStatement implements C3P0ProxyStatement { WrapperStatementHelper wsh; ProxyPreparedStatement(PreparedStatement ps) { super(ps); this.wsh = new WrapperStatementHelper(this, ps); } public Connection getConnection() { return parentConnection; } public ResultSet getResultSet() throws SQLException { return wsh.wrap(super.getResultSet()); } public ResultSet getGeneratedKeys() throws SQLException { return wsh.wrap(super.getGeneratedKeys()); } public ResultSet executeQuery(String sql) throws SQLException { return wsh.wrap(super.executeQuery(sql)); } public ResultSet executeQuery() throws SQLException { return wsh.wrap(super.executeQuery()); } public Object rawStatementOperation(Method m, Object target, Object[] args) throws IllegalAccessException, InvocationTargetException, SQLException { return wsh.doRawStatementOperation(m, target, args); } public void close() throws SQLException { wsh.doClose(); } } return new ProxyPreparedStatement((PreparedStatement) innerStmt); } else { class ProxyStatement extends FilterStatement implements C3P0ProxyStatement { WrapperStatementHelper wsh; ProxyStatement(Statement s) { super(s); this.wsh = new WrapperStatementHelper(this, s); } public Connection getConnection() { return parentConnection; } public ResultSet getResultSet() throws SQLException { return wsh.wrap(super.getResultSet()); } public ResultSet getGeneratedKeys() throws SQLException { return wsh.wrap(super.getGeneratedKeys()); } public ResultSet executeQuery(String sql) throws SQLException { return wsh.wrap(super.executeQuery(sql)); } public Object rawStatementOperation(Method m, Object target, Object[] args) throws IllegalAccessException, InvocationTargetException, SQLException { return wsh.doRawStatementOperation(m, target, args); } public void close() throws SQLException { wsh.doClose(); } } return new ProxyStatement(innerStmt); } }
// TODO: factor out repetitive debugging code private synchronized void close(boolean known_invalid) throws SQLException { // System.err.println("Closing " + this); if (physicalConnection != null) { try { StringBuffer debugOnlyLog = null; if (Debug.DEBUG && known_invalid) { debugOnlyLog = new StringBuffer(); debugOnlyLog.append("[ exceptions: "); } Exception exc = cleanupUncachedActiveStatements(); if (Debug.DEBUG && exc != null) { if (known_invalid) debugOnlyLog.append(exc.toString() + ' '); else logger.log( MLevel.WARNING, "An exception occurred while cleaning up uncached active Statements.", exc); // exc.printStackTrace(); } try { // we've got to use silentClose() rather than close() here, // 'cuz if there's still an exposedProxy (say a user forgot to // close his Connection) before we close, and we use regular (loud) // close, we will try to check this dead or dying PooledConnection // back into the pool. We only want to do this when close is called // on user proxies, and the underlying PooledConnection might still // be good. The PooledConnection itself should only be closed by the // pool. if (exposedProxy != null) exposedProxy.silentClose(known_invalid); } catch (Exception e) { if (Debug.DEBUG) { if (known_invalid) debugOnlyLog.append(e.toString() + ' '); else logger.log(MLevel.WARNING, "An exception occurred.", exc); // e.printStackTrace(); } exc = e; } try { this.closeAll(); } catch (Exception e) { if (Debug.DEBUG) { if (known_invalid) debugOnlyLog.append(e.toString() + ' '); else logger.log(MLevel.WARNING, "An exception occurred.", exc); // e.printStackTrace(); } exc = e; } try { physicalConnection.close(); } catch (Exception e) { if (Debug.DEBUG) { if (known_invalid) debugOnlyLog.append(e.toString() + ' '); else logger.log(MLevel.WARNING, "An exception occurred.", exc); e.printStackTrace(); } exc = e; } if (exc != null) { if (known_invalid) { debugOnlyLog.append(" ]"); if (Debug.DEBUG) { // System.err.print("[DEBUG]" + this + ": while closing a PooledConnection known // to be invalid, "); // System.err.println(" some exceptions occurred. This is probably not a // problem:"); // System.err.println( debugOnlyLog.toString() ); logger.fine( this + ": while closing a PooledConnection known to be invalid, " + " some exceptions occurred. This is probably not a problem: " + debugOnlyLog.toString()); } } else throw new SQLException( "At least one error occurred while attempting " + "to close() the PooledConnection: " + exc); } if (Debug.TRACE == Debug.TRACE_MAX) logger.fine("C3P0PooledConnection closed. [" + this + ']'); // System.err.println("C3P0PooledConnection closed. [" + this + ']'); } finally { physicalConnection = null; } } }