📄 c3p0pooledconnection.java
字号:
} } return okay; } void ensureOkay() throws SQLException { if (physicalConnection == null) throw new SQLException( invalidatingException == null ? "Connection is closed or broken." : "Connection is broken. Invalidating Exception: " + invalidatingException.toString()); } 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; } private SQLException cleanupUncachedActiveStatements() { //System.err.println("IN uncachedActiveStatements.size(): " + uncachedActiveStatements.size()); boolean okay = closeAndRemoveResourcesInSet(uncachedActiveStatements, STMT_CLOSE_METHOD); //System.err.println("OUT uncachedActiveStatements.size(): " + uncachedActiveStatements.size()); if (okay) return null; else return new SQLException("An exception occurred while trying to " + "clean up orphaned resources."); } ProxyConnection createProxyConnection() throws Exception { // we should always have a separate handler for each proxy connection, so // that object methods behave as expected... the handler covers // all object methods on behalf of the proxy. InvocationHandler handler = new ProxyConnectionInvocationHandler(); return (ProxyConnection) CON_PROXY_CTOR.newInstance( new Object[] {handler} ); } Statement createProxyStatement( Statement innerStmt ) throws Exception { return this.createProxyStatement( false, innerStmt ); } private static class StatementProxyingSetManagedResultSet extends SetManagedResultSet { private Statement proxyStatement; StatementProxyingSetManagedResultSet(Set activeResultSets) { super( activeResultSets ); } public void setProxyStatement( Statement proxyStatement ) { this.proxyStatement = proxyStatement; } public Statement getStatement() throws SQLException { return (proxyStatement == null ? super.getStatement() : proxyStatement); } } /* * 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 ); } } final class ProxyConnectionInvocationHandler implements InvocationHandler { //MT: ThreadSafe, but reassigned -- protected by this' lock Connection activeConnection = physicalConnection; DatabaseMetaData metaData = null; boolean connection_error_signaled = false; /* * contains all unclosed ResultSets derived from this Connection's metadata * associated with the physical connection * * MT: protected by this' lock */ final Set activeMetaDataResultSets = new HashSet(); //being careful with doRawConnectionOperation //we initialize lazily, because this will be very rarely used Set doRawResultSets = null; boolean txn_known_resolved = true; public String toString() { return "C3P0ProxyConnection [Invocation Handler: " + super.toString() + ']'; } private Object doRawConnectionOperation(Method m, Object target, Object[] args) throws IllegalAccessException, InvocationTargetException, SQLException, Exception { if (activeConnection == null) throw new SQLException("Connection previously closed. You cannot operate on a closed Connection."); if (target == C3P0ProxyConnection.RAW_CONNECTION) target = activeConnection; for (int i = 0, len = args.length; i < len; ++i) if (args[i] == C3P0ProxyConnection.RAW_CONNECTION) args[i] = activeConnection; Object out = m.invoke(target, args); // we never cache Statements generated by an operation on the raw Connection if (out instanceof Statement) out = createProxyStatement( false, (Statement) out ); else if (out instanceof ResultSet) { if (doRawResultSets == null) doRawResultSets = new HashSet(); out = new NullStatementSetManagedResultSet( (ResultSet) out, doRawResultSets ); } return out; } public synchronized Object invoke(Object proxy, Method m, Object[] args) throws Throwable { if ( OBJECT_METHODS.contains( m ) ) return m.invoke( this, args ); try { String mname = m.getName(); if (activeConnection != null) { if (mname.equals("rawConnectionOperation")) { ensureOkay(); txn_known_resolved = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -