/****************************************************************************** * Copyright (C) 2008 Low Heng Sin * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ package org.compiere.db; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Date; import java.util.logging.Level; import javax.sql.RowSet; import org.adempiere.exceptions.DBException; import org.compiere.model.SystemProperties; import org.compiere.util.CCachedRowSet; import org.compiere.util.CLogger; import org.compiere.util.CStatementVO; import org.compiere.util.DB; import org.compiere.util.DisplayType; import org.compiere.util.Trx; import org.idempiere.db.util.AutoCommitConnectionBroker; /** * Dynamic proxy for the CStatement interface * @author Low Heng Sin */ public class StatementProxy implements InvocationHandler { protected Connection m_conn = null; private boolean close = false; /** Logger */ protected transient CLogger log = CLogger.getCLogger (getClass()); /** Used if local */ protected transient Statement p_stmt = null; /** Value Object */ protected CStatementVO p_vo = null; /** * @param resultSetType * @param resultSetConcurrency * @param trxName */ public StatementProxy(int resultSetType, int resultSetConcurrency, String trxName) { p_vo = new CStatementVO (resultSetType, resultSetConcurrency); p_vo.setTrxName(trxName); init(); } /** * @param vo */ public StatementProxy(CStatementVO vo) { p_vo = vo; init(); } //for subclass protected StatementProxy() {} @Override public Object invoke(Object obj, Method method, Object[] args) throws Throwable { String name = method.getName(); //handle special case if (name.equals("executeQuery") || name.equals("executeUpdate") || name.equals("execute") || name.equals("addBatch")) { if (args != null && args.length > 0 && args[0] != null && args[0] instanceof String) { String sql = (String)args[0]; p_vo.setSql(DB.getDatabase().convertStatement(sql)); args[0] = p_vo.getSql(); } } else if (name.equals("close") && (args == null || args.length == 0)) { close(); return null; } else if (name.equals("getRowSet") && (args == null || args.length == 0)) { return getRowSet(); } else if (name.equals("isClosed") && (args == null || args.length == 0)) { return close; } else if (name.equals("finalize") && (args == null || args.length == 0)) { if (p_stmt != null && !close) { this.close(); } return null; } else if (name.equals("commit") && (args == null || args.length == 0)) { commit(); return null; } else if (name.equals("getSql") && (args == null || args.length == 0)) { return getSql(); } else if (name.equals("equals") && (args != null && args.length == 1)) { return equals(args[0]); } String logSql = null; String logOperation = null; if (log.isLoggable(Level.FINE) && getSql() != null) { if (name.equals("executeUpdate") || name.equals("execute")) { logSql = getSql().toUpperCase(); if (logSql.startsWith("UPDATE ")) { logSql = logSql.substring("UPDATE ".length()).trim(); logOperation = "Update"; } else if (logSql.startsWith("INSERT INTO ")) { logSql = logSql.substring("INSERT INTO ".length()).trim(); logOperation = "Insert"; } else if (logSql.startsWith("DELETE FROM ")) { logSql = logSql.substring("DELETE FROM ".length()).trim(); logOperation = "Delete"; } if (logOperation != null) { int idxspace = logSql.indexOf(' '); if (idxspace > 0) logSql = logSql.substring(0, logSql.indexOf(' ')); if (log.isLoggable(Level.FINE)) log.fine((DisplayType.getDateFormat(DisplayType.DateTime)).format(new Date(System.currentTimeMillis()))+","+logOperation+","+logSql+","+(p_vo.getTrxName() != null ? p_vo.getTrxName() : "")+" (begin)"); } } } Method m = p_stmt.getClass().getMethod(name, method.getParameterTypes()); String nullTrxName = null; try { if (SystemProperties.isTraceNullTrxConnection() && p_vo.getTrxName() == null) nullTrxName = Trx.registerNullTrx(); return m.invoke(p_stmt, args); } catch (InvocationTargetException e) { throw DB.getSQLException(e); } finally { if (nullTrxName != null && p_vo.getTrxName() == null) Trx.unregisterNullTrx(nullTrxName); if (log.isLoggable(Level.FINE) && logSql != null && logOperation != null) { log.fine((DisplayType.getDateFormat(DisplayType.DateTime)).format(new Date(System.currentTimeMillis()))+","+logOperation+","+logSql+","+(p_vo.getTrxName() != null ? p_vo.getTrxName() : "")+" (end)"); } } } /** * Initialise the statement wrapper object */ protected void init() { try { Connection conn = null; Trx trx = p_vo.getTrxName() == null ? null : Trx.get(p_vo.getTrxName(), false); if (trx != null) { conn = trx.getConnection(); } else { m_conn = AutoCommitConnectionBroker.getConnection(); conn = m_conn; } if (conn == null) throw new DBException("No Connection"); p_stmt = conn.createStatement(p_vo.getResultSetType(), p_vo.getResultSetConcurrency()); } catch (SQLException e) { log.log(Level.SEVERE, "CStatement", e); throw new DBException(e); } } /** * Close * @throws SQLException * @see java.sql.Statement#close() */ protected void close () throws SQLException { if (close) return; try { DB.close(p_stmt); } finally { if (m_conn != null) { AutoCommitConnectionBroker.releaseConnection(m_conn); } m_conn = null; p_stmt = null; close = true; } } // close /** * Execute the wrapped statement and return row set * @return RowSet * @throws SQLException * @see java.sql.PreparedStatement#executeQuery() */ protected RowSet getRowSet() { if (log.isLoggable(Level.FINEST)) log.finest("getRowSet"); RowSet rowSet = null; ResultSet rs = null; try { rs = p_stmt.executeQuery(p_vo.getSql()); rowSet = CCachedRowSet.getRowSet(rs); } catch (Exception ex) { log.log(Level.SEVERE, p_vo.toString(), ex); throw new RuntimeException (ex); } finally { DB.close(rs); rs = null; DB.close(rowSet); rowSet = null; } return rowSet; } // getRowSet /** * Commit (if local trx) * @throws SQLException */ private void commit() throws SQLException { if (m_conn != null && !m_conn.getAutoCommit()) { m_conn.commit(); } } // commit /** * Get Sql * @return sql */ public String getSql() { if (p_vo != null) return p_vo.getSql(); return null; } // getSql }