All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cayenne.conn.ConnectionWrapper Maven / Gradle / Ivy

There is a newer version: 2.0.4
Show newest version
/*****************************************************************
 *   Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 ****************************************************************/

package org.apache.cayenne.conn;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Map;

/**
 * ConnectionWrapper is a java.sql.Connection implementation that wraps
 * another Connection, delegating method calls to this connection. It works in conjunction
 * with PooledConnectionImpl, to generate pool events, provide limited automated
 * reconnection functionality, etc.
 * 
 * @author Andrei Adamchik
 */
public class ConnectionWrapper implements Connection {

    private Connection connection;
    private PooledConnectionImpl pooledConnection;
    private long lastReconnected;
    private int reconnectCount;

    /**
     * Fixes Sybase problems with autocommit. Used idea from Jonas
     * org.objectweb.jonas.jdbc_xa.ConnectionImpl (http://www.objectweb.org/jonas/).
     * 

* If problem is not the one that can be fixed by this patch, original exception is * rethrown. If exception occurs when fixing the problem, new exception is thrown. *

*/ static void sybaseAutoCommitPatch(Connection c, SQLException e, boolean autoCommit) throws SQLException { String s = e.getMessage().toLowerCase(); if (s.indexOf("set chained command not allowed") >= 0) { c.commit(); c.setAutoCommit(autoCommit); // Shouldn't fail now. } else { throw e; } } /** * Creates new ConnectionWrapper */ public ConnectionWrapper(Connection connection, PooledConnectionImpl pooledConnection) { this.connection = connection; this.pooledConnection = pooledConnection; } protected void reconnect(SQLException exception) throws SQLException { // if there was a relatively recent reconnect, just rethrow an error // and retire itself. THIS WILL PREVENT RECONNECT LOOPS if (reconnectCount > 0 && System.currentTimeMillis() - lastReconnected < 60000) { retire(exception); throw exception; } pooledConnection.reconnect(); // Pooled connection will wrap returned connection into // another ConnectionWrapper.... lets get the real connection // underneath... Connection connection = pooledConnection.getConnection(); if (connection instanceof ConnectionWrapper) { this.connection = ((ConnectionWrapper) connection).connection; } else { this.connection = connection; } lastReconnected = System.currentTimeMillis(); reconnectCount++; } protected void retire(SQLException exception) { // notify all the listeners.... pooledConnection.connectionErrorNotification(exception); } public void clearWarnings() throws SQLException { try { connection.clearWarnings(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public void close() throws SQLException { if (null != pooledConnection) { pooledConnection.returnConnectionToThePool(); } connection = null; pooledConnection = null; } public void commit() throws SQLException { try { connection.commit(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public Statement createStatement() throws SQLException { try { return connection.createStatement(); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return createStatement(); } } public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { try { return connection.createStatement(resultSetType, resultSetConcurrency); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return createStatement(resultSetType, resultSetConcurrency); } } public boolean getAutoCommit() throws SQLException { try { return connection.getAutoCommit(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public String getCatalog() throws SQLException { try { return connection.getCatalog(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public DatabaseMetaData getMetaData() throws SQLException { try { return connection.getMetaData(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public int getTransactionIsolation() throws SQLException { try { return connection.getTransactionIsolation(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public SQLWarning getWarnings() throws SQLException { try { return connection.getWarnings(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public boolean isClosed() throws SQLException { if (connection != null) { try { return connection.isClosed(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } else return true; } public boolean isReadOnly() throws SQLException { try { return connection.isReadOnly(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public String nativeSQL(String sql) throws SQLException { try { return connection.nativeSQL(sql); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public CallableStatement prepareCall(String sql) throws SQLException { try { return connection.prepareCall(sql); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return prepareCall(sql); } } public CallableStatement prepareCall( String sql, int resultSetType, int resultSetConcurrency) throws SQLException { try { return connection.prepareCall(sql, resultSetType, resultSetConcurrency); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return prepareCall(sql, resultSetType, resultSetConcurrency); } } public PreparedStatement prepareStatement(String sql) throws SQLException { try { return connection.prepareStatement(sql); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return prepareStatement(sql); } } public PreparedStatement prepareStatement( String sql, int resultSetType, int resultSetConcurrency) throws SQLException { try { return connection.prepareStatement(sql, resultSetType, resultSetConcurrency); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return prepareStatement(sql, resultSetType, resultSetConcurrency); } } public void rollback() throws SQLException { try { connection.rollback(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public void setAutoCommit(boolean autoCommit) throws SQLException { try { connection.setAutoCommit(autoCommit); } catch (SQLException sqlEx) { try { // apply Sybase patch sybaseAutoCommitPatch(connection, sqlEx, autoCommit); } catch (SQLException patchEx) { retire(sqlEx); throw sqlEx; } } } public void setCatalog(String catalog) throws SQLException { try { connection.setCatalog(catalog); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public void setReadOnly(boolean readOnly) throws SQLException { try { connection.setReadOnly(readOnly); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public void setTransactionIsolation(int level) throws SQLException { try { connection.setTransactionIsolation(level); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public Map getTypeMap() throws SQLException { try { return connection.getTypeMap(); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public void setTypeMap(Map map) throws SQLException { try { connection.setTypeMap(map); } catch (SQLException sqlEx) { retire(sqlEx); throw sqlEx; } } public void setHoldability(int holdability) throws SQLException { throw new java.lang.UnsupportedOperationException( "Method setHoldability() not yet implemented."); } public int getHoldability() throws SQLException { throw new java.lang.UnsupportedOperationException( "Method getHoldability() not yet implemented."); } public Savepoint setSavepoint() throws SQLException { throw new java.lang.UnsupportedOperationException( "Method setSavepoint() not yet implemented."); } public Savepoint setSavepoint(String name) throws SQLException { throw new java.lang.UnsupportedOperationException( "Method setSavepoint() not yet implemented."); } public void rollback(Savepoint savepoint) throws SQLException { throw new java.lang.UnsupportedOperationException( "Method rollback() not yet implemented."); } public void releaseSavepoint(Savepoint savepoint) throws SQLException { throw new java.lang.UnsupportedOperationException( "Method releaseSavepoint() not yet implemented."); } public Statement createStatement( int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { throw new java.lang.UnsupportedOperationException( "Method createStatement() not yet implemented."); } public PreparedStatement prepareStatement( String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { throw new java.lang.UnsupportedOperationException( "Method prepareStatement() not yet implemented."); } public CallableStatement prepareCall( String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { try { return connection.prepareCall( sql, resultSetType, resultSetConcurrency, resultSetHoldability); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return prepareCall( sql, resultSetType, resultSetConcurrency, resultSetHoldability); } } public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { try { return connection.prepareStatement(sql, autoGeneratedKeys); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return prepareStatement(sql, autoGeneratedKeys); } } public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { try { return connection.prepareStatement(sql, columnIndexes); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return prepareStatement(sql, columnIndexes); } } public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { try { return connection.prepareStatement(sql, columnNames); } catch (SQLException sqlEx) { // reconnect has code to prevent loops reconnect(sqlEx); return prepareStatement(sql, columnNames); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy